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: 2017-07-14 10:03:36 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    21207409 :         while (entries > 0) {
     311    12382305 :                 half = entries / 2;
     312    12382305 :                 middle = first + half;
     313             : 
     314    12382305 :                 if (middle->opcode < opcode) {
     315     1710675 :                         first = middle + 1;
     316     1710675 :                         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 (*(vftbl_t **) ((uint8_t *) s + t->subtype_offset) == t)
     610             :                 // same as:
     611             :                 // s->subtype_display[std::min(t->subtype_depth, DISPLAY_SIZE)]
     612      200951 :                 return true;
     613          78 :    if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
     614          43 :        return false;
     615          35 :    return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
     616             : }
     617             : #endif
     618             : 
     619             : /* builtin_fast_canstore *******************************************************
     620             : 
     621             :    Checks, if an object can be stored in an array.
     622             : 
     623             :    RETURN VALUE:
     624             :       1......possible
     625             :       0......otherwise (no exception thrown!)
     626             : 
     627             :    NOTE: This is a FAST builtin and can be called from JIT code only.
     628             : 
     629             : *******************************************************************************/
     630             : 
     631     7784817 : bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
     632             : {
     633             :         arraydescriptor *desc;
     634             :         arraydescriptor *valuedesc;
     635             :         vftbl_t         *componentvftbl;
     636             :         vftbl_t         *valuevftbl;
     637             :         int32_t          baseval;
     638             :         bool             result;
     639             : 
     640     7784817 :         if (o == NULL)
     641     7037203 :                 return 1;
     642             : 
     643             :         /* The following is guaranteed (by verifier checks):
     644             :          *
     645             :          *     *) oa->...vftbl->arraydesc != NULL
     646             :          *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
     647             :          *     *) o->vftbl is not an interface vftbl
     648             :          */
     649             : 
     650      747614 :         desc           = oa->header.objheader.vftbl->arraydesc;
     651      747614 :         componentvftbl = desc->componentvftbl;
     652      747614 :         valuevftbl     = o->vftbl;
     653      747614 :         valuedesc      = valuevftbl->arraydesc;
     654             : 
     655      747614 :         if ((desc->dimension - 1) == 0) {
     656             :                 /* {oa is a one-dimensional array} */
     657             :                 /* {oa is an array of references} */
     658             :                 
     659      423724 :                 if (valuevftbl == componentvftbl)
     660      335545 :                         return 1;
     661             : 
     662             :                 LOCK_CLASSRENUMBER_LOCK;
     663             : 
     664       88179 :                 baseval = componentvftbl->baseval;
     665             : 
     666       88179 :                 if (baseval <= 0) {
     667             :                         /* an array of interface references */
     668             : 
     669             :                         result = ((valuevftbl->interfacetablelength > -baseval) &&
     670        1171 :                                           (valuevftbl->interfacetable[baseval] != NULL));
     671             :                 }
     672             :                 else {
     673             : #if USES_NEW_SUBTYPE
     674       87008 :                         result = fast_subtype_check(valuevftbl, componentvftbl);
     675             : #else
     676             :                         uint32_t diffval = valuevftbl->baseval - componentvftbl->baseval;
     677             :                         result = diffval <= (uint32_t) componentvftbl->diffval;
     678             : #endif
     679             :                 }
     680             : 
     681             :                 UNLOCK_CLASSRENUMBER_LOCK;
     682             :         }
     683      323890 :         else if (valuedesc == NULL) {
     684             :                 /* {oa has dimension > 1} */
     685             :                 /* {componentvftbl->arraydesc != NULL} */
     686             : 
     687             :                 /* check if o is an array */
     688             : 
     689           0 :                 return 0;
     690             :         }
     691             :         else {
     692             :                 /* {o is an array} */
     693             : 
     694      323890 :                 result = class_is_arraycompatible(valuedesc, componentvftbl->arraydesc);
     695             :         }
     696             : 
     697             :         /* return result */
     698             : 
     699      412069 :         return result;
     700             : }
     701             : 
     702             : 
     703             : /* This is an optimized version where a is guaranteed to be one-dimensional */
     704           0 : bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
     705             : {
     706             :         arraydescriptor *desc;
     707             :         vftbl_t         *elementvftbl;
     708             :         vftbl_t         *valuevftbl;
     709             :         int32_t          baseval;
     710             :         bool             result;
     711             :         
     712           0 :         if (o == NULL)
     713           0 :                 return 1;
     714             : 
     715             :         /* The following is guaranteed (by verifier checks):
     716             :          *
     717             :          *     *) a->...vftbl->arraydesc != NULL
     718             :          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
     719             :          *     *) a->...vftbl->arraydesc->dimension == 1
     720             :          *     *) o->vftbl is not an interface vftbl
     721             :          */
     722             : 
     723           0 :         desc = a->header.objheader.vftbl->arraydesc;
     724           0 :     elementvftbl = desc->elementvftbl;
     725           0 :         valuevftbl = o->vftbl;
     726             : 
     727             :         /* {a is a one-dimensional array} */
     728             :         
     729           0 :         if (valuevftbl == elementvftbl)
     730           0 :                 return 1;
     731             : 
     732             :         LOCK_CLASSRENUMBER_LOCK;
     733             : 
     734           0 :         baseval = elementvftbl->baseval;
     735             : 
     736           0 :         if (baseval <= 0) {
     737             :                 /* an array of interface references */
     738             :                 result = ((valuevftbl->interfacetablelength > -baseval) &&
     739           0 :                                   (valuevftbl->interfacetable[baseval] != NULL));
     740             :         }
     741             :         else {
     742             : #if USES_NEW_SUBTYPE
     743           0 :                 result = fast_subtype_check(valuevftbl, elementvftbl);
     744             : #else
     745             :                 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
     746             :                 result = diffval <= (uint32_t) elementvftbl->diffval;
     747             : #endif
     748             :         }
     749             : 
     750             :         UNLOCK_CLASSRENUMBER_LOCK;
     751             : 
     752           0 :         return result;
     753             : }
     754             : 
     755             : 
     756             : /* This is an optimized version where a is guaranteed to be a
     757             :  * one-dimensional array of a class type */
     758           0 : bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
     759             : {
     760             :         vftbl_t *elementvftbl;
     761             :         vftbl_t *valuevftbl;
     762             :         bool     result;
     763             :         
     764           0 :         if (o == NULL)
     765           0 :                 return 1;
     766             : 
     767             :         /* The following is guaranteed (by verifier checks):
     768             :          *
     769             :          *     *) a->...vftbl->arraydesc != NULL
     770             :          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
     771             :          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
     772             :          *     *) a->...vftbl->arraydesc->dimension == 1
     773             :          *     *) o->vftbl is not an interface vftbl
     774             :          */
     775             : 
     776           0 :     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
     777           0 :         valuevftbl = o->vftbl;
     778             : 
     779             :         /* {a is a one-dimensional array} */
     780             :         
     781           0 :         if (valuevftbl == elementvftbl)
     782           0 :                 return 1;
     783             : 
     784             :         LOCK_CLASSRENUMBER_LOCK;
     785             : 
     786             : #if USES_NEW_SUBTYPE
     787           0 :         result = fast_subtype_check(valuevftbl, elementvftbl);
     788             : #else
     789             :         uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
     790             :         result = diffval <= (uint32_t) elementvftbl->diffval;
     791             : #endif
     792             : 
     793             :         UNLOCK_CLASSRENUMBER_LOCK;
     794             : 
     795           0 :         return result;
     796             : }
     797             : 
     798             : // register boot real-time group
     799             : RT_REGISTER_GROUP(buildin_group,"boot","boot group")
     800             : 
     801             : // register real-time timers
     802             : RT_REGISTER_GROUP_TIMER(bi_new_timer,"buildin","builtin_new time",buildin_group)
     803             : RT_REGISTER_GROUP_TIMER(bi_newa_timer,"buildin","builtin_newarray time",buildin_group)
     804             : 
     805             : /* builtin_new *****************************************************************
     806             : 
     807             :    Creates a new instance of class c on the heap.
     808             : 
     809             :    RETURN VALUE:
     810             :       pointer to the object, or NULL if no memory is available
     811             : 
     812             :    NOTE: This builtin can be called from NATIVE code only.
     813             : 
     814             : *******************************************************************************/
     815             : 
     816     1184315 : java_handle_t *builtin_new(classinfo *c)
     817             : {
     818             :         java_handle_t *o;
     819             : #if defined(ENABLE_CYCLES_STATS)
     820             :         u8 cycles_start, cycles_end;
     821             : #endif
     822             : 
     823             :         RT_TIMER_START(bi_new_timer);
     824             :         CYCLES_STATS_GET(cycles_start);
     825             : 
     826             :         /* is the class loaded */
     827             : 
     828     1184315 :         assert(c->state & CLASS_LOADED);
     829             : 
     830             :         /* check if we can instantiate this class */
     831             : 
     832     1184315 :         if (c->flags & ACC_ABSTRACT) {
     833           0 :                 exceptions_throw_instantiationerror(c);
     834           0 :                 return NULL;
     835             :         }
     836             : 
     837             :         /* is the class linked */
     838             : 
     839     1184315 :         if (!(c->state & CLASS_LINKED))
     840          75 :                 if (!link_class(c))
     841           0 :                         return NULL;
     842             : 
     843     1184315 :         if (!(c->state & CLASS_INITIALIZED)) {
     844             : #if !defined(NDEBUG)
     845       82184 :                 if (initverbose)
     846           0 :                         log_message_class("Initialize class (from builtin_new): ", c);
     847             : #endif
     848             : 
     849       82184 :                 if (!initialize_class(c))
     850           0 :                         return NULL;
     851             :         }
     852             : 
     853             :         o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
     854     1184315 :                                                                         c->finalizer, true);
     855             : 
     856     1184315 :         if (!o)
     857           0 :                 return NULL;
     858             : 
     859             : #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
     860             :         /* XXX this is only a dirty hack to make Boehm work with handles */
     861             : 
     862             :         o = LLNI_WRAP((java_object_t *) o);
     863             : #endif
     864             : 
     865     1184315 :         LLNI_vftbl_direct(o) = c->vftbl;
     866             : 
     867     1184315 :         Lockword(LLNI_DIRECT(o)->lockword).init();
     868             : 
     869             :         CYCLES_STATS_GET(cycles_end);
     870             :         RT_TIMER_STOP(bi_new_timer);
     871             : 
     872             :         CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
     873             : 
     874     1184315 :         return o;
     875             : }
     876             : 
     877             : #if defined(ENABLE_ESCAPE_REASON)
     878             : java_handle_t *builtin_escape_reason_new(classinfo *c) {
     879             :         print_escape_reasons();
     880             :         return builtin_java_new(c);
     881             : }
     882             : #endif
     883             : 
     884             : #if defined(ENABLE_TLH)
     885             : java_handle_t *builtin_tlh_new(classinfo *c)
     886             : {
     887             :         java_handle_t *o;
     888             : # if defined(ENABLE_CYCLES_STATS)
     889             :         u8 cycles_start, cycles_end;
     890             : # endif
     891             : 
     892             :         CYCLES_STATS_GET(cycles_start);
     893             : 
     894             :         /* is the class loaded */
     895             : 
     896             :         assert(c->state & CLASS_LOADED);
     897             : 
     898             :         /* check if we can instantiate this class */
     899             : 
     900             :         if (c->flags & ACC_ABSTRACT) {
     901             :                 exceptions_throw_instantiationerror(c);
     902             :                 return NULL;
     903             :         }
     904             : 
     905             :         /* is the class linked */
     906             : 
     907             :         if (!(c->state & CLASS_LINKED))
     908             :                 if (!link_class(c))
     909             :                         return NULL;
     910             : 
     911             :         if (!(c->state & CLASS_INITIALIZED)) {
     912             : # if !defined(NDEBUG)
     913             :                 if (initverbose)
     914             :                         log_message_class("Initialize class (from builtin_new): ", c);
     915             : # endif
     916             : 
     917             :                 if (!initialize_class(c))
     918             :                         return NULL;
     919             :         }
     920             : 
     921             :         /*
     922             :         o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
     923             :         */
     924             :         o = NULL;
     925             : 
     926             :         if (o == NULL) {
     927             :                 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
     928             :                                                                                 c->finalizer, true);
     929             :         }
     930             : 
     931             :         if (!o)
     932             :                 return NULL;
     933             : 
     934             : # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
     935             :         /* XXX this is only a dirty hack to make Boehm work with handles */
     936             : 
     937             :         o = LLNI_WRAP((java_object_t *) o);
     938             : # endif
     939             : 
     940             :         LLNI_vftbl_direct(o) = c->vftbl;
     941             : 
     942             :         Lockword(LLNI_DIRECT(o)->lockword).init();
     943             : 
     944             :         CYCLES_STATS_GET(cycles_end);
     945             : 
     946             : /*
     947             :         CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
     948             :         TODO port to new rt-timing
     949             :         RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
     950             : */
     951             : 
     952             :         return o;
     953             : }
     954             : #endif
     955             : 
     956             : 
     957             : /* builtin_java_new ************************************************************
     958             : 
     959             :    NOTE: This is a SLOW builtin and can be called from JIT code only.
     960             : 
     961             : *******************************************************************************/
     962             : 
     963     1097710 : java_handle_t *builtin_java_new(java_handle_t *clazz)
     964             : {
     965     1097710 :         return builtin_new(LLNI_classinfo_unwrap(clazz));
     966             : }
     967             : 
     968             : 
     969             : /* builtin_fast_new ************************************************************
     970             : 
     971             :    Creates a new instance of class c on the heap.
     972             : 
     973             :    RETURN VALUE:
     974             :       pointer to the object, or NULL if no fast return
     975             :       is possible for any reason.
     976             : 
     977             :    NOTE: This is a FAST builtin and can be called from JIT code only.
     978             : 
     979             : *******************************************************************************/
     980             : 
     981           0 : java_object_t *builtin_fast_new(classinfo *c)
     982             : {
     983             :         java_object_t *o;
     984             : #if defined(ENABLE_CYCLES_STATS)
     985             :         u8 cycles_start, cycles_end;
     986             : #endif
     987             : 
     988             :         CYCLES_STATS_GET(cycles_start);
     989             : 
     990             :         /* is the class loaded */
     991             : 
     992           0 :         assert(c->state & CLASS_LOADED);
     993             : 
     994             :         /* check if we can instantiate this class */
     995             : 
     996           0 :         if (c->flags & ACC_ABSTRACT)
     997           0 :                 return NULL;
     998             : 
     999             :         /* is the class linked */
    1000             : 
    1001           0 :         if (!(c->state & CLASS_LINKED))
    1002           0 :                 return NULL;
    1003             : 
    1004           0 :         if (!(c->state & CLASS_INITIALIZED))
    1005           0 :                 return NULL;
    1006             : 
    1007             :         o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
    1008           0 :                                                                         c->finalizer, false);
    1009             : 
    1010           0 :         if (!o)
    1011           0 :                 return NULL;
    1012             : 
    1013           0 :         o->vftbl = c->vftbl;
    1014             : 
    1015           0 :         Lockword(LLNI_DIRECT(o)->lockword).init();
    1016             : 
    1017             :         CYCLES_STATS_GET(cycles_end);
    1018             : 
    1019             :         CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
    1020             : 
    1021           0 :         return o;
    1022             : }
    1023             : 
    1024             : 
    1025             : /* builtin_java_newarray *******************************************************
    1026             : 
    1027             :    Creates an array with the given vftbl on the heap. This function
    1028             :    takes as class argument an array class.
    1029             : 
    1030             :    RETURN VALUE:
    1031             :       pointer to the array or NULL if no memory is available
    1032             : 
    1033             :    NOTE: This is a SLOW builtin and can be called from JIT code only.
    1034             : 
    1035             : *******************************************************************************/
    1036             : 
    1037       35316 : java_handle_array_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
    1038             : {
    1039             : 
    1040             :         RT_TIMER_START(bi_newa_timer);
    1041             : 
    1042       35316 :         classinfo* arrayclass = LLNI_classinfo_unwrap(arrayclazz);
    1043             : 
    1044             :         // Allocate a new array with given size and class on the heap
    1045       35316 :         Array a(size, arrayclass);
    1046             : 
    1047             :         RT_TIMER_STOP(bi_newa_timer);
    1048             : 
    1049       35316 :         return a.get_handle();
    1050             : }
    1051             : 
    1052             : 
    1053             : /* builtin_newarray_type ****************************************************
    1054             : 
    1055             :    Creates an array of [type]s on the heap.
    1056             :         
    1057             :    RETURN VALUE:
    1058             :       pointer to the array or NULL if no memory is available
    1059             : 
    1060             :    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
    1061             : 
    1062             : *******************************************************************************/
    1063             : 
    1064             : #define BUILTIN_NEWARRAY_TYPE(type, name)                          \
    1065             : java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
    1066             : {                                                                  \
    1067             :         name##Array a(size);                                           \
    1068             :         return a.get_handle();                                         \
    1069             : }
    1070             : 
    1071           0 : BUILTIN_NEWARRAY_TYPE(boolean, Boolean)
    1072      190645 : BUILTIN_NEWARRAY_TYPE(byte,    Byte)
    1073      247178 : BUILTIN_NEWARRAY_TYPE(char,    Char)
    1074        2540 : BUILTIN_NEWARRAY_TYPE(short,   Short)
    1075        1849 : BUILTIN_NEWARRAY_TYPE(int,     Int)
    1076          47 : BUILTIN_NEWARRAY_TYPE(long,    Long)
    1077           9 : BUILTIN_NEWARRAY_TYPE(float,   Float)
    1078           9 : BUILTIN_NEWARRAY_TYPE(double,  Double)
    1079             : 
    1080             : 
    1081             : /* builtin_multianewarray_intern ***********************************************
    1082             : 
    1083             :    Creates a multi-dimensional array on the heap. The dimensions are
    1084             :    passed in an array of longs.
    1085             : 
    1086             :    ARGUMENTS:
    1087             :       n.............number of dimensions to create
    1088             :       arrayclass....the array class
    1089             :       dims..........array containing the size of each dimension to create
    1090             : 
    1091             :    RETURN VALUE:
    1092             :       pointer to the array or NULL if no memory is available
    1093             : 
    1094             : ******************************************************************************/
    1095             : 
    1096         180 : static java_handle_array_t *builtin_multianewarray_intern(int n,
    1097             :                                                                                                         classinfo *arrayclass,
    1098             :                                                                                                         long *dims)
    1099             : {
    1100             :         int32_t i;
    1101             : 
    1102             :         /* create this dimension */
    1103             : 
    1104         180 :         int32_t size = (int32_t) dims[0];
    1105         180 :         Array a(size, arrayclass);
    1106             : 
    1107         180 :         if (a.is_null())
    1108           1 :                 return NULL;
    1109             : 
    1110             :         /* if this is the last dimension return */
    1111             : 
    1112         179 :         if (!--n)
    1113         140 :                 return a.get_handle();
    1114             : 
    1115             :         /* get the class of the components to create */
    1116             : 
    1117          39 :         classinfo* componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
    1118             : 
    1119             :         /* The verifier guarantees that the dimension count is in the range. */
    1120             : 
    1121             :         /* create the component arrays */
    1122             : 
    1123          39 :         ObjectArray oa(a.get_handle());
    1124             : 
    1125         199 :         for (i = 0; i < size; i++) {
    1126             :                 java_handle_array_t *ea =
    1127             : #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
    1128             :                         /* we save an s4 to a s8 slot, 8-byte aligned */
    1129             : 
    1130             :                         builtin_multianewarray_intern(n, componentclass, dims + 2);
    1131             : #else
    1132         160 :                         builtin_multianewarray_intern(n, componentclass, dims + 1);
    1133             : #endif
    1134             : 
    1135         160 :                 if (!ea)
    1136           0 :                         return NULL;
    1137             : 
    1138         160 :                 oa.set_element(i, (java_handle_t*) ea);
    1139             :         }
    1140             : 
    1141          39 :         return a.get_handle();
    1142             : }
    1143             : 
    1144             : 
    1145             : /* builtin_multianewarray ******************************************************
    1146             : 
    1147             :    Wrapper for builtin_multianewarray_intern which checks all
    1148             :    dimensions before we start allocating.
    1149             : 
    1150             :    NOTE: This is a SLOW builtin and can be called from JIT code only.
    1151             : 
    1152             : ******************************************************************************/
    1153             : 
    1154          22 : java_handle_objectarray_t *builtin_multianewarray(int n,
    1155             :                                                                                                   java_handle_t *arrayclazz,
    1156             :                                                                                                   long *dims)
    1157             : {
    1158             :         classinfo *c;
    1159             :         s4         i;
    1160             :         s4         size;
    1161             : 
    1162             :         /* check all dimensions before doing anything */
    1163             : 
    1164          71 :         for (i = 0; i < n; i++) {
    1165             : #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
    1166             :                 /* we save an s4 to a s8 slot, 8-byte aligned */
    1167             :                 size = (s4) dims[i * 2];
    1168             : #else
    1169          51 :                 size = (s4) dims[i];
    1170             : #endif
    1171             : 
    1172          51 :                 if (size < 0) {
    1173           2 :                         exceptions_throw_negativearraysizeexception();
    1174           2 :                         return NULL;
    1175             :                 }
    1176             :         }
    1177             : 
    1178          20 :         c = LLNI_classinfo_unwrap(arrayclazz);
    1179             : 
    1180             :         /* now call the real function */
    1181             : 
    1182             :         return (java_handle_objectarray_t *)
    1183          20 :                 builtin_multianewarray_intern(n, c, dims);
    1184             : }
    1185             : 
    1186             : 
    1187             : /* builtin_verbosecall_enter ***************************************************
    1188             : 
    1189             :    Print method call with arguments for -verbose:call.
    1190             : 
    1191             :    XXX: Remove mew once all archs use the new tracer!
    1192             : 
    1193             : *******************************************************************************/
    1194             : 
    1195             : #if !defined(NDEBUG)
    1196             : #ifdef TRACE_ARGS_NUM
    1197             : void builtin_verbosecall_enter(s8 a0, s8 a1,
    1198             : # if TRACE_ARGS_NUM >= 4
    1199             :                                                            s8 a2, s8 a3,
    1200             : # endif
    1201             : # if TRACE_ARGS_NUM >= 6
    1202             :                                                            s8 a4, s8 a5,
    1203             : # endif
    1204             : # if TRACE_ARGS_NUM == 8
    1205             :                                                            s8 a6, s8 a7,
    1206             : # endif
    1207             :                                                            methodinfo *m)
    1208             : {
    1209             :         log_text("builtin_verbosecall_enter: Do not call me anymore!");
    1210             : }
    1211             : #endif
    1212             : #endif /* !defined(NDEBUG) */
    1213             : 
    1214             : 
    1215             : /* builtin_verbosecall_exit ****************************************************
    1216             : 
    1217             :    Print method exit for -verbose:call.
    1218             : 
    1219             :    XXX: Remove mew once all archs use the new tracer!
    1220             : 
    1221             : *******************************************************************************/
    1222             : 
    1223             : #if !defined(NDEBUG)
    1224           0 : void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
    1225             : {
    1226           0 :         log_text("builtin_verbosecall_exit: Do not call me anymore!");
    1227           0 : }
    1228             : #endif /* !defined(NDEBUG) */
    1229             : 
    1230             : 
    1231             : /*============================================================================*/
    1232             : /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS                                */
    1233             : /*============================================================================*/
    1234             : 
    1235             : /*********** Functions for integer divisions *****************************
    1236             :  
    1237             :         On some systems (eg. DEC ALPHA), integer division is not supported by the
    1238             :         CPU. These helper functions implement the missing functionality.
    1239             : 
    1240             : ******************************************************************************/
    1241             : 
    1242             : #if !SUPPORT_DIVISION || defined(DISABLE_GC)
    1243             : s4 builtin_idiv(s4 a, s4 b)
    1244             : {
    1245             :         s4 c;
    1246             : 
    1247             :         c = a / b;
    1248             : 
    1249             :         return c;
    1250             : }
    1251             : 
    1252             : s4 builtin_irem(s4 a, s4 b)
    1253             : {
    1254             :         s4 c;
    1255             : 
    1256             :         c = a % b;
    1257             : 
    1258             :         return c;
    1259             : }
    1260             : #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
    1261             : 
    1262             : 
    1263             : /* functions for long arithmetics **********************************************
    1264             : 
    1265             :    On systems where 64 bit Integers are not supported by the CPU,
    1266             :    these functions are needed.
    1267             : 
    1268             : ******************************************************************************/
    1269             : 
    1270             : #if !SUPPORT_LONG_ADD
    1271             : s8 builtin_ladd(s8 a, s8 b)
    1272             : {
    1273             :         s8 c;
    1274             : 
    1275             :         c = a + b; 
    1276             : 
    1277             :         return c;
    1278             : }
    1279             : 
    1280             : s8 builtin_lsub(s8 a, s8 b)
    1281             : {
    1282             :         s8 c;
    1283             : 
    1284             :         c = a - b; 
    1285             : 
    1286             :         return c;
    1287             : }
    1288             : 
    1289             : s8 builtin_lneg(s8 a)
    1290             : {
    1291             :         s8 c;
    1292             : 
    1293             :         c = -a;
    1294             : 
    1295             :         return c;
    1296             : }
    1297             : #endif
    1298             : 
    1299             : 
    1300             : #if !SUPPORT_LONG_MUL
    1301             : s8 builtin_lmul(s8 a, s8 b)
    1302             : {
    1303             :         s8 c;
    1304             : 
    1305             :         c = a * b; 
    1306             : 
    1307             :         return c;
    1308             : }
    1309             : #endif
    1310             : 
    1311             : 
    1312             : #if !(SUPPORT_DIVISION && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
    1313             : s8 builtin_ldiv(s8 a, s8 b)
    1314             : {
    1315             :         s8 c;
    1316             : 
    1317             :         c = a / b; 
    1318             : 
    1319             :         return c;
    1320             : }
    1321             : 
    1322             : s8 builtin_lrem(s8 a, s8 b)
    1323             : {
    1324             :         s8 c;
    1325             : 
    1326             :         c = a % b; 
    1327             : 
    1328             :         return c;
    1329             : }
    1330             : #endif
    1331             : 
    1332             : 
    1333             : #if !SUPPORT_LONG_SHIFT
    1334             : s8 builtin_lshl(s8 a, s4 b)
    1335             : {
    1336             :         s8 c;
    1337             : 
    1338             :         c = a << (b & 63);
    1339             : 
    1340             :         return c;
    1341             : }
    1342             : 
    1343             : s8 builtin_lshr(s8 a, s4 b)
    1344             : {
    1345             :         s8 c;
    1346             : 
    1347             :         c = a >> (b & 63);
    1348             : 
    1349             :         return c;
    1350             : }
    1351             : 
    1352             : s8 builtin_lushr(s8 a, s4 b)
    1353             : {
    1354             :         s8 c;
    1355             : 
    1356             :         c = ((u8) a) >> (b & 63);
    1357             : 
    1358             :         return c;
    1359             : }
    1360             : #endif
    1361             : 
    1362             : 
    1363           1 : s4 builtin_lcmp(s8 a, s8 b)
    1364             : { 
    1365           1 :         if (a < b)
    1366           1 :                 return -1;
    1367             : 
    1368           0 :         if (a > b)
    1369           0 :                 return 1;
    1370             : 
    1371           0 :         return 0;
    1372             : }
    1373             : 
    1374             : 
    1375             : /* functions for unsupported floating instructions ****************************/
    1376             : 
    1377             : /* used to convert FLT_xxx defines into float values */
    1378             : 
    1379             : #if !SUPPORT_FLOAT
    1380             : static inline float intBitsToFloat(s4 i)
    1381             : {
    1382             :         imm_union imb;
    1383             : 
    1384             :         imb.i = i;
    1385             :         return imb.f;
    1386             : }
    1387             : #endif
    1388             : 
    1389             : 
    1390             : /* used to convert DBL_xxx defines into double values */
    1391             : 
    1392             : #if !SUPPORT_DOUBLE
    1393             : static inline float longBitsToDouble(s8 l)
    1394             : {
    1395             :         imm_union imb;
    1396             : 
    1397             :         imb.l = l;
    1398             :         return imb.d;
    1399             : }
    1400             : #endif
    1401             : 
    1402             : 
    1403             : #if !SUPPORT_FLOAT
    1404             : float builtin_fadd(float a, float b)
    1405             : {
    1406             :         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
    1407             :         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
    1408             :         if (finitef(a)) {
    1409             :                 if (finitef(b))
    1410             :                         return a + b;
    1411             :                 else
    1412             :                         return b;
    1413             :         }
    1414             :         else {
    1415             :                 if (finitef(b))
    1416             :                         return a;
    1417             :                 else {
    1418             :                         if (copysignf(1.0, a) == copysignf(1.0, b))
    1419             :                                 return a;
    1420             :                         else
    1421             :                                 return intBitsToFloat(FLT_NAN);
    1422             :                 }
    1423             :         }
    1424             : }
    1425             : 
    1426             : 
    1427             : float builtin_fsub(float a, float b)
    1428             : {
    1429             :         return builtin_fadd(a, builtin_fneg(b));
    1430             : }
    1431             : 
    1432             : 
    1433             : float builtin_fmul(float a, float b)
    1434             : {
    1435             :         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
    1436             :         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
    1437             :         if (finitef(a)) {
    1438             :                 if (finitef(b)) return a * b;
    1439             :                 else {
    1440             :                         if (a == 0) return intBitsToFloat(FLT_NAN);
    1441             :                         else return copysignf(b, copysignf(1.0, b)*a);
    1442             :                 }
    1443             :         }
    1444             :         else {
    1445             :                 if (finitef(b)) {
    1446             :                         if (b == 0) return intBitsToFloat(FLT_NAN);
    1447             :                         else return copysignf(a, copysignf(1.0, a)*b);
    1448             :                 }
    1449             :                 else {
    1450             :                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
    1451             :                 }
    1452             :         }
    1453             : }
    1454             : 
    1455             : 
    1456             : /* builtin_ddiv ****************************************************************
    1457             : 
    1458             :    Implementation as described in VM Spec.
    1459             : 
    1460             : *******************************************************************************/
    1461             : 
    1462             : float builtin_fdiv(float a, float b)
    1463             : {
    1464             :         if (finitef(a)) {
    1465             :                 if (finitef(b)) {
    1466             :                         /* If neither value1' nor value2' is NaN, the sign of the result */
    1467             :                         /* is positive if both values have the same sign, negative if the */
    1468             :                         /* values have different signs. */
    1469             : 
    1470             :                         return a / b;
    1471             : 
    1472             :                 } else {
    1473             :                         if (isnanf(b)) {
    1474             :                                 /* If either value1' or value2' is NaN, the result is NaN. */
    1475             : 
    1476             :                                 return intBitsToFloat(FLT_NAN);
    1477             : 
    1478             :                         } else {
    1479             :                                 /* Division of a finite value by an infinity results in a */
    1480             :                                 /* signed zero, with the sign-producing rule just given. */
    1481             : 
    1482             :                                 /* is sign equal? */
    1483             : 
    1484             :                                 if (copysignf(1.0, a) == copysignf(1.0, b))
    1485             :                                         return 0.0;
    1486             :                                 else
    1487             :                                         return -0.0;
    1488             :                         }
    1489             :                 }
    1490             : 
    1491             :         } else {
    1492             :                 if (isnanf(a)) {
    1493             :                         /* If either value1' or value2' is NaN, the result is NaN. */
    1494             : 
    1495             :                         return intBitsToFloat(FLT_NAN);
    1496             : 
    1497             :                 } else if (finitef(b)) {
    1498             :                         /* Division of an infinity by a finite value results in a signed */
    1499             :                         /* infinity, with the sign-producing rule just given. */
    1500             : 
    1501             :                         /* is sign equal? */
    1502             : 
    1503             :                         if (copysignf(1.0, a) == copysignf(1.0, b))
    1504             :                                 return intBitsToFloat(FLT_POSINF);
    1505             :                         else
    1506             :                                 return intBitsToFloat(FLT_NEGINF);
    1507             : 
    1508             :                 } else {
    1509             :                         /* Division of an infinity by an infinity results in NaN. */
    1510             : 
    1511             :                         return intBitsToFloat(FLT_NAN);
    1512             :                 }
    1513             :         }
    1514             : }
    1515             : 
    1516             : 
    1517             : float builtin_fneg(float a)
    1518             : {
    1519             :         if (isnanf(a)) return a;
    1520             :         else {
    1521             :                 if (finitef(a)) return -a;
    1522             :                 else return copysignf(a, -copysignf(1.0, a));
    1523             :         }
    1524             : }
    1525             : #endif /* !SUPPORT_FLOAT */
    1526             : 
    1527             : 
    1528             : #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
    1529             : s4 builtin_fcmpl(float a, float b)
    1530             : {
    1531             :         if (isnanf(a))
    1532             :                 return -1;
    1533             : 
    1534             :         if (isnanf(b))
    1535             :                 return -1;
    1536             : 
    1537             :         if (!finitef(a) || !finitef(b)) {
    1538             :                 a = finitef(a) ? 0 : copysignf(1.0,     a);
    1539             :                 b = finitef(b) ? 0 : copysignf(1.0, b);
    1540             :         }
    1541             : 
    1542             :         if (a > b)
    1543             :                 return 1;
    1544             : 
    1545             :         if (a == b)
    1546             :                 return 0;
    1547             : 
    1548             :         return -1;
    1549             : }
    1550             : 
    1551             : 
    1552             : s4 builtin_fcmpg(float a, float b)
    1553             : {
    1554             :         if (isnanf(a)) return 1;
    1555             :         if (isnanf(b)) return 1;
    1556             :         if (!finitef(a) || !finitef(b)) {
    1557             :                 a = finitef(a) ? 0 : copysignf(1.0, a);
    1558             :                 b = finitef(b) ? 0 : copysignf(1.0, b);
    1559             :         }
    1560             :         if (a > b) return 1;
    1561             :         if (a == b) return 0;
    1562             :         return -1;
    1563             : }
    1564             : #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
    1565             : 
    1566             : 
    1567        1037 : float builtin_frem(float a, float b)
    1568             : {
    1569        1037 :         return fmodf(a, b);
    1570             : }
    1571             : 
    1572             : 
    1573             : /* functions for unsupported double instructions ******************************/
    1574             : 
    1575             : #if !SUPPORT_DOUBLE
    1576             : double builtin_dadd(double a, double b)
    1577             : {
    1578             :         if (isnan(a)) return longBitsToDouble(DBL_NAN);
    1579             :         if (isnan(b)) return longBitsToDouble(DBL_NAN);
    1580             :         if (finite(a)) {
    1581             :                 if (finite(b)) return a + b;
    1582             :                 else return b;
    1583             :         }
    1584             :         else {
    1585             :                 if (finite(b)) return a;
    1586             :                 else {
    1587             :                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
    1588             :                         else return longBitsToDouble(DBL_NAN);
    1589             :                 }
    1590             :         }
    1591             : }
    1592             : 
    1593             : 
    1594             : double builtin_dsub(double a, double b)
    1595             : {
    1596             :         return builtin_dadd(a, builtin_dneg(b));
    1597             : }
    1598             : 
    1599             : 
    1600             : double builtin_dmul(double a, double b)
    1601             : {
    1602             :         if (isnan(a)) return longBitsToDouble(DBL_NAN);
    1603             :         if (isnan(b)) return longBitsToDouble(DBL_NAN);
    1604             :         if (finite(a)) {
    1605             :                 if (finite(b)) return a * b;
    1606             :                 else {
    1607             :                         if (a == 0) return longBitsToDouble(DBL_NAN);
    1608             :                         else return copysign(b, copysign(1.0, b) * a);
    1609             :                 }
    1610             :         }
    1611             :         else {
    1612             :                 if (finite(b)) {
    1613             :                         if (b == 0) return longBitsToDouble(DBL_NAN);
    1614             :                         else return copysign(a, copysign(1.0, a) * b);
    1615             :                 }
    1616             :                 else {
    1617             :                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
    1618             :                 }
    1619             :         }
    1620             : }
    1621             : 
    1622             : 
    1623             : /* builtin_ddiv ****************************************************************
    1624             : 
    1625             :    Implementation as described in VM Spec.
    1626             : 
    1627             : *******************************************************************************/
    1628             : 
    1629             : double builtin_ddiv(double a, double b)
    1630             : {
    1631             :         if (finite(a)) {
    1632             :                 if (finite(b)) {
    1633             :                         /* If neither value1' nor value2' is NaN, the sign of the result */
    1634             :                         /* is positive if both values have the same sign, negative if the */
    1635             :                         /* values have different signs. */
    1636             : 
    1637             :                         return a / b;
    1638             : 
    1639             :                 } else {
    1640             :                         if (isnan(b)) {
    1641             :                                 /* If either value1' or value2' is NaN, the result is NaN. */
    1642             : 
    1643             :                                 return longBitsToDouble(DBL_NAN);
    1644             : 
    1645             :                         } else {
    1646             :                                 /* Division of a finite value by an infinity results in a */
    1647             :                                 /* signed zero, with the sign-producing rule just given. */
    1648             : 
    1649             :                                 /* is sign equal? */
    1650             : 
    1651             :                                 if (copysign(1.0, a) == copysign(1.0, b))
    1652             :                                         return 0.0;
    1653             :                                 else
    1654             :                                         return -0.0;
    1655             :                         }
    1656             :                 }
    1657             : 
    1658             :         } else {
    1659             :                 if (isnan(a)) {
    1660             :                         /* If either value1' or value2' is NaN, the result is NaN. */
    1661             : 
    1662             :                         return longBitsToDouble(DBL_NAN);
    1663             : 
    1664             :                 } else if (finite(b)) {
    1665             :                         /* Division of an infinity by a finite value results in a signed */
    1666             :                         /* infinity, with the sign-producing rule just given. */
    1667             : 
    1668             :                         /* is sign equal? */
    1669             : 
    1670             :                         if (copysign(1.0, a) == copysign(1.0, b))
    1671             :                                 return longBitsToDouble(DBL_POSINF);
    1672             :                         else
    1673             :                                 return longBitsToDouble(DBL_NEGINF);
    1674             : 
    1675             :                 } else {
    1676             :                         /* Division of an infinity by an infinity results in NaN. */
    1677             : 
    1678             :                         return longBitsToDouble(DBL_NAN);
    1679             :                 }
    1680             :         }
    1681             : }
    1682             : 
    1683             : 
    1684             : /* builtin_dneg ****************************************************************
    1685             : 
    1686             :    Implemented as described in VM Spec.
    1687             : 
    1688             : *******************************************************************************/
    1689             : 
    1690             : double builtin_dneg(double a)
    1691             : {
    1692             :         if (isnan(a)) {
    1693             :                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
    1694             :                 /* sign). */
    1695             : 
    1696             :                 return a;
    1697             : 
    1698             :         } else {
    1699             :                 if (finite(a)) {
    1700             :                         /* If the operand is a zero, the result is the zero of opposite */
    1701             :                         /* sign. */
    1702             : 
    1703             :                         return -a;
    1704             : 
    1705             :                 } else {
    1706             :                         /* If the operand is an infinity, the result is the infinity of */
    1707             :                         /* opposite sign. */
    1708             : 
    1709             :                         return copysign(a, -copysign(1.0, a));
    1710             :                 }
    1711             :         }
    1712             : }
    1713             : #endif /* !SUPPORT_DOUBLE */
    1714             : 
    1715             : 
    1716             : #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
    1717             : s4 builtin_dcmpl(double a, double b)
    1718             : {
    1719             :         if (isnan(a))
    1720             :                 return -1;
    1721             : 
    1722             :         if (isnan(b))
    1723             :                 return -1;
    1724             : 
    1725             :         if (!finite(a) || !finite(b)) {
    1726             :                 a = finite(a) ? 0 : copysign(1.0, a);
    1727             :                 b = finite(b) ? 0 : copysign(1.0, b);
    1728             :         }
    1729             : 
    1730             :         if (a > b)
    1731             :                 return 1;
    1732             : 
    1733             :         if (a == b)
    1734             :                 return 0;
    1735             : 
    1736             :         return -1;
    1737             : }
    1738             : 
    1739             : 
    1740             : s4 builtin_dcmpg(double a, double b)
    1741             : {
    1742             :         if (isnan(a))
    1743             :                 return 1;
    1744             : 
    1745             :         if (isnan(b))
    1746             :                 return 1;
    1747             : 
    1748             :         if (!finite(a) || !finite(b)) {
    1749             :                 a = finite(a) ? 0 : copysign(1.0, a);
    1750             :                 b = finite(b) ? 0 : copysign(1.0, b);
    1751             :         }
    1752             : 
    1753             :         if (a > b)
    1754             :                 return 1;
    1755             : 
    1756             :         if (a == b)
    1757             :                 return 0;
    1758             : 
    1759             :         return -1;
    1760             : }
    1761             : #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
    1762             : 
    1763             : 
    1764          35 : double builtin_drem(double a, double b)
    1765             : {
    1766          35 :         return fmod(a, b);
    1767             : }
    1768             : 
    1769             : 
    1770             : /* conversion operations ******************************************************/
    1771             : 
    1772             : #if !(SUPPORT_FLOAT && SUPPORT_I2F)
    1773             : float builtin_i2f(s4 a)
    1774             : {
    1775             :         float f = (float) a;
    1776             :         return f;
    1777             : }
    1778             : #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
    1779             : 
    1780             : 
    1781             : #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
    1782             : double builtin_i2d(s4 a)
    1783             : {
    1784             :         double d = (double) a;
    1785             :         return d;
    1786             : }
    1787             : #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
    1788             : 
    1789             : 
    1790             : #if !(SUPPORT_FLOAT && SUPPORT_L2F)
    1791             : float builtin_l2f(s8 a)
    1792             : {
    1793             :         float f = (float) a;
    1794             :         return f;
    1795             : }
    1796             : #endif
    1797             : 
    1798             : 
    1799             : #if !(SUPPORT_DOUBLE && SUPPORT_L2D)
    1800             : double builtin_l2d(s8 a)
    1801             : {
    1802             :         double d = (double) a;
    1803             :         return d;
    1804             : }
    1805             : #endif
    1806             : 
    1807             : 
    1808             : #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
    1809      106868 : s4 builtin_f2i(float a) 
    1810             : {
    1811             :         s4 i;
    1812             : 
    1813      106868 :         i = builtin_d2i((double) a);
    1814             : 
    1815      106868 :         return i;
    1816             : 
    1817             :         /*      float f;
    1818             :         
    1819             :                 if (isnanf(a))
    1820             :                 return 0;
    1821             :                 if (finitef(a)) {
    1822             :                 if (a > 2147483647)
    1823             :                 return 2147483647;
    1824             :                 if (a < (-2147483648))
    1825             :                 return (-2147483648);
    1826             :                 return (s4) a;
    1827             :                 }
    1828             :                 f = copysignf((float) 1.0, a);
    1829             :                 if (f > 0)
    1830             :                 return 2147483647;
    1831             :                 return (-2147483648); */
    1832             : }
    1833             : #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
    1834             : 
    1835             : 
    1836             : #if !(SUPPORT_FLOAT && SUPPORT_F2L) || defined(DISABLE_GC)
    1837          24 : s8 builtin_f2l(float a)
    1838             : {
    1839             :         s8 l;
    1840             : 
    1841          24 :         l = builtin_d2l((double) a);
    1842             : 
    1843          24 :         return l;
    1844             : 
    1845             :         /*      float f;
    1846             :         
    1847             :                 if (finitef(a)) {
    1848             :                 if (a > 9223372036854775807L)
    1849             :                 return 9223372036854775807L;
    1850             :                 if (a < (-9223372036854775808L))
    1851             :                 return (-9223372036854775808L);
    1852             :                 return (s8) a;
    1853             :                 }
    1854             :                 if (isnanf(a))
    1855             :                 return 0;
    1856             :                 f = copysignf((float) 1.0, a);
    1857             :                 if (f > 0)
    1858             :                 return 9223372036854775807L;
    1859             :                 return (-9223372036854775808L); */
    1860             : }
    1861             : #endif
    1862             : 
    1863             : 
    1864             : #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
    1865      106916 : s4 builtin_d2i(double a) 
    1866             : { 
    1867             :         double d;
    1868             :         
    1869      106916 :         if (finite(a)) {
    1870      106910 :                 if (a >= 2147483647)
    1871          13 :                         return 2147483647;
    1872      106897 :                 if (a <= (-2147483647-1))
    1873          11 :                         return (-2147483647-1);
    1874      106886 :                 return (s4) a;
    1875             :         }
    1876           6 :         if (isnan(a))
    1877           2 :                 return 0;
    1878           4 :         d = copysign(1.0, a);
    1879           4 :         if (d > 0)
    1880           2 :                 return 2147483647;
    1881           2 :         return (-2147483647-1);
    1882             : }
    1883             : #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
    1884             : 
    1885             : 
    1886             : #if !(SUPPORT_DOUBLE && SUPPORT_D2L) || defined(DISABLE_GC)
    1887          48 : s8 builtin_d2l(double a)
    1888             : {
    1889             :         double d;
    1890             :         
    1891          48 :         if (finite(a)) {
    1892          42 :                 if (a >= 9223372036854775807LL)
    1893           8 :                         return 9223372036854775807LL;
    1894          34 :                 if (a <= (-9223372036854775807LL-1))
    1895           6 :                         return (-9223372036854775807LL-1);
    1896          28 :                 return (s8) a;
    1897             :         }
    1898           6 :         if (isnan(a))
    1899           2 :                 return 0;
    1900           4 :         d = copysign(1.0, a);
    1901           4 :         if (d > 0)
    1902           2 :                 return 9223372036854775807LL;
    1903           2 :         return (-9223372036854775807LL-1);
    1904             : }
    1905             : #endif
    1906             : 
    1907             : 
    1908             : #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
    1909             : double builtin_f2d(float a)
    1910             : {
    1911             :         if (finitef(a)) return (double) a;
    1912             :         else {
    1913             :                 if (isnanf(a))
    1914             :                         return longBitsToDouble(DBL_NAN);
    1915             :                 else
    1916             :                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
    1917             :         }
    1918             : }
    1919             : 
    1920             : float builtin_d2f(double a)
    1921             : {
    1922             :         if (finite(a))
    1923             :                 return (float) a;
    1924             :         else {
    1925             :                 if (isnan(a))
    1926             :                         return intBitsToFloat(FLT_NAN);
    1927             :                 else
    1928             :                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
    1929             :         }
    1930             : }
    1931             : #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
    1932             : 
    1933             : 
    1934             : /*============================================================================*/
    1935             : /* AUTOMATICALLY REPLACED FUNCTIONS                                           */
    1936             : /*============================================================================*/
    1937             : 
    1938             : /* builtin_arraycopy ***********************************************************
    1939             : 
    1940             :    Builtin for java.lang.System.arraycopy.
    1941             : 
    1942             :    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
    1943             : 
    1944             : *******************************************************************************/
    1945             : 
    1946      478508 : void builtin_arraycopy(java_handle_t *src, s4 srcStart,
    1947             :                                            java_handle_t *dest, s4 destStart, s4 len)
    1948             : {
    1949             :         arraydescriptor *sdesc;
    1950             :         arraydescriptor *ddesc;
    1951             :         s4               i;
    1952             : 
    1953      478508 :         if ((src == NULL) || (dest == NULL)) {
    1954           1 :                 exceptions_throw_nullpointerexception();
    1955           1 :                 return;
    1956             :         }
    1957             : 
    1958      478507 :         Array sa(src);
    1959      478507 :         Array da(dest);
    1960             : 
    1961      478507 :         sdesc = LLNI_vftbl_direct(src)->arraydesc;
    1962      478507 :         ddesc = LLNI_vftbl_direct(dest)->arraydesc;
    1963             : 
    1964      478507 :         if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
    1965           0 :                 exceptions_throw_arraystoreexception();
    1966             :                 return;
    1967             :         }
    1968             : 
    1969             :         // Check if offsets and length are positive.
    1970      478507 :         if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
    1971           0 :                 exceptions_throw_arrayindexoutofboundsexception();
    1972             :                 return;
    1973             :         }
    1974             : 
    1975             :         // Check if ranges are valid.
    1976      478507 :         if ((((uint32_t) srcStart  + (uint32_t) len) > (uint32_t) sa.get_length()) ||
    1977             :                 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) da.get_length())) {
    1978           1 :                 exceptions_throw_arrayindexoutofboundsexception();
    1979             :                 return;
    1980             :         }
    1981             : 
    1982             :         // Special case.
    1983      478506 :         if (len == 0) {
    1984             :                 return;
    1985             :         }
    1986             : 
    1987      461452 :         if (sdesc->componentvftbl == ddesc->componentvftbl) {
    1988             :                 /* We copy primitive values or references of exactly the same type */
    1989             : 
    1990      459245 :                 s4 dataoffset = sdesc->dataoffset;
    1991      459245 :                 s4 componentsize = sdesc->componentsize;
    1992             : 
    1993             :                 LLNI_CRITICAL_START;
    1994             : 
    1995             :                 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
    1996             :                           ((u1 *) LLNI_DIRECT(src))  + dataoffset + componentsize * srcStart,
    1997      459245 :                           u1, (size_t) len * componentsize);
    1998             : 
    1999             :                 LLNI_CRITICAL_END;
    2000             :         }
    2001             :         else {
    2002             :                 /* We copy references of different type */
    2003             : 
    2004        2207 :                 ObjectArray oas((java_handle_objectarray_t*) src);
    2005        2207 :                 ObjectArray oad((java_handle_objectarray_t*) dest);
    2006             :  
    2007        2207 :                 if (destStart <= srcStart) {
    2008       12615 :                         for (i = 0; i < len; i++) {
    2009       10409 :                                 java_handle_t* o = oas.get_element(srcStart + i);
    2010             : 
    2011       10409 :                                 if (!builtin_canstore(oad.get_handle(), o))
    2012             :                                         return;
    2013             : 
    2014       10408 :                                 oad.set_element(destStart + i, o);
    2015             :                         }
    2016             :                 }
    2017             :                 else {
    2018             :                         /* XXX this does not completely obey the specification!
    2019             :                            If an exception is thrown only the elements above the
    2020             :                            current index have been copied. The specification
    2021             :                            requires that only the elements *below* the current
    2022             :                            index have been copied before the throw. */
    2023             : 
    2024           0 :                         for (i = len - 1; i >= 0; i--) {
    2025           0 :                                 java_handle_t* o = oas.get_element(srcStart + i);
    2026             : 
    2027           0 :                                 if (!builtin_canstore(oad.get_handle(), o))
    2028             :                                         return;
    2029             : 
    2030           0 :                                 oad.set_element(destStart + i, o);
    2031             :                         }
    2032           0 :                 }
    2033           0 :         }
    2034             : }
    2035             : 
    2036             : 
    2037             : /* builtin_nanotime ************************************************************
    2038             : 
    2039             :    Return the current time in nanoseconds.
    2040             : 
    2041             : *******************************************************************************/
    2042             : 
    2043         335 : s8 builtin_nanotime(void)
    2044             : {
    2045             :         struct timeval tv;
    2046             :         s8             usecs;
    2047             : 
    2048         335 :         if (gettimeofday(&tv, NULL) == -1)
    2049           0 :                 vm_abort("gettimeofday failed: %s", strerror(errno));
    2050             : 
    2051         335 :         usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
    2052             : 
    2053         335 :         return usecs * 1000;
    2054             : }
    2055             : 
    2056             : 
    2057             : /* builtin_currenttimemillis ***************************************************
    2058             : 
    2059             :    Return the current time in milliseconds.
    2060             : 
    2061             : *******************************************************************************/
    2062             : 
    2063         335 : s8 builtin_currenttimemillis(void)
    2064             : {
    2065             :         s8 msecs;
    2066             : 
    2067         335 :         msecs = builtin_nanotime() / 1000 / 1000;
    2068             : 
    2069         335 :         return msecs;
    2070             : }
    2071             : 
    2072             : 
    2073             : /* builtin_clone ***************************************************************
    2074             : 
    2075             :    Function for cloning objects or arrays.
    2076             : 
    2077             :    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
    2078             : 
    2079             : *******************************************************************************/
    2080             : 
    2081        1419 : java_handle_t *builtin_clone(void *env, java_handle_t *o)
    2082             : {
    2083             :         arraydescriptor *ad;
    2084             :         u4               size;
    2085             :         classinfo       *c;
    2086             :         java_handle_t   *co;                /* cloned object header               */
    2087             : 
    2088             :         /* get the array descriptor */
    2089             : 
    2090        1419 :         ad = LLNI_vftbl_direct(o)->arraydesc;
    2091             : 
    2092             :         /* we are cloning an array */
    2093             : 
    2094        1419 :         if (ad != NULL) {
    2095        1004 :                 Array a(o);
    2096             : 
    2097        1004 :                 size = ad->dataoffset + ad->componentsize * a.get_length();
    2098             :         
    2099        1004 :                 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
    2100             : 
    2101        1004 :                 if (co == NULL)
    2102           1 :                         return NULL;
    2103             : 
    2104             : #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
    2105             :                 /* XXX this is only a dirty hack to make Boehm work with handles */
    2106             : 
    2107             :                 co = LLNI_WRAP((java_object_t *) co);
    2108             : #endif
    2109             : 
    2110             :                 LLNI_CRITICAL_START;
    2111             : 
    2112        1003 :                 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
    2113             : 
    2114             : #if defined(ENABLE_GC_CACAO)
    2115             :                 heap_init_objectheader(LLNI_DIRECT(co), size);
    2116             : #endif
    2117             : 
    2118        1003 :                 Lockword(LLNI_DIRECT(co)->lockword).init();
    2119             : 
    2120             :                 LLNI_CRITICAL_END;
    2121             : 
    2122        1003 :                 return co;
    2123             :         }
    2124             :     
    2125             :     /* we are cloning a non-array */
    2126             : 
    2127         415 :     if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
    2128           0 :         exceptions_throw_clonenotsupportedexception();
    2129           0 :         return NULL;
    2130             :     }
    2131             : 
    2132             :         /* get the class of the object */
    2133             : 
    2134         415 :         LLNI_class_get(o, c);
    2135             : 
    2136             :         /* create new object */
    2137             : 
    2138         415 :     co = builtin_new(c);
    2139             : 
    2140         415 :     if (co == NULL)
    2141           0 :         return NULL;
    2142             : 
    2143             :         LLNI_CRITICAL_START;
    2144             : 
    2145         415 :         MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
    2146             : 
    2147             : #if defined(ENABLE_GC_CACAO)
    2148             :         heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
    2149             : #endif
    2150             : 
    2151         415 :         Lockword(LLNI_DIRECT(co)->lockword).init();
    2152             : 
    2153             :         LLNI_CRITICAL_END;
    2154             : 
    2155         415 :     return co;
    2156         495 : }
    2157             : 
    2158             : 
    2159             : #if defined(ENABLE_CYCLES_STATS)
    2160             : void builtin_print_cycles_stats(FILE *file)
    2161             : {
    2162             :         fprintf(file,"builtin cylce count statistics:\n");
    2163             : 
    2164             :         CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
    2165             :         CYCLES_STATS_PRINT(builtin_new         ,file);
    2166             : 
    2167             :         fprintf(file,"\n");
    2168             : }
    2169             : #endif /* defined(ENABLE_CYCLES_STATS) */
    2170             : 
    2171             : 
    2172             : /*
    2173             :  * These are local overrides for various environment variables in Emacs.
    2174             :  * Please do not remove this and leave it at the end of the file, where
    2175             :  * Emacs will automagically detect them.
    2176             :  * ---------------------------------------------------------------------
    2177             :  * Local variables:
    2178             :  * mode: c++
    2179             :  * indent-tabs-mode: t
    2180             :  * c-basic-offset: 4
    2181             :  * tab-width: 4
    2182             :  * End:
    2183             :  * vim:noexpandtab:sw=4:ts=4:
    2184             :  */

Generated by: LCOV version 1.11