LCOV - code coverage report
Current view: top level - vm/jit - builtin.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 262 346 75.7 %
Date: 2015-06-10 18:10:59 Functions: 40 47 85.1 %

          Line data    Source code
       1             : /* src/vm/jit/builtin.cpp - functions for unsupported operations
       2             : 
       3             :    Copyright (C) 1996-2014
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             : 
       6             :    This file is part of CACAO.
       7             : 
       8             :    This program is free software; you can redistribute it and/or
       9             :    modify it under the terms of the GNU General Public License as
      10             :    published by the Free Software Foundation; either version 2, or (at
      11             :    your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful, but
      14             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :    General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program; if not, write to the Free Software
      20             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      21             :    02110-1301, USA.
      22             : 
      23             :    Contains C functions for JavaVM Instructions that cannot be
      24             :    translated to machine language directly. Consequently, the
      25             :    generated machine code for these instructions contains function
      26             :    calls instead of machine instructions, using the C calling
      27             :    convention.
      28             : 
      29             : */
      30             : 
      31             : #include "vm/jit/builtin.hpp"
      32             : #include "config.h"
      33             : 
      34             : #include <cassert>
      35             : #include <cerrno>                       // for errno
      36             : #include <cstddef>                      // for size_t
      37             : #include <cstdlib>                      // for qsort
      38             : #include <cstring>                      // for strerror
      39             : #include <stdint.h>                     // for uint32_t
      40             : #include <sys/time.h>                   // for timeval, gettimeofday
      41             : 
      42             : //#include "arch.hpp"
      43             : //#include "md-abi.hpp"
      44             : 
      45             : #include "mm/dumpmemory.hpp"            // for DumpMemoryArea
      46             : #include "mm/gc.hpp"                    // for heap_alloc
      47             : 
      48             : #include "threads/lockword.hpp"         // for Lockword
      49             : //#include "threads/lock.hpp"
      50             : //#include "threads/mutex.hpp"
      51             : 
      52             : #include "toolbox/logging.hpp"          // for log_message_class
      53             : 
      54             : #include "vm/array.hpp"                 // for ObjectArray, Array, etc
      55             : #include "vm/class.hpp"                 // for classinfo, etc
      56             : #include "vm/cycles-stats.hpp"
      57             : #include "vm/descriptor.hpp"            // for descriptor_pool
      58             : #include "vm/exceptions.hpp"
      59             : #include "vm/global.hpp"                // for java_handle_t, etc
      60             : #include "vm/globals.hpp"               // for class_java_lang_Cloneable, etc
      61             : #include "vm/initialize.hpp"            // for initialize_class
      62             : #include "vm/linker.hpp"                // for arraydescriptor, link_class
      63             : #include "vm/method.hpp"                // for method_new_builtin, etc
      64             : #include "vm/options.hpp"               // for initverbose, etc
      65             : #include "vm/references.hpp"            // for constant_FMIref
      66             : #include "vm/rt-timing.hpp"
      67             : #include "vm/types.hpp"                 // for s4, s8, u1, u4
      68             : #include "vm/vftbl.hpp"                 // for vftbl_t
      69             : #include "vm/vm.hpp"                    // for vm_abort
      70             : 
      71             : #include "vm/jit/emit-common.hpp"
      72             : #include "vm/jit/stubs.hpp"             // for BuiltinStub
      73             : #include "vm/jit/trace.hpp"             // for trace_exception_builtin
      74             : 
      75             : #include "vm/jit/ir/icmd.hpp"           // for ::ICMD_INVOKESTATIC
      76             : #include "vm/jit/ir/instruction.hpp"    // for instruction, etc
      77             : 
      78             : #include "fdlibm/fdlibm.h"              // for finite, copysign, fmod
      79             : #if defined(__CYGWIN__) && defined(Bias)
      80             : # undef Bias
      81             : #endif
      82             : 
      83             : using namespace cacao;
      84             : 
      85             : /* float versions are not defined in GNU classpath's fdlibm */
      86             : 
      87             : #define copysignf    copysign
      88             : #define finitef      finite
      89             : #define fmodf        fmod
      90             : #define isnanf       isnan
      91             : 
      92             : 
      93             : /* include builtin tables *****************************************************/
      94             : 
      95             : #include "vm/jit/builtintable.inc"
      96             : 
      97             : 
      98             : CYCLES_STATS_DECLARE(builtin_new         ,100,5)
      99             : CYCLES_STATS_DECLARE(builtin_overhead    , 80,1)
     100             : 
     101             : 
     102             : /*============================================================================*/
     103             : /* BUILTIN TABLE MANAGEMENT FUNCTIONS                                         */
     104             : /*============================================================================*/
     105             : 
     106             : /* builtintable_init ***********************************************************
     107             : 
     108             :    Parse the descriptors of builtin functions and create the parsed
     109             :    descriptors.
     110             : 
     111             : *******************************************************************************/
     112             : 
     113         163 : static bool builtintable_init(void)
     114             : {
     115             :         // Create new dump memory area.
     116         163 :         DumpMemoryArea dma;
     117             : 
     118             :         /* create a new descriptor pool */
     119             : 
     120         163 :         DescriptorPool descpool(class_java_lang_Object);
     121             : 
     122             :         /* add some entries we need */
     123             : 
     124         163 :         if (!descpool.add_class(utf8::java_lang_Object))
     125           0 :                 return false;
     126             : 
     127         163 :         if (!descpool.add_class(utf8::java_lang_Class))
     128           0 :                 return false;
     129             : 
     130             :         /* first add all descriptors to the pool */
     131             : 
     132        3423 :         for (builtintable_entry *bte = builtintable_internal; bte->fp != NULL; bte++) {
     133        3260 :                 bte->name       = Utf8String::from_utf8(bte->cname);
     134        3260 :                 bte->descriptor = Utf8String::from_utf8(bte->cdescriptor);
     135             : 
     136        3260 :                 if (descpool.add_method(bte->descriptor) == -1)
     137           0 :                         return false;
     138             :         }
     139             : 
     140         815 :         for (builtintable_entry *bte = builtintable_automatic; bte->fp != NULL; bte++) {
     141         652 :                 bte->descriptor = Utf8String::from_utf8(bte->cdescriptor);
     142             : 
     143         652 :                 if (descpool.add_method(bte->descriptor) == -1)
     144           0 :                         return false;
     145             :         }
     146             : 
     147         652 :         for (builtintable_entry *bte = builtintable_function; bte->fp != NULL; bte++) {
     148         489 :                 bte->classname  = Utf8String::from_utf8(bte->cclassname);
     149         489 :                 bte->name       = Utf8String::from_utf8(bte->cname);
     150         489 :                 bte->descriptor = Utf8String::from_utf8(bte->cdescriptor);
     151             : 
     152         489 :                 if (descpool.add_method(bte->descriptor) == -1)
     153           0 :                         return false;
     154             :         }
     155             : 
     156             :         /* create the class reference table */
     157             : 
     158         163 :         (void) descpool.create_classrefs(NULL);
     159             : 
     160             :         /* allocate space for the parsed descriptors */
     161             : 
     162         163 :         descpool.alloc_parsed_descriptors();
     163             : 
     164             :         /* Now parse all descriptors.  NOTE: builtin-functions are treated
     165             :            like static methods (no `this' pointer). */
     166             : 
     167        3423 :         for (builtintable_entry *bte = builtintable_internal; bte->fp != NULL; bte++) {
     168             :                 bte->md =
     169             :                         descpool.parse_method_descriptor(bte->descriptor,
     170             :                                                                                          ACC_STATIC | ACC_METHOD_BUILTIN,
     171        3260 :                                                                                          NULL);
     172             : 
     173             :                 /* generate a builtin stub if we need one */
     174             : 
     175        3260 :                 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
     176        2119 :                         BuiltinStub::generate(method_new_builtin(bte), bte);
     177             :                 }
     178             :         }
     179             : 
     180         815 :         for (builtintable_entry *bte = builtintable_automatic; bte->fp != NULL; bte++) {
     181             :                 bte->md =
     182             :                         descpool.parse_method_descriptor(bte->descriptor,
     183             :                                                                                          ACC_STATIC | ACC_METHOD_BUILTIN,
     184         652 :                                                                                          NULL);
     185             : 
     186             :                 /* no stubs should be needed for this table */
     187             : 
     188         652 :                 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
     189             :         }
     190             : 
     191         652 :         for (builtintable_entry *bte = builtintable_function; bte->fp != NULL; bte++) {
     192             :                 bte->md =
     193             :                         descpool.parse_method_descriptor(bte->descriptor,
     194             :                                                                                          ACC_STATIC | ACC_METHOD_BUILTIN,
     195         489 :                                                                                          NULL);
     196             : 
     197             :                 /* generate a builtin stub if we need one */
     198             : 
     199         489 :                 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
     200         163 :                         BuiltinStub::generate(method_new_builtin(bte), bte);
     201             :                 }
     202             :         }
     203             : 
     204         163 :         return true;
     205             : }
     206             : 
     207             : 
     208             : /* builtintable_comparator *****************************************************
     209             : 
     210             :    qsort comparator for the automatic builtin table.
     211             : 
     212             : *******************************************************************************/
     213             : 
     214         652 : static int builtintable_comparator(const void *a, const void *b)
     215             : {
     216             :         builtintable_entry *bte1;
     217             :         builtintable_entry *bte2;
     218             : 
     219         652 :         bte1 = (builtintable_entry *) a;
     220         652 :         bte2 = (builtintable_entry *) b;
     221             : 
     222         652 :         return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
     223             : }
     224             : 
     225             : 
     226             : /* builtintable_sort_automatic *************************************************
     227             : 
     228             :    Sorts the automatic builtin table.
     229             : 
     230             : *******************************************************************************/
     231             : 
     232         163 : static void builtintable_sort_automatic(void)
     233             : {
     234             :         s4 entries;
     235             : 
     236             :         /* calculate table size statically (`- 1' comment see builtintable.inc) */
     237             : 
     238         163 :         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
     239             : 
     240             :         qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
     241         163 :                   builtintable_comparator);
     242         163 : }
     243             : 
     244             : 
     245             : /* builtin_init ****************************************************************
     246             : 
     247             :    Initialize the global table of builtin functions.
     248             : 
     249             : *******************************************************************************/
     250             : 
     251         163 : bool builtin_init(void)
     252             : {
     253         163 :         TRACESUBSYSTEMINITIALIZATION("builtin_init");
     254             : 
     255             :         /* initialize the builtin tables */
     256             : 
     257         163 :         if (!builtintable_init())
     258           0 :                 return false;
     259             : 
     260             :         /* sort builtin tables */
     261             : 
     262         163 :         builtintable_sort_automatic();
     263             : 
     264         163 :         return true;
     265             : }
     266             : 
     267             : 
     268             : /* builtintable_get_internal ***************************************************
     269             : 
     270             :    Finds an entry in the builtintable for internal functions and
     271             :    returns the a pointer to the structure.
     272             : 
     273             : *******************************************************************************/
     274             : 
     275      141036 : builtintable_entry *builtintable_get_internal(functionptr fp)
     276             : {
     277             :         builtintable_entry *bte;
     278             : 
     279     1650574 :         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
     280     1650574 :                 if (bte->fp == fp)
     281      141036 :                         return bte;
     282             :         }
     283             : 
     284           0 :         return NULL;
     285             : }
     286             : 
     287             : 
     288             : /* builtintable_get_automatic **************************************************
     289             : 
     290             :    Finds an entry in the builtintable for functions which are replaced
     291             :    automatically and returns the a pointer to the structure.
     292             : 
     293             : *******************************************************************************/
     294             : 
     295     4412552 : builtintable_entry *builtintable_get_automatic(s4 opcode)
     296             : {
     297             :         builtintable_entry *first;
     298             :         builtintable_entry *last;
     299             :         builtintable_entry *middle;
     300             :         s4                  half;
     301             :         s4                  entries;
     302             : 
     303             :         /* calculate table size statically (`- 1' comment see builtintable.inc) */
     304             : 
     305     4412552 :         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
     306             : 
     307     4412552 :         first = builtintable_automatic;
     308     4412552 :         last = builtintable_automatic + entries;
     309             : 
     310    21207403 :         while (entries > 0) {
     311    12382299 :                 half = entries / 2;
     312    12382299 :                 middle = first + half;
     313             : 
     314    12382299 :                 if (middle->opcode < opcode) {
     315     1710669 :                         first = middle + 1;
     316     1710669 :                         entries -= half + 1;
     317             :                 }
     318             :                 else
     319    10671630 :                         entries = half;
     320             :         }
     321             : 
     322     4412552 :         return (first != last ? first : NULL);
     323             : }
     324             : 
     325             : 
     326             : /* builtintable_replace_function ***********************************************
     327             : 
     328             :    XXX
     329             : 
     330             : *******************************************************************************/
     331             : 
     332             : #if defined(ENABLE_JIT)
     333      283216 : bool builtintable_replace_function(void *iptr_)
     334             : {
     335             :         constant_FMIref    *mr;
     336             :         builtintable_entry *bte;
     337             :         instruction        *iptr;
     338             : 
     339      283216 :         iptr = (instruction *) iptr_; /* twisti will kill me ;) */
     340             : 
     341             :         /* get name and descriptor of the function */
     342             : 
     343      283216 :         switch (iptr->opc) {
     344             :         case ICMD_INVOKESTATIC:
     345             :                 /* The instruction MUST be resolved, otherwise we run into
     346             :                    lazy loading troubles.  Anyway, we should/can only replace
     347             :                    very VM-close functions. */
     348             : 
     349       57944 :                 if (INSTRUCTION_IS_UNRESOLVED(iptr))
     350           0 :                         return false;
     351             : 
     352       57944 :                 mr = iptr->sx.s23.s3.fmiref;
     353             :                 break;  
     354             : 
     355             :         default:
     356      225272 :                 return false;
     357             :         }
     358             : 
     359             :         /* search the function table */
     360             : 
     361      228693 :         for (bte = builtintable_function; bte->fp != NULL; bte++) {
     362      171782 :                 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
     363             :                         (mr->name                == bte->name) &&
     364             :                         (mr->descriptor          == bte->descriptor)) {
     365             : 
     366             :                         /* set the values in the instruction */
     367             : 
     368        1033 :                         iptr->opc           = bte->opcode;
     369        1033 :                         iptr->sx.s23.s3.bte = bte;
     370             : 
     371        1033 :                         if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
     372        1025 :                                 iptr->flags.bits |= INS_FLAG_CHECK;
     373             :                         else
     374           8 :                                 iptr->flags.bits &= ~INS_FLAG_CHECK;
     375             : 
     376        1033 :                         return true;
     377             :                 }
     378             :         }
     379             : 
     380       56911 :         return false;
     381             : }
     382             : #endif /* defined(ENABLE_JIT) */
     383             : 
     384             : 
     385             : /*============================================================================*/
     386             : /* INTERNAL BUILTIN FUNCTIONS                                                 */
     387             : /*============================================================================*/
     388             : 
     389             : /* builtin_instanceof **********************************************************
     390             : 
     391             :    Checks if an object is an instance of some given class (or subclass
     392             :    of that class). If class is an interface, checks if the interface
     393             :    is implemented.
     394             : 
     395             :    RETURN VALUE:
     396             :      1......o is an instance of class or implements the interface
     397             :      0......otherwise or if o == NULL
     398             : 
     399             :    NOTE: This builtin can be called from NATIVE code only.
     400             : 
     401             : *******************************************************************************/
     402             : 
     403      118136 : bool builtin_instanceof(java_handle_t *o, classinfo *c)
     404             : {
     405             :         classinfo *oc;
     406             : 
     407      118136 :         if (o == NULL)
     408           0 :                 return 0;
     409             : 
     410      118136 :         LLNI_class_get(o, oc);
     411             : 
     412      118136 :         return class_isanysubclass(oc, c);
     413             : }
     414             : 
     415             : 
     416             : 
     417             : /* builtin_checkcast ***********************************************************
     418             : 
     419             :    The same as builtin_instanceof but with the exception
     420             :    that 1 is returned when (o == NULL).
     421             : 
     422             :    NOTE: This builtin can be called from NATIVE code only.
     423             : 
     424             : *******************************************************************************/
     425             : 
     426           0 : bool builtin_checkcast(java_handle_t *o, classinfo *c)
     427             : {
     428             :         classinfo *oc;
     429             : 
     430           0 :         if (o == NULL)
     431           0 :                 return 1;
     432             : 
     433           0 :         LLNI_class_get(o, oc);
     434             : 
     435           0 :         if (class_isanysubclass(oc, c))
     436           0 :                 return 1;
     437             : 
     438           0 :         return 0;
     439             : }
     440             : 
     441             : 
     442             : /* builtin_arraycheckcast ******************************************************
     443             : 
     444             :    Checks if an object is really a subtype of the requested array
     445             :    type.  The object has to be an array to begin with. For simple
     446             :    arrays (int, short, double, etc.) the types have to match exactly.
     447             :    For arrays of objects, the type of elements in the array has to be
     448             :    a subtype (or the same type) of the requested element type. For
     449             :    arrays of arrays (which in turn can again be arrays of arrays), the
     450             :    types at the lowest level have to satisfy the corresponding sub
     451             :    class relation.
     452             : 
     453             :    NOTE: This is a FAST builtin and can be called from JIT code only.
     454             : 
     455             : *******************************************************************************/
     456             : 
     457       28995 : bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
     458             : {
     459             :         arraydescriptor *desc;
     460             : 
     461       28995 :         if (o == NULL)
     462         673 :                 return 1;
     463             : 
     464       28322 :         desc = o->vftbl->arraydesc;
     465             : 
     466       28322 :         if (desc == NULL)
     467           3 :                 return 0;
     468             :  
     469       28319 :         return class_is_arraycompatible(desc, targetclass->vftbl->arraydesc);
     470             : }
     471             : 
     472             : 
     473             : /* builtin_fast_arrayinstanceof ************************************************
     474             : 
     475             :    NOTE: This is a FAST builtin and can be called from JIT code only.
     476             : 
     477             : *******************************************************************************/
     478             : 
     479        4852 : bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
     480             : {
     481        4852 :         if (o == NULL)
     482           1 :                 return 0;
     483             : 
     484        4851 :         return builtin_fast_arraycheckcast(o, targetclass);
     485             : }
     486             : 
     487             : 
     488             : /* builtin_arrayinstanceof *****************************************************
     489             : 
     490             :    NOTE: This builtin can be called from NATIVE code only.
     491             : 
     492             : *******************************************************************************/
     493             : 
     494         176 : bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
     495             : {
     496             :         bool result;
     497             : 
     498             :         LLNI_CRITICAL_START;
     499             : 
     500         176 :         result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
     501             : 
     502             :         LLNI_CRITICAL_END;
     503             : 
     504         176 :         return result;
     505             : }
     506             : 
     507             : 
     508             : /* builtin_throw_exception *****************************************************
     509             : 
     510             :    Sets the exception pointer with the thrown exception and prints some
     511             :    debugging information.
     512             :    
     513             :    NOTE: This is a FAST builtin and can be called from JIT code,
     514             :    or from asm_vm_call_method.
     515             : 
     516             : *******************************************************************************/
     517             : 
     518          60 : void *builtin_throw_exception(java_object_t *xptr)
     519             : {
     520             : #if !defined(NDEBUG)
     521             :         /* print exception trace */
     522             : 
     523          60 :         if (opt_TraceExceptions)
     524           0 :                 trace_exception_builtin(xptr);
     525             : #endif /* !defined(NDEBUG) */
     526             : 
     527             :         /* actually set the exception */
     528             : 
     529          60 :         exceptions_set_exception(LLNI_QUICKWRAP(xptr));
     530             : 
     531             :         /* Return a NULL pointer.  This is required for vm_call_method to
     532             :            check for an exception.  This is for convenience. */
     533             : 
     534          60 :         return NULL;
     535             : }
     536             : 
     537             : 
     538             : /* builtin_retrieve_exception **************************************************
     539             : 
     540             :    Gets and clears the exception pointer of the current thread.
     541             : 
     542             :    RETURN VALUE:
     543             :       the exception object, or NULL if no exception was thrown.
     544             : 
     545             :    NOTE: This is a FAST builtin and can be called from JIT code,
     546             :    or from the signal handlers.
     547             : 
     548             : *******************************************************************************/
     549             : 
     550           0 : java_object_t *builtin_retrieve_exception(void)
     551             : {
     552             :         java_handle_t *h;
     553             :         java_object_t *o;
     554             : 
     555             :         /* actually get and clear the exception */
     556             : 
     557           0 :         h = exceptions_get_and_clear_exception();
     558           0 :         o = LLNI_UNWRAP(h);
     559             : 
     560           0 :         return o;
     561             : }
     562             : 
     563             : 
     564             : /* builtin_canstore ************************************************************
     565             : 
     566             :    Checks, if an object can be stored in an array.
     567             : 
     568             :    RETURN VALUE:
     569             :       1......possible
     570             :       0......otherwise (throws an ArrayStoreException)
     571             : 
     572             :    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
     573             : 
     574             : *******************************************************************************/
     575             : 
     576     7068098 : bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
     577             : {
     578             :         bool result;
     579             : 
     580             :         LLNI_CRITICAL_START;
     581             : 
     582     7068098 :         result = builtin_fast_canstore((java_objectarray_t*) LLNI_DIRECT(oa), LLNI_UNWRAP(o));
     583             : 
     584             :         LLNI_CRITICAL_END;
     585             : 
     586             :         /* if not possible, throw an exception */
     587             : 
     588     7068098 :         if (result == 0)
     589           1 :                 exceptions_throw_arraystoreexception();
     590             : 
     591     7068098 :         return result;
     592             : }
     593             : 
     594             : #if USES_NEW_SUBTYPE
     595             : /* fast_subtype_check **********************************************************
     596             : 
     597             :    Checks if s is a subtype of t, using both the restricted subtype relation
     598             :    and the overflow array (see Cliff Click and John Rose: Fast subtype checking
     599             :    in the Hotspot JVM.)
     600             : 
     601             :    RETURN VALUE:
     602             :       1......s is a subtype of t.
     603             :       0......otherwise
     604             : 
     605             : *******************************************************************************/
     606             : 
     607      201029 : bool fast_subtype_check(vftbl_t *s, vftbl_t *t)
     608             : {
     609      201029 :    if (s->subtype_display[t->subtype_depth] == t)
     610      200951 :        return true;
     611          78 :    if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
     612          43 :        return false;
     613          35 :    return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
     614             : }
     615             : #endif
     616             : 
     617             : /* builtin_fast_canstore *******************************************************
     618             : 
     619             :    Checks, if an object can be stored in an array.
     620             : 
     621             :    RETURN VALUE:
     622             :       1......possible
     623             :       0......otherwise (no exception thrown!)
     624             : 
     625             :    NOTE: This is a FAST builtin and can be called from JIT code only.
     626             : 
     627             : *******************************************************************************/
     628             : 
     629     7784836 : bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
     630             : {
     631             :         arraydescriptor *desc;
     632             :         arraydescriptor *valuedesc;
     633             :         vftbl_t         *componentvftbl;
     634             :         vftbl_t         *valuevftbl;
     635             :         int32_t          baseval;
     636             :         bool             result;
     637             : 
     638     7784836 :         if (o == NULL)
     639     7037203 :                 return 1;
     640             : 
     641             :         /* The following is guaranteed (by verifier checks):
     642             :          *
     643             :          *     *) oa->...vftbl->arraydesc != NULL
     644             :          *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
     645             :          *     *) o->vftbl is not an interface vftbl
     646             :          */
     647             : 
     648      747633 :         desc           = oa->header.objheader.vftbl->arraydesc;
     649      747633 :         componentvftbl = desc->componentvftbl;
     650      747633 :         valuevftbl     = o->vftbl;
     651      747633 :         valuedesc      = valuevftbl->arraydesc;
     652             : 
     653      747633 :         if ((desc->dimension - 1) == 0) {
     654             :                 /* {oa is a one-dimensional array} */
     655             :                 /* {oa is an array of references} */
     656             :                 
     657      423743 :                 if (valuevftbl == componentvftbl)
     658      335564 :                         return 1;
     659             : 
     660             :                 LOCK_CLASSRENUMBER_LOCK;
     661             : 
     662       88179 :                 baseval = componentvftbl->baseval;
     663             : 
     664       88179 :                 if (baseval <= 0) {
     665             :                         /* an array of interface references */
     666             : 
     667             :                         result = ((valuevftbl->interfacetablelength > -baseval) &&
     668        1171 :                                           (valuevftbl->interfacetable[baseval] != NULL));
     669             :                 }
     670             :                 else {
     671             : #if USES_NEW_SUBTYPE
     672       87008 :                         result = fast_subtype_check(valuevftbl, componentvftbl);
     673             : #else
     674             :                         uint32_t diffval = valuevftbl->baseval - componentvftbl->baseval;
     675             :                         result = diffval <= (uint32_t) componentvftbl->diffval;
     676             : #endif
     677             :                 }
     678             : 
     679             :                 UNLOCK_CLASSRENUMBER_LOCK;
     680             :         }
     681      323890 :         else if (valuedesc == NULL) {
     682             :                 /* {oa has dimension > 1} */
     683             :                 /* {componentvftbl->arraydesc != NULL} */
     684             : 
     685             :                 /* check if o is an array */
     686             : 
     687           0 :                 return 0;
     688             :         }
     689             :         else {
     690             :                 /* {o is an array} */
     691             : 
     692      323890 :                 result = class_is_arraycompatible(valuedesc, componentvftbl->arraydesc);
     693             :         }
     694             : 
     695             :         /* return result */
     696             : 
     697      412069 :         return result;
     698             : }
     699             : 
     700             : 
     701             : /* This is an optimized version where a is guaranteed to be one-dimensional */
     702           0 : bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
     703             : {
     704             :         arraydescriptor *desc;
     705             :         vftbl_t         *elementvftbl;
     706             :         vftbl_t         *valuevftbl;
     707             :         int32_t          baseval;
     708             :         bool             result;
     709             :         
     710           0 :         if (o == NULL)
     711           0 :                 return 1;
     712             : 
     713             :         /* The following is guaranteed (by verifier checks):
     714             :          *
     715             :          *     *) a->...vftbl->arraydesc != NULL
     716             :          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
     717             :          *     *) a->...vftbl->arraydesc->dimension == 1
     718             :          *     *) o->vftbl is not an interface vftbl
     719             :          */
     720             : 
     721           0 :         desc = a->header.objheader.vftbl->arraydesc;
     722           0 :     elementvftbl = desc->elementvftbl;
     723           0 :         valuevftbl = o->vftbl;
     724             : 
     725             :         /* {a is a one-dimensional array} */
     726             :         
     727           0 :         if (valuevftbl == elementvftbl)
     728           0 :                 return 1;
     729             : 
     730             :         LOCK_CLASSRENUMBER_LOCK;
     731             : 
     732           0 :         baseval = elementvftbl->baseval;
     733             : 
     734           0 :         if (baseval <= 0) {
     735             :                 /* an array of interface references */
     736             :                 result = ((valuevftbl->interfacetablelength > -baseval) &&
     737           0 :                                   (valuevftbl->interfacetable[baseval] != NULL));
     738             :         }
     739             :         else {
     740             : #if USES_NEW_SUBTYPE
     741           0 :                 result = fast_subtype_check(valuevftbl, elementvftbl);
     742             : #else
     743             :                 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
     744             :                 result = diffval <= (uint32_t) elementvftbl->diffval;
     745             : #endif
     746             :         }
     747             : 
     748             :         UNLOCK_CLASSRENUMBER_LOCK;
     749             : 
     750           0 :         return result;
     751             : }
     752             : 
     753             : 
     754             : /* This is an optimized version where a is guaranteed to be a
     755             :  * one-dimensional array of a class type */
     756           0 : bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
     757             : {
     758             :         vftbl_t *elementvftbl;
     759             :         vftbl_t *valuevftbl;
     760             :         bool     result;
     761             :         
     762           0 :         if (o == NULL)
     763           0 :                 return 1;
     764             : 
     765             :         /* The following is guaranteed (by verifier checks):
     766             :          *
     767             :          *     *) a->...vftbl->arraydesc != NULL
     768             :          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
     769             :          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
     770             :          *     *) a->...vftbl->arraydesc->dimension == 1
     771             :          *     *) o->vftbl is not an interface vftbl
     772             :          */
     773             : 
     774           0 :     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
     775           0 :         valuevftbl = o->vftbl;
     776             : 
     777             :         /* {a is a one-dimensional array} */
     778             :         
     779           0 :         if (valuevftbl == elementvftbl)
     780           0 :                 return 1;
     781             : 
     782             :         LOCK_CLASSRENUMBER_LOCK;
     783             : 
     784             : #if USES_NEW_SUBTYPE
     785           0 :         result = fast_subtype_check(valuevftbl, elementvftbl);
     786             : #else
     787             :         uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
     788             :         result = diffval <= (uint32_t) elementvftbl->diffval;
     789             : #endif
     790             : 
     791             :         UNLOCK_CLASSRENUMBER_LOCK;
     792             : 
     793           0 :         return result;
     794             : }
     795             : 
     796             : // register boot real-time group
     797             : RT_REGISTER_GROUP(buildin_group,"boot","boot group")
     798             : 
     799             : // register real-time timers
     800             : RT_REGISTER_GROUP_TIMER(bi_new_timer,"buildin","builtin_new time",buildin_group)
     801             : RT_REGISTER_GROUP_TIMER(bi_newa_timer,"buildin","builtin_newarray time",buildin_group)
     802             : 
     803             : /* builtin_new *****************************************************************
     804             : 
     805             :    Creates a new instance of class c on the heap.
     806             : 
     807             :    RETURN VALUE:
     808             :       pointer to the object, or NULL if no memory is available
     809             : 
     810             :    NOTE: This builtin can be called from NATIVE code only.
     811             : 
     812             : *******************************************************************************/
     813             : 
     814     1184314 : java_handle_t *builtin_new(classinfo *c)
     815             : {
     816             :         java_handle_t *o;
     817             : #if defined(ENABLE_CYCLES_STATS)
     818             :         u8 cycles_start, cycles_end;
     819             : #endif
     820             : 
     821             :         RT_TIMER_START(bi_new_timer);
     822             :         CYCLES_STATS_GET(cycles_start);
     823             : 
     824             :         /* is the class loaded */
     825             : 
     826     1184314 :         assert(c->state & CLASS_LOADED);
     827             : 
     828             :         /* check if we can instantiate this class */
     829             : 
     830     1184314 :         if (c->flags & ACC_ABSTRACT) {
     831           0 :                 exceptions_throw_instantiationerror(c);
     832           0 :                 return NULL;
     833             :         }
     834             : 
     835             :         /* is the class linked */
     836             : 
     837     1184314 :         if (!(c->state & CLASS_LINKED))
     838          75 :                 if (!link_class(c))
     839           0 :                         return NULL;
     840             : 
     841     1184314 :         if (!(c->state & CLASS_INITIALIZED)) {
     842             : #if !defined(NDEBUG)
     843       82184 :                 if (initverbose)
     844           0 :                         log_message_class("Initialize class (from builtin_new): ", c);
     845             : #endif
     846             : 
     847       82184 :                 if (!initialize_class(c))
     848           0 :                         return NULL;
     849             :         }
     850             : 
     851             :         o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
     852     1184314 :                                                                         c->finalizer, true);
     853             : 
     854     1184314 :         if (!o)
     855           0 :                 return NULL;
     856             : 
     857             : #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
     858             :         /* XXX this is only a dirty hack to make Boehm work with handles */
     859             : 
     860             :         o = LLNI_WRAP((java_object_t *) o);
     861             : #endif
     862             : 
     863     1184314 :         LLNI_vftbl_direct(o) = c->vftbl;
     864             : 
     865     1184314 :         Lockword(LLNI_DIRECT(o)->lockword).init();
     866             : 
     867             :         CYCLES_STATS_GET(cycles_end);
     868             :         RT_TIMER_STOP(bi_new_timer);
     869             : 
     870             :         CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
     871             : 
     872     1184314 :         return o;
     873             : }
     874             : 
     875             : #if defined(ENABLE_ESCAPE_REASON)
     876             : java_handle_t *builtin_escape_reason_new(classinfo *c) {
     877             :         print_escape_reasons();
     878             :         return builtin_java_new(c);
     879             : }
     880             : #endif
     881             : 
     882             : #if defined(ENABLE_TLH)
     883             : java_handle_t *builtin_tlh_new(classinfo *c)
     884             : {
     885             :         java_handle_t *o;
     886             : # if defined(ENABLE_CYCLES_STATS)
     887             :         u8 cycles_start, cycles_end;
     888             : # endif
     889             : 
     890             :         CYCLES_STATS_GET(cycles_start);
     891             : 
     892             :         /* is the class loaded */
     893             : 
     894             :         assert(c->state & CLASS_LOADED);
     895             : 
     896             :         /* check if we can instantiate this class */
     897             : 
     898             :         if (c->flags & ACC_ABSTRACT) {
     899             :                 exceptions_throw_instantiationerror(c);
     900             :                 return NULL;
     901             :         }
     902             : 
     903             :         /* is the class linked */
     904             : 
     905             :         if (!(c->state & CLASS_LINKED))
     906             :                 if (!link_class(c))
     907             :                         return NULL;
     908             : 
     909             :         if (!(c->state & CLASS_INITIALIZED)) {
     910             : # if !defined(NDEBUG)
     911             :                 if (initverbose)
     912             :                         log_message_class("Initialize class (from builtin_new): ", c);
     913             : # endif
     914             : 
     915             :                 if (!initialize_class(c))
     916             :                         return NULL;
     917             :         }
     918             : 
     919             :         /*
     920             :         o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
     921             :         */
     922             :         o = NULL;
     923             : 
     924             :         if (o == NULL) {
     925             :                 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
     926             :                                                                                 c->finalizer, true);
     927             :         }
     928             : 
     929             :         if (!o)
     930             :                 return NULL;
     931             : 
     932             : # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
     933             :         /* XXX this is only a dirty hack to make Boehm work with handles */
     934             : 
     935             :         o = LLNI_WRAP((java_object_t *) o);
     936             : # endif
     937             : 
     938             :         LLNI_vftbl_direct(o) = c->vftbl;
     939             : 
     940             :         Lockword(LLNI_DIRECT(o)->lockword).init();
     941             : 
     942             :         CYCLES_STATS_GET(cycles_end);
     943             : 
     944             : /*
     945             :         CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
     946             :         TODO port to new rt-timing
     947             :         RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
     948             : */
     949             : 
     950             :         return o;
     951             : }
     952             : #endif
     953             : 
     954             : 
     955             : /* builtin_java_new ************************************************************
     956             : 
     957             :    NOTE: This is a SLOW builtin and can be called from JIT code only.
     958             : 
     959             : *******************************************************************************/
     960             : 
     961     1097710 : java_handle_t *builtin_java_new(java_handle_t *clazz)
     962             : {
     963     1097710 :         return builtin_new(LLNI_classinfo_unwrap(clazz));
     964             : }
     965             : 
     966             : 
     967             : /* builtin_fast_new ************************************************************
     968             : 
     969             :    Creates a new instance of class c on the heap.
     970             : 
     971             :    RETURN VALUE:
     972             :       pointer to the object, or NULL if no fast return
     973             :       is possible for any reason.
     974             : 
     975             :    NOTE: This is a FAST builtin and can be called from JIT code only.
     976             : 
     977             : *******************************************************************************/
     978             : 
     979           0 : java_object_t *builtin_fast_new(classinfo *c)
     980             : {
     981             :         java_object_t *o;
     982             : #if defined(ENABLE_CYCLES_STATS)
     983             :         u8 cycles_start, cycles_end;
     984             : #endif
     985             : 
     986             :         CYCLES_STATS_GET(cycles_start);
     987             : 
     988             :         /* is the class loaded */
     989             : 
     990           0 :         assert(c->state & CLASS_LOADED);
     991             : 
     992             :         /* check if we can instantiate this class */
     993             : 
     994           0 :         if (c->flags & ACC_ABSTRACT)
     995           0 :                 return NULL;
     996             : 
     997             :         /* is the class linked */
     998             : 
     999           0 :         if (!(c->state & CLASS_LINKED))
    1000           0 :                 return NULL;
    1001             : 
    1002           0 :         if (!(c->state & CLASS_INITIALIZED))
    1003           0 :                 return NULL;
    1004             : 
    1005             :         o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
    1006           0 :                                                                         c->finalizer, false);
    1007             : 
    1008           0 :         if (!o)
    1009           0 :                 return NULL;
    1010             : 
    1011           0 :         o->vftbl = c->vftbl;
    1012             : 
    1013           0 :         Lockword(LLNI_DIRECT(o)->lockword).init();
    1014             : 
    1015             :         CYCLES_STATS_GET(cycles_end);
    1016             : 
    1017             :         CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
    1018             : 
    1019           0 :         return o;
    1020             : }
    1021             : 
    1022             : 
    1023             : /* builtin_java_newarray *******************************************************
    1024             : 
    1025             :    Creates an array with the given vftbl on the heap. This function
    1026             :    takes as class argument an array class.
    1027             : 
    1028             :    RETURN VALUE:
    1029             :       pointer to the array or NULL if no memory is available
    1030             : 
    1031             :    NOTE: This is a SLOW builtin and can be called from JIT code only.
    1032             : 
    1033             : *******************************************************************************/
    1034             : 
    1035       35316 : java_handle_array_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
    1036             : {
    1037             : 
    1038             :         RT_TIMER_START(bi_newa_timer);
    1039             : 
    1040       35316 :         classinfo* arrayclass = LLNI_classinfo_unwrap(arrayclazz);
    1041             : 
    1042             :         // Allocate a new array with given size and class on the heap
    1043       35316 :         Array a(size, arrayclass);
    1044             : 
    1045             :         RT_TIMER_STOP(bi_newa_timer);
    1046             : 
    1047       35316 :         return a.get_handle();
    1048             : }
    1049             : 
    1050             : 
    1051             : /* builtin_newarray_type ****************************************************
    1052             : 
    1053             :    Creates an array of [type]s on the heap.
    1054             :         
    1055             :    RETURN VALUE:
    1056             :       pointer to the array or NULL if no memory is available
    1057             : 
    1058             :    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
    1059             : 
    1060             : *******************************************************************************/
    1061             : 
    1062             : #define BUILTIN_NEWARRAY_TYPE(type, name)                          \
    1063             : java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
    1064             : {                                                                  \
    1065             :         name##Array a(size);                                           \
    1066             :         return a.get_handle();                                         \
    1067             : }
    1068             : 
    1069           0 : BUILTIN_NEWARRAY_TYPE(boolean, Boolean)
    1070      190645 : BUILTIN_NEWARRAY_TYPE(byte,    Byte)
    1071      247174 : BUILTIN_NEWARRAY_TYPE(char,    Char)
    1072        2540 : BUILTIN_NEWARRAY_TYPE(short,   Short)
    1073        1849 : BUILTIN_NEWARRAY_TYPE(int,     Int)
    1074          47 : BUILTIN_NEWARRAY_TYPE(long,    Long)
    1075           9 : BUILTIN_NEWARRAY_TYPE(float,   Float)
    1076           9 : BUILTIN_NEWARRAY_TYPE(double,  Double)
    1077             : 
    1078             : 
    1079             : /* builtin_multianewarray_intern ***********************************************
    1080             : 
    1081             :    Creates a multi-dimensional array on the heap. The dimensions are
    1082             :    passed in an array of longs.
    1083             : 
    1084             :    ARGUMENTS:
    1085             :       n.............number of dimensions to create
    1086             :       arrayclass....the array class
    1087             :       dims..........array containing the size of each dimension to create
    1088             : 
    1089             :    RETURN VALUE:
    1090             :       pointer to the array or NULL if no memory is available
    1091             : 
    1092             : ******************************************************************************/
    1093             : 
    1094         180 : static java_handle_array_t *builtin_multianewarray_intern(int n,
    1095             :                                                                                                         classinfo *arrayclass,
    1096             :                                                                                                         long *dims)
    1097             : {
    1098             :         int32_t i;
    1099             : 
    1100             :         /* create this dimension */
    1101             : 
    1102         180 :         int32_t size = (int32_t) dims[0];
    1103         180 :         Array a(size, arrayclass);
    1104             : 
    1105         180 :         if (a.is_null())
    1106           1 :                 return NULL;
    1107             : 
    1108             :         /* if this is the last dimension return */
    1109             : 
    1110         179 :         if (!--n)
    1111         140 :                 return a.get_handle();
    1112             : 
    1113             :         /* get the class of the components to create */
    1114             : 
    1115          39 :         classinfo* componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
    1116             : 
    1117             :         /* The verifier guarantees that the dimension count is in the range. */
    1118             : 
    1119             :         /* create the component arrays */
    1120             : 
    1121          39 :         ObjectArray oa(a.get_handle());
    1122             : 
    1123         199 :         for (i = 0; i < size; i++) {
    1124             :                 java_handle_array_t *ea =
    1125             : #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
    1126             :                         /* we save an s4 to a s8 slot, 8-byte aligned */
    1127             : 
    1128             :                         builtin_multianewarray_intern(n, componentclass, dims + 2);
    1129             : #else
    1130         160 :                         builtin_multianewarray_intern(n, componentclass, dims + 1);
    1131             : #endif
    1132             : 
    1133         160 :                 if (!ea)
    1134           0 :                         return NULL;
    1135             : 
    1136         160 :                 oa.set_element(i, (java_handle_t*) ea);
    1137             :         }
    1138             : 
    1139          39 :         return a.get_handle();
    1140             : }
    1141             : 
    1142             : 
    1143             : /* builtin_multianewarray ******************************************************
    1144             : 
    1145             :    Wrapper for builtin_multianewarray_intern which checks all
    1146             :    dimensions before we start allocating.
    1147             : 
    1148             :    NOTE: This is a SLOW builtin and can be called from JIT code only.
    1149             : 
    1150             : ******************************************************************************/
    1151             : 
    1152          22 : java_handle_objectarray_t *builtin_multianewarray(int n,
    1153             :                                                                                                   java_handle_t *arrayclazz,
    1154             :                                                                                                   long *dims)
    1155             : {
    1156             :         classinfo *c;
    1157             :         s4         i;
    1158             :         s4         size;
    1159             : 
    1160             :         /* check all dimensions before doing anything */
    1161             : 
    1162          71 :         for (i = 0; i < n; i++) {
    1163             : #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
    1164             :                 /* we save an s4 to a s8 slot, 8-byte aligned */
    1165             :                 size = (s4) dims[i * 2];
    1166             : #else
    1167          51 :                 size = (s4) dims[i];
    1168             : #endif
    1169             : 
    1170          51 :                 if (size < 0) {
    1171           2 :                         exceptions_throw_negativearraysizeexception();
    1172           2 :                         return NULL;
    1173             :                 }
    1174             :         }
    1175             : 
    1176          20 :         c = LLNI_classinfo_unwrap(arrayclazz);
    1177             : 
    1178             :         /* now call the real function */
    1179             : 
    1180             :         return (java_handle_objectarray_t *)
    1181          20 :                 builtin_multianewarray_intern(n, c, dims);
    1182             : }
    1183             : 
    1184             : 
    1185             : /* builtin_verbosecall_enter ***************************************************
    1186             : 
    1187             :    Print method call with arguments for -verbose:call.
    1188             : 
    1189             :    XXX: Remove mew once all archs use the new tracer!
    1190             : 
    1191             : *******************************************************************************/
    1192             : 
    1193             : #if !defined(NDEBUG)
    1194             : #ifdef TRACE_ARGS_NUM
    1195             : void builtin_verbosecall_enter(s8 a0, s8 a1,
    1196             : # if TRACE_ARGS_NUM >= 4
    1197             :                                                            s8 a2, s8 a3,
    1198             : # endif
    1199             : # if TRACE_ARGS_NUM >= 6
    1200             :                                                            s8 a4, s8 a5,
    1201             : # endif
    1202             : # if TRACE_ARGS_NUM == 8
    1203             :                                                            s8 a6, s8 a7,
    1204             : # endif
    1205             :                                                            methodinfo *m)
    1206             : {
    1207             :         log_text("builtin_verbosecall_enter: Do not call me anymore!");
    1208             : }
    1209             : #endif
    1210             : #endif /* !defined(NDEBUG) */
    1211             : 
    1212             : 
    1213             : /* builtin_verbosecall_exit ****************************************************
    1214             : 
    1215             :    Print method exit for -verbose:call.
    1216             : 
    1217             :    XXX: Remove mew once all archs use the new tracer!
    1218             : 
    1219             : *******************************************************************************/
    1220             : 
    1221             : #if !defined(NDEBUG)
    1222           0 : void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
    1223             : {
    1224           0 :         log_text("builtin_verbosecall_exit: Do not call me anymore!");
    1225           0 : }
    1226             : #endif /* !defined(NDEBUG) */
    1227             : 
    1228             : 
    1229             : /*============================================================================*/
    1230             : /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS                                */
    1231             : /*============================================================================*/
    1232             : 
    1233             : /*********** Functions for integer divisions *****************************
    1234             :  
    1235             :         On some systems (eg. DEC ALPHA), integer division is not supported by the
    1236             :         CPU. These helper functions implement the missing functionality.
    1237             : 
    1238             : ******************************************************************************/
    1239             : 
    1240             : #if !SUPPORT_DIVISION || defined(DISABLE_GC)
    1241             : s4 builtin_idiv(s4 a, s4 b)
    1242             : {
    1243             :         s4 c;
    1244             : 
    1245             :         c = a / b;
    1246             : 
    1247             :         return c;
    1248             : }
    1249             : 
    1250             : s4 builtin_irem(s4 a, s4 b)
    1251             : {
    1252             :         s4 c;
    1253             : 
    1254             :         c = a % b;
    1255             : 
    1256             :         return c;
    1257             : }
    1258             : #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
    1259             : 
    1260             : 
    1261             : /* functions for long arithmetics **********************************************
    1262             : 
    1263             :    On systems where 64 bit Integers are not supported by the CPU,
    1264             :    these functions are needed.
    1265             : 
    1266             : ******************************************************************************/
    1267             : 
    1268             : #if !SUPPORT_LONG_ADD
    1269             : s8 builtin_ladd(s8 a, s8 b)
    1270             : {
    1271             :         s8 c;
    1272             : 
    1273             :         c = a + b; 
    1274             : 
    1275             :         return c;
    1276             : }
    1277             : 
    1278             : s8 builtin_lsub(s8 a, s8 b)
    1279             : {
    1280             :         s8 c;
    1281             : 
    1282             :         c = a - b; 
    1283             : 
    1284             :         return c;
    1285             : }
    1286             : 
    1287             : s8 builtin_lneg(s8 a)
    1288             : {
    1289             :         s8 c;
    1290             : 
    1291             :         c = -a;
    1292             : 
    1293             :         return c;
    1294             : }
    1295             : #endif
    1296             : 
    1297             : 
    1298             : #if !SUPPORT_LONG_MUL
    1299             : s8 builtin_lmul(s8 a, s8 b)
    1300             : {
    1301             :         s8 c;
    1302             : 
    1303             :         c = a * b; 
    1304             : 
    1305             :         return c;
    1306             : }
    1307             : #endif
    1308             : 
    1309             : 
    1310             : #if !(SUPPORT_DIVISION && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
    1311             : s8 builtin_ldiv(s8 a, s8 b)
    1312             : {
    1313             :         s8 c;
    1314             : 
    1315             :         c = a / b; 
    1316             : 
    1317             :         return c;
    1318             : }
    1319             : 
    1320             : s8 builtin_lrem(s8 a, s8 b)
    1321             : {
    1322             :         s8 c;
    1323             : 
    1324             :         c = a % b; 
    1325             : 
    1326             :         return c;
    1327             : }
    1328             : #endif
    1329             : 
    1330             : 
    1331             : #if !SUPPORT_LONG_SHIFT
    1332             : s8 builtin_lshl(s8 a, s4 b)
    1333             : {
    1334             :         s8 c;
    1335             : 
    1336             :         c = a << (b & 63);
    1337             : 
    1338             :         return c;
    1339             : }
    1340             : 
    1341             : s8 builtin_lshr(s8 a, s4 b)
    1342             : {
    1343             :         s8 c;
    1344             : 
    1345             :         c = a >> (b & 63);
    1346             : 
    1347             :         return c;
    1348             : }
    1349             : 
    1350             : s8 builtin_lushr(s8 a, s4 b)
    1351             : {
    1352             :         s8 c;
    1353             : 
    1354             :         c = ((u8) a) >> (b & 63);
    1355             : 
    1356             :         return c;
    1357             : }
    1358             : #endif
    1359             : 
    1360             : 
    1361           1 : s4 builtin_lcmp(s8 a, s8 b)
    1362             : { 
    1363           1 :         if (a < b)
    1364           1 :                 return -1;
    1365             : 
    1366           0 :         if (a > b)
    1367           0 :                 return 1;
    1368             : 
    1369           0 :         return 0;
    1370             : }
    1371             : 
    1372             : 
    1373             : /* functions for unsupported floating instructions ****************************/
    1374             : 
    1375             : /* used to convert FLT_xxx defines into float values */
    1376             : 
    1377             : #if !SUPPORT_FLOAT
    1378             : static inline float intBitsToFloat(s4 i)
    1379             : {
    1380             :         imm_union imb;
    1381             : 
    1382             :         imb.i = i;
    1383             :         return imb.f;
    1384             : }
    1385             : #endif
    1386             : 
    1387             : 
    1388             : /* used to convert DBL_xxx defines into double values */
    1389             : 
    1390             : #if !SUPPORT_DOUBLE
    1391             : static inline float longBitsToDouble(s8 l)
    1392             : {
    1393             :         imm_union imb;
    1394             : 
    1395             :         imb.l = l;
    1396             :         return imb.d;
    1397             : }
    1398             : #endif
    1399             : 
    1400             : 
    1401             : #if !SUPPORT_FLOAT
    1402             : float builtin_fadd(float a, float b)
    1403             : {
    1404             :         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
    1405             :         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
    1406             :         if (finitef(a)) {
    1407             :                 if (finitef(b))
    1408             :                         return a + b;
    1409             :                 else
    1410             :                         return b;
    1411             :         }
    1412             :         else {
    1413             :                 if (finitef(b))
    1414             :                         return a;
    1415             :                 else {
    1416             :                         if (copysignf(1.0, a) == copysignf(1.0, b))
    1417             :                                 return a;
    1418             :                         else
    1419             :                                 return intBitsToFloat(FLT_NAN);
    1420             :                 }
    1421             :         }
    1422             : }
    1423             : 
    1424             : 
    1425             : float builtin_fsub(float a, float b)
    1426             : {
    1427             :         return builtin_fadd(a, builtin_fneg(b));
    1428             : }
    1429             : 
    1430             : 
    1431             : float builtin_fmul(float a, float b)
    1432             : {
    1433             :         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
    1434             :         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
    1435             :         if (finitef(a)) {
    1436             :                 if (finitef(b)) return a * b;
    1437             :                 else {
    1438             :                         if (a == 0) return intBitsToFloat(FLT_NAN);
    1439             :                         else return copysignf(b, copysignf(1.0, b)*a);
    1440             :                 }
    1441             :         }
    1442             :         else {
    1443             :                 if (finitef(b)) {
    1444             :                         if (b == 0) return intBitsToFloat(FLT_NAN);
    1445             :                         else return copysignf(a, copysignf(1.0, a)*b);
    1446             :                 }
    1447             :                 else {
    1448             :                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
    1449             :                 }
    1450             :         }
    1451             : }
    1452             : 
    1453             : 
    1454             : /* builtin_ddiv ****************************************************************
    1455             : 
    1456             :    Implementation as described in VM Spec.
    1457             : 
    1458             : *******************************************************************************/
    1459             : 
    1460             : float builtin_fdiv(float a, float b)
    1461             : {
    1462             :         if (finitef(a)) {
    1463             :                 if (finitef(b)) {
    1464             :                         /* If neither value1' nor value2' is NaN, the sign of the result */
    1465             :                         /* is positive if both values have the same sign, negative if the */
    1466             :                         /* values have different signs. */
    1467             : 
    1468             :                         return a / b;
    1469             : 
    1470             :                 } else {
    1471             :                         if (isnanf(b)) {
    1472             :                                 /* If either value1' or value2' is NaN, the result is NaN. */
    1473             : 
    1474             :                                 return intBitsToFloat(FLT_NAN);
    1475             : 
    1476             :                         } else {
    1477             :                                 /* Division of a finite value by an infinity results in a */
    1478             :                                 /* signed zero, with the sign-producing rule just given. */
    1479             : 
    1480             :                                 /* is sign equal? */
    1481             : 
    1482             :                                 if (copysignf(1.0, a) == copysignf(1.0, b))
    1483             :                                         return 0.0;
    1484             :                                 else
    1485             :                                         return -0.0;
    1486             :                         }
    1487             :                 }
    1488             : 
    1489             :         } else {
    1490             :                 if (isnanf(a)) {
    1491             :                         /* If either value1' or value2' is NaN, the result is NaN. */
    1492             : 
    1493             :                         return intBitsToFloat(FLT_NAN);
    1494             : 
    1495             :                 } else if (finitef(b)) {
    1496             :                         /* Division of an infinity by a finite value results in a signed */
    1497             :                         /* infinity, with the sign-producing rule just given. */
    1498             : 
    1499             :                         /* is sign equal? */
    1500             : 
    1501             :                         if (copysignf(1.0, a) == copysignf(1.0, b))
    1502             :                                 return intBitsToFloat(FLT_POSINF);
    1503             :                         else
    1504             :                                 return intBitsToFloat(FLT_NEGINF);
    1505             : 
    1506             :                 } else {
    1507             :                         /* Division of an infinity by an infinity results in NaN. */
    1508             : 
    1509             :                         return intBitsToFloat(FLT_NAN);
    1510             :                 }
    1511             :         }
    1512             : }
    1513             : 
    1514             : 
    1515             : float builtin_fneg(float a)
    1516             : {
    1517             :         if (isnanf(a)) return a;
    1518             :         else {
    1519             :                 if (finitef(a)) return -a;
    1520             :                 else return copysignf(a, -copysignf(1.0, a));
    1521             :         }
    1522             : }
    1523             : #endif /* !SUPPORT_FLOAT */
    1524             : 
    1525             : 
    1526             : #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
    1527             : s4 builtin_fcmpl(float a, float b)
    1528             : {
    1529             :         if (isnanf(a))
    1530             :                 return -1;
    1531             : 
    1532             :         if (isnanf(b))
    1533             :                 return -1;
    1534             : 
    1535             :         if (!finitef(a) || !finitef(b)) {
    1536             :                 a = finitef(a) ? 0 : copysignf(1.0,     a);
    1537             :                 b = finitef(b) ? 0 : copysignf(1.0, b);
    1538             :         }
    1539             : 
    1540             :         if (a > b)
    1541             :                 return 1;
    1542             : 
    1543             :         if (a == b)
    1544             :                 return 0;
    1545             : 
    1546             :         return -1;
    1547             : }
    1548             : 
    1549             : 
    1550             : s4 builtin_fcmpg(float a, float b)
    1551             : {
    1552             :         if (isnanf(a)) return 1;
    1553             :         if (isnanf(b)) return 1;
    1554             :         if (!finitef(a) || !finitef(b)) {
    1555             :                 a = finitef(a) ? 0 : copysignf(1.0, a);
    1556             :                 b = finitef(b) ? 0 : copysignf(1.0, b);
    1557             :         }
    1558             :         if (a > b) return 1;
    1559             :         if (a == b) return 0;
    1560             :         return -1;
    1561             : }
    1562             : #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
    1563             : 
    1564             : 
    1565        1037 : float builtin_frem(float a, float b)
    1566             : {
    1567        1037 :         return fmodf(a, b);
    1568             : }
    1569             : 
    1570             : 
    1571             : /* functions for unsupported double instructions ******************************/
    1572             : 
    1573             : #if !SUPPORT_DOUBLE
    1574             : double builtin_dadd(double a, double b)
    1575             : {
    1576             :         if (isnan(a)) return longBitsToDouble(DBL_NAN);
    1577             :         if (isnan(b)) return longBitsToDouble(DBL_NAN);
    1578             :         if (finite(a)) {
    1579             :                 if (finite(b)) return a + b;
    1580             :                 else return b;
    1581             :         }
    1582             :         else {
    1583             :                 if (finite(b)) return a;
    1584             :                 else {
    1585             :                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
    1586             :                         else return longBitsToDouble(DBL_NAN);
    1587             :                 }
    1588             :         }
    1589             : }
    1590             : 
    1591             : 
    1592             : double builtin_dsub(double a, double b)
    1593             : {
    1594             :         return builtin_dadd(a, builtin_dneg(b));
    1595             : }
    1596             : 
    1597             : 
    1598             : double builtin_dmul(double a, double b)
    1599             : {
    1600             :         if (isnan(a)) return longBitsToDouble(DBL_NAN);
    1601             :         if (isnan(b)) return longBitsToDouble(DBL_NAN);
    1602             :         if (finite(a)) {
    1603             :                 if (finite(b)) return a * b;
    1604             :                 else {
    1605             :                         if (a == 0) return longBitsToDouble(DBL_NAN);
    1606             :                         else return copysign(b, copysign(1.0, b) * a);
    1607             :                 }
    1608             :         }
    1609             :         else {
    1610             :                 if (finite(b)) {
    1611             :                         if (b == 0) return longBitsToDouble(DBL_NAN);
    1612             :                         else return copysign(a, copysign(1.0, a) * b);
    1613             :                 }
    1614             :                 else {
    1615             :                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
    1616             :                 }
    1617             :         }
    1618             : }
    1619             : 
    1620             : 
    1621             : /* builtin_ddiv ****************************************************************
    1622             : 
    1623             :    Implementation as described in VM Spec.
    1624             : 
    1625             : *******************************************************************************/
    1626             : 
    1627             : double builtin_ddiv(double a, double b)
    1628             : {
    1629             :         if (finite(a)) {
    1630             :                 if (finite(b)) {
    1631             :                         /* If neither value1' nor value2' is NaN, the sign of the result */
    1632             :                         /* is positive if both values have the same sign, negative if the */
    1633             :                         /* values have different signs. */
    1634             : 
    1635             :                         return a / b;
    1636             : 
    1637             :                 } else {
    1638             :                         if (isnan(b)) {
    1639             :                                 /* If either value1' or value2' is NaN, the result is NaN. */
    1640             : 
    1641             :                                 return longBitsToDouble(DBL_NAN);
    1642             : 
    1643             :                         } else {
    1644             :                                 /* Division of a finite value by an infinity results in a */
    1645             :                                 /* signed zero, with the sign-producing rule just given. */
    1646             : 
    1647             :                                 /* is sign equal? */
    1648             : 
    1649             :                                 if (copysign(1.0, a) == copysign(1.0, b))
    1650             :                                         return 0.0;
    1651             :                                 else
    1652             :                                         return -0.0;
    1653             :                         }
    1654             :                 }
    1655             : 
    1656             :         } else {
    1657             :                 if (isnan(a)) {
    1658             :                         /* If either value1' or value2' is NaN, the result is NaN. */
    1659             : 
    1660             :                         return longBitsToDouble(DBL_NAN);
    1661             : 
    1662             :                 } else if (finite(b)) {
    1663             :                         /* Division of an infinity by a finite value results in a signed */
    1664             :                         /* infinity, with the sign-producing rule just given. */
    1665             : 
    1666             :                         /* is sign equal? */
    1667             : 
    1668             :                         if (copysign(1.0, a) == copysign(1.0, b))
    1669             :                                 return longBitsToDouble(DBL_POSINF);
    1670             :                         else
    1671             :                                 return longBitsToDouble(DBL_NEGINF);
    1672             : 
    1673             :                 } else {
    1674             :                         /* Division of an infinity by an infinity results in NaN. */
    1675             : 
    1676             :                         return longBitsToDouble(DBL_NAN);
    1677             :                 }
    1678             :         }
    1679             : }
    1680             : 
    1681             : 
    1682             : /* builtin_dneg ****************************************************************
    1683             : 
    1684             :    Implemented as described in VM Spec.
    1685             : 
    1686             : *******************************************************************************/
    1687             : 
    1688             : double builtin_dneg(double a)
    1689             : {
    1690             :         if (isnan(a)) {
    1691             :                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
    1692             :                 /* sign). */
    1693             : 
    1694             :                 return a;
    1695             : 
    1696             :         } else {
    1697             :                 if (finite(a)) {
    1698             :                         /* If the operand is a zero, the result is the zero of opposite */
    1699             :                         /* sign. */
    1700             : 
    1701             :                         return -a;
    1702             : 
    1703             :                 } else {
    1704             :                         /* If the operand is an infinity, the result is the infinity of */
    1705             :                         /* opposite sign. */
    1706             : 
    1707             :                         return copysign(a, -copysign(1.0, a));
    1708             :                 }
    1709             :         }
    1710             : }
    1711             : #endif /* !SUPPORT_DOUBLE */
    1712             : 
    1713             : 
    1714             : #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
    1715             : s4 builtin_dcmpl(double a, double b)
    1716             : {
    1717             :         if (isnan(a))
    1718             :                 return -1;
    1719             : 
    1720             :         if (isnan(b))
    1721             :                 return -1;
    1722             : 
    1723             :         if (!finite(a) || !finite(b)) {
    1724             :                 a = finite(a) ? 0 : copysign(1.0, a);
    1725             :                 b = finite(b) ? 0 : copysign(1.0, b);
    1726             :         }
    1727             : 
    1728             :         if (a > b)
    1729             :                 return 1;
    1730             : 
    1731             :         if (a == b)
    1732             :                 return 0;
    1733             : 
    1734             :         return -1;
    1735             : }
    1736             : 
    1737             : 
    1738             : s4 builtin_dcmpg(double a, double b)
    1739             : {
    1740             :         if (isnan(a))
    1741             :                 return 1;
    1742             : 
    1743             :         if (isnan(b))
    1744             :                 return 1;
    1745             : 
    1746             :         if (!finite(a) || !finite(b)) {
    1747             :                 a = finite(a) ? 0 : copysign(1.0, a);
    1748             :                 b = finite(b) ? 0 : copysign(1.0, b);
    1749             :         }
    1750             : 
    1751             :         if (a > b)
    1752             :                 return 1;
    1753             : 
    1754             :         if (a == b)
    1755             :                 return 0;
    1756             : 
    1757             :         return -1;
    1758             : }
    1759             : #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
    1760             : 
    1761             : 
    1762          35 : double builtin_drem(double a, double b)
    1763             : {
    1764          35 :         return fmod(a, b);
    1765             : }
    1766             : 
    1767             : 
    1768             : /* conversion operations ******************************************************/
    1769             : 
    1770             : #if !(SUPPORT_FLOAT && SUPPORT_I2F)
    1771             : float builtin_i2f(s4 a)
    1772             : {
    1773             :         float f = (float) a;
    1774             :         return f;
    1775             : }
    1776             : #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
    1777             : 
    1778             : 
    1779             : #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
    1780             : double builtin_i2d(s4 a)
    1781             : {
    1782             :         double d = (double) a;
    1783             :         return d;
    1784             : }
    1785             : #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
    1786             : 
    1787             : 
    1788             : #if !(SUPPORT_FLOAT && SUPPORT_L2F)
    1789             : float builtin_l2f(s8 a)
    1790             : {
    1791             :         float f = (float) a;
    1792             :         return f;
    1793             : }
    1794             : #endif
    1795             : 
    1796             : 
    1797             : #if !(SUPPORT_DOUBLE && SUPPORT_L2D)
    1798             : double builtin_l2d(s8 a)
    1799             : {
    1800             :         double d = (double) a;
    1801             :         return d;
    1802             : }
    1803             : #endif
    1804             : 
    1805             : 
    1806             : #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
    1807      106868 : s4 builtin_f2i(float a) 
    1808             : {
    1809             :         s4 i;
    1810             : 
    1811      106868 :         i = builtin_d2i((double) a);
    1812             : 
    1813      106868 :         return i;
    1814             : 
    1815             :         /*      float f;
    1816             :         
    1817             :                 if (isnanf(a))
    1818             :                 return 0;
    1819             :                 if (finitef(a)) {
    1820             :                 if (a > 2147483647)
    1821             :                 return 2147483647;
    1822             :                 if (a < (-2147483648))
    1823             :                 return (-2147483648);
    1824             :                 return (s4) a;
    1825             :                 }
    1826             :                 f = copysignf((float) 1.0, a);
    1827             :                 if (f > 0)
    1828             :                 return 2147483647;
    1829             :                 return (-2147483648); */
    1830             : }
    1831             : #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
    1832             : 
    1833             : 
    1834             : #if !(SUPPORT_FLOAT && SUPPORT_F2L) || defined(DISABLE_GC)
    1835          24 : s8 builtin_f2l(float a)
    1836             : {
    1837             :         s8 l;
    1838             : 
    1839          24 :         l = builtin_d2l((double) a);
    1840             : 
    1841          24 :         return l;
    1842             : 
    1843             :         /*      float f;
    1844             :         
    1845             :                 if (finitef(a)) {
    1846             :                 if (a > 9223372036854775807L)
    1847             :                 return 9223372036854775807L;
    1848             :                 if (a < (-9223372036854775808L))
    1849             :                 return (-9223372036854775808L);
    1850             :                 return (s8) a;
    1851             :                 }
    1852             :                 if (isnanf(a))
    1853             :                 return 0;
    1854             :                 f = copysignf((float) 1.0, a);
    1855             :                 if (f > 0)
    1856             :                 return 9223372036854775807L;
    1857             :                 return (-9223372036854775808L); */
    1858             : }
    1859             : #endif
    1860             : 
    1861             : 
    1862             : #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
    1863      106916 : s4 builtin_d2i(double a) 
    1864             : { 
    1865             :         double d;
    1866             :         
    1867      106916 :         if (finite(a)) {
    1868      106910 :                 if (a >= 2147483647)
    1869          13 :                         return 2147483647;
    1870      106897 :                 if (a <= (-2147483647-1))
    1871          11 :                         return (-2147483647-1);
    1872      106886 :                 return (s4) a;
    1873             :         }
    1874           6 :         if (isnan(a))
    1875           2 :                 return 0;
    1876           4 :         d = copysign(1.0, a);
    1877           4 :         if (d > 0)
    1878           2 :                 return 2147483647;
    1879           2 :         return (-2147483647-1);
    1880             : }
    1881             : #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
    1882             : 
    1883             : 
    1884             : #if !(SUPPORT_DOUBLE && SUPPORT_D2L) || defined(DISABLE_GC)
    1885          48 : s8 builtin_d2l(double a)
    1886             : {
    1887             :         double d;
    1888             :         
    1889          48 :         if (finite(a)) {
    1890          42 :                 if (a >= 9223372036854775807LL)
    1891           8 :                         return 9223372036854775807LL;
    1892          34 :                 if (a <= (-9223372036854775807LL-1))
    1893           6 :                         return (-9223372036854775807LL-1);
    1894          28 :                 return (s8) a;
    1895             :         }
    1896           6 :         if (isnan(a))
    1897           2 :                 return 0;
    1898           4 :         d = copysign(1.0, a);
    1899           4 :         if (d > 0)
    1900           2 :                 return 9223372036854775807LL;
    1901           2 :         return (-9223372036854775807LL-1);
    1902             : }
    1903             : #endif
    1904             : 
    1905             : 
    1906             : #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
    1907             : double builtin_f2d(float a)
    1908             : {
    1909             :         if (finitef(a)) return (double) a;
    1910             :         else {
    1911             :                 if (isnanf(a))
    1912             :                         return longBitsToDouble(DBL_NAN);
    1913             :                 else
    1914             :                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
    1915             :         }
    1916             : }
    1917             : 
    1918             : float builtin_d2f(double a)
    1919             : {
    1920             :         if (finite(a))
    1921             :                 return (float) a;
    1922             :         else {
    1923             :                 if (isnan(a))
    1924             :                         return intBitsToFloat(FLT_NAN);
    1925             :                 else
    1926             :                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
    1927             :         }
    1928             : }
    1929             : #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
    1930             : 
    1931             : 
    1932             : /*============================================================================*/
    1933             : /* AUTOMATICALLY REPLACED FUNCTIONS                                           */
    1934             : /*============================================================================*/
    1935             : 
    1936             : /* builtin_arraycopy ***********************************************************
    1937             : 
    1938             :    Builtin for java.lang.System.arraycopy.
    1939             : 
    1940             :    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
    1941             : 
    1942             : *******************************************************************************/
    1943             : 
    1944      478504 : void builtin_arraycopy(java_handle_t *src, s4 srcStart,
    1945             :                                            java_handle_t *dest, s4 destStart, s4 len)
    1946             : {
    1947             :         arraydescriptor *sdesc;
    1948             :         arraydescriptor *ddesc;
    1949             :         s4               i;
    1950             : 
    1951      478504 :         if ((src == NULL) || (dest == NULL)) {
    1952           1 :                 exceptions_throw_nullpointerexception();
    1953           1 :                 return;
    1954             :         }
    1955             : 
    1956      478503 :         Array sa(src);
    1957      478503 :         Array da(dest);
    1958             : 
    1959      478503 :         sdesc = LLNI_vftbl_direct(src)->arraydesc;
    1960      478503 :         ddesc = LLNI_vftbl_direct(dest)->arraydesc;
    1961             : 
    1962      478503 :         if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
    1963           0 :                 exceptions_throw_arraystoreexception();
    1964             :                 return;
    1965             :         }
    1966             : 
    1967             :         // Check if offsets and length are positive.
    1968      478503 :         if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
    1969           0 :                 exceptions_throw_arrayindexoutofboundsexception();
    1970             :                 return;
    1971             :         }
    1972             : 
    1973             :         // Check if ranges are valid.
    1974      478503 :         if ((((uint32_t) srcStart  + (uint32_t) len) > (uint32_t) sa.get_length()) ||
    1975             :                 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) da.get_length())) {
    1976           1 :                 exceptions_throw_arrayindexoutofboundsexception();
    1977             :                 return;
    1978             :         }
    1979             : 
    1980             :         // Special case.
    1981      478502 :         if (len == 0) {
    1982             :                 return;
    1983             :         }
    1984             : 
    1985      461448 :         if (sdesc->componentvftbl == ddesc->componentvftbl) {
    1986             :                 /* We copy primitive values or references of exactly the same type */
    1987             : 
    1988      459241 :                 s4 dataoffset = sdesc->dataoffset;
    1989      459241 :                 s4 componentsize = sdesc->componentsize;
    1990             : 
    1991             :                 LLNI_CRITICAL_START;
    1992             : 
    1993             :                 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
    1994             :                           ((u1 *) LLNI_DIRECT(src))  + dataoffset + componentsize * srcStart,
    1995      459241 :                           u1, (size_t) len * componentsize);
    1996             : 
    1997             :                 LLNI_CRITICAL_END;
    1998             :         }
    1999             :         else {
    2000             :                 /* We copy references of different type */
    2001             : 
    2002        2207 :                 ObjectArray oas((java_handle_objectarray_t*) src);
    2003        2207 :                 ObjectArray oad((java_handle_objectarray_t*) dest);
    2004             :  
    2005        2207 :                 if (destStart <= srcStart) {
    2006       12615 :                         for (i = 0; i < len; i++) {
    2007       10409 :                                 java_handle_t* o = oas.get_element(srcStart + i);
    2008             : 
    2009       10409 :                                 if (!builtin_canstore(oad.get_handle(), o))
    2010             :                                         return;
    2011             : 
    2012       10408 :                                 oad.set_element(destStart + i, o);
    2013             :                         }
    2014             :                 }
    2015             :                 else {
    2016             :                         /* XXX this does not completely obey the specification!
    2017             :                            If an exception is thrown only the elements above the
    2018             :                            current index have been copied. The specification
    2019             :                            requires that only the elements *below* the current
    2020             :                            index have been copied before the throw. */
    2021             : 
    2022           0 :                         for (i = len - 1; i >= 0; i--) {
    2023           0 :                                 java_handle_t* o = oas.get_element(srcStart + i);
    2024             : 
    2025           0 :                                 if (!builtin_canstore(oad.get_handle(), o))
    2026             :                                         return;
    2027             : 
    2028           0 :                                 oad.set_element(destStart + i, o);
    2029             :                         }
    2030           0 :                 }
    2031           0 :         }
    2032             : }
    2033             : 
    2034             : 
    2035             : /* builtin_nanotime ************************************************************
    2036             : 
    2037             :    Return the current time in nanoseconds.
    2038             : 
    2039             : *******************************************************************************/
    2040             : 
    2041         335 : s8 builtin_nanotime(void)
    2042             : {
    2043             :         struct timeval tv;
    2044             :         s8             usecs;
    2045             : 
    2046         335 :         if (gettimeofday(&tv, NULL) == -1)
    2047           0 :                 vm_abort("gettimeofday failed: %s", strerror(errno));
    2048             : 
    2049         335 :         usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
    2050             : 
    2051         335 :         return usecs * 1000;
    2052             : }
    2053             : 
    2054             : 
    2055             : /* builtin_currenttimemillis ***************************************************
    2056             : 
    2057             :    Return the current time in milliseconds.
    2058             : 
    2059             : *******************************************************************************/
    2060             : 
    2061         335 : s8 builtin_currenttimemillis(void)
    2062             : {
    2063             :         s8 msecs;
    2064             : 
    2065         335 :         msecs = builtin_nanotime() / 1000 / 1000;
    2066             : 
    2067         335 :         return msecs;
    2068             : }
    2069             : 
    2070             : 
    2071             : /* builtin_clone ***************************************************************
    2072             : 
    2073             :    Function for cloning objects or arrays.
    2074             : 
    2075             :    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
    2076             : 
    2077             : *******************************************************************************/
    2078             : 
    2079        1419 : java_handle_t *builtin_clone(void *env, java_handle_t *o)
    2080             : {
    2081             :         arraydescriptor *ad;
    2082             :         u4               size;
    2083             :         classinfo       *c;
    2084             :         java_handle_t   *co;                /* cloned object header               */
    2085             : 
    2086             :         /* get the array descriptor */
    2087             : 
    2088        1419 :         ad = LLNI_vftbl_direct(o)->arraydesc;
    2089             : 
    2090             :         /* we are cloning an array */
    2091             : 
    2092        1419 :         if (ad != NULL) {
    2093        1004 :                 Array a(o);
    2094             : 
    2095        1004 :                 size = ad->dataoffset + ad->componentsize * a.get_length();
    2096             :         
    2097        1004 :                 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
    2098             : 
    2099        1004 :                 if (co == NULL)
    2100           1 :                         return NULL;
    2101             : 
    2102             : #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
    2103             :                 /* XXX this is only a dirty hack to make Boehm work with handles */
    2104             : 
    2105             :                 co = LLNI_WRAP((java_object_t *) co);
    2106             : #endif
    2107             : 
    2108             :                 LLNI_CRITICAL_START;
    2109             : 
    2110        1003 :                 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
    2111             : 
    2112             : #if defined(ENABLE_GC_CACAO)
    2113             :                 heap_init_objectheader(LLNI_DIRECT(co), size);
    2114             : #endif
    2115             : 
    2116        1003 :                 Lockword(LLNI_DIRECT(co)->lockword).init();
    2117             : 
    2118             :                 LLNI_CRITICAL_END;
    2119             : 
    2120        1003 :                 return co;
    2121             :         }
    2122             :     
    2123             :     /* we are cloning a non-array */
    2124             : 
    2125         415 :     if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
    2126           0 :         exceptions_throw_clonenotsupportedexception();
    2127           0 :         return NULL;
    2128             :     }
    2129             : 
    2130             :         /* get the class of the object */
    2131             : 
    2132         415 :         LLNI_class_get(o, c);
    2133             : 
    2134             :         /* create new object */
    2135             : 
    2136         415 :     co = builtin_new(c);
    2137             : 
    2138         415 :     if (co == NULL)
    2139           0 :         return NULL;
    2140             : 
    2141             :         LLNI_CRITICAL_START;
    2142             : 
    2143         415 :         MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
    2144             : 
    2145             : #if defined(ENABLE_GC_CACAO)
    2146             :         heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
    2147             : #endif
    2148             : 
    2149         415 :         Lockword(LLNI_DIRECT(co)->lockword).init();
    2150             : 
    2151             :         LLNI_CRITICAL_END;
    2152             : 
    2153         415 :     return co;
    2154         495 : }
    2155             : 
    2156             : 
    2157             : #if defined(ENABLE_CYCLES_STATS)
    2158             : void builtin_print_cycles_stats(FILE *file)
    2159             : {
    2160             :         fprintf(file,"builtin cylce count statistics:\n");
    2161             : 
    2162             :         CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
    2163             :         CYCLES_STATS_PRINT(builtin_new         ,file);
    2164             : 
    2165             :         fprintf(file,"\n");
    2166             : }
    2167             : #endif /* defined(ENABLE_CYCLES_STATS) */
    2168             : 
    2169             : 
    2170             : /*
    2171             :  * These are local overrides for various environment variables in Emacs.
    2172             :  * Please do not remove this and leave it at the end of the file, where
    2173             :  * Emacs will automagically detect them.
    2174             :  * ---------------------------------------------------------------------
    2175             :  * Local variables:
    2176             :  * mode: c++
    2177             :  * indent-tabs-mode: t
    2178             :  * c-basic-offset: 4
    2179             :  * tab-width: 4
    2180             :  * End:
    2181             :  * vim:noexpandtab:sw=4:ts=4:
    2182             :  */

Generated by: LCOV version 1.11