1 /* src/vm/jit/builtin.cpp - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
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
45 #include "fdlibm/fdlibm.h"
46 #if defined(__CYGWIN__) && defined(Bias)
51 #include "mm/memory.h"
53 #include "native/llni.h"
55 #include "threads/lock.hpp"
56 #include "threads/mutex.hpp"
57 #include "threads/thread.hpp"
59 #include "toolbox/logging.h"
60 #include "toolbox/util.h"
62 #include "vm/array.hpp"
63 #include "vm/jit/builtin.hpp"
64 #include "vm/class.hpp"
65 #include "vm/cycles-stats.h"
66 #include "vm/exceptions.hpp"
67 #include "vm/global.h"
68 #include "vm/globals.hpp"
69 #include "vm/initialize.hpp"
70 #include "vm/linker.h"
71 #include "vm/loader.hpp"
72 #include "vm/options.h"
73 #include "vm/primitive.hpp"
74 #include "vm/rt-timing.h"
75 #include "vm/string.hpp"
77 #include "vm/jit/asmpart.h"
78 #include "vm/jit/stubs.hpp"
79 #include "vm/jit/trace.hpp"
81 #if defined(ENABLE_VMLOG)
82 #include <vmlog_cacao.h>
86 /* include builtin tables *****************************************************/
88 #include "vm/jit/builtintable.inc"
91 CYCLES_STATS_DECLARE(builtin_new ,100,5)
92 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
95 /*============================================================================*/
96 /* BUILTIN TABLE MANAGEMENT FUNCTIONS */
97 /*============================================================================*/
99 /* builtintable_init ***********************************************************
101 Parse the descriptors of builtin functions and create the parsed
104 *******************************************************************************/
106 static bool builtintable_init(void)
108 descriptor_pool *descpool;
109 builtintable_entry *bte;
112 // Create new dump memory area.
115 /* create a new descriptor pool */
117 descpool = descriptor_pool_new(class_java_lang_Object);
119 /* add some entries we need */
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
124 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
127 /* first add all descriptors to the pool */
129 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
130 bte->name = utf_new_char(bte->cname);
131 bte->descriptor = utf_new_char(bte->cdescriptor);
133 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
137 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
138 bte->descriptor = utf_new_char(bte->cdescriptor);
140 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
144 for (bte = builtintable_function; bte->fp != NULL; bte++) {
145 bte->classname = utf_new_char(bte->cclassname);
146 bte->name = utf_new_char(bte->cname);
147 bte->descriptor = utf_new_char(bte->cdescriptor);
149 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
153 /* create the class reference table */
155 (void) descriptor_pool_create_classrefs(descpool, NULL);
157 /* allocate space for the parsed descriptors */
159 descriptor_pool_alloc_parsed_descriptors(descpool);
161 /* Now parse all descriptors. NOTE: builtin-functions are treated
162 like static methods (no `this' pointer). */
164 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
166 descriptor_pool_parse_method_descriptor(descpool,
168 ACC_STATIC | ACC_METHOD_BUILTIN,
171 /* generate a builtin stub if we need one */
173 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
174 m = method_new_builtin(bte);
175 BuiltinStub::generate(m, bte);
179 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
181 descriptor_pool_parse_method_descriptor(descpool,
183 ACC_STATIC | ACC_METHOD_BUILTIN,
186 /* no stubs should be needed for this table */
188 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
191 for (bte = builtintable_function; bte->fp != NULL; bte++) {
193 descriptor_pool_parse_method_descriptor(descpool,
195 ACC_STATIC | ACC_METHOD_BUILTIN,
198 /* generate a builtin stub if we need one */
200 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
201 m = method_new_builtin(bte);
202 BuiltinStub::generate(m, bte);
210 /* builtintable_comparator *****************************************************
212 qsort comparator for the automatic builtin table.
214 *******************************************************************************/
216 static int builtintable_comparator(const void *a, const void *b)
218 builtintable_entry *bte1;
219 builtintable_entry *bte2;
221 bte1 = (builtintable_entry *) a;
222 bte2 = (builtintable_entry *) b;
224 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
228 /* builtintable_sort_automatic *************************************************
230 Sorts the automatic builtin table.
232 *******************************************************************************/
234 static void builtintable_sort_automatic(void)
238 /* calculate table size statically (`- 1' comment see builtintable.inc) */
240 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
242 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
243 builtintable_comparator);
247 /* builtin_init ****************************************************************
249 Initialize the global table of builtin functions.
251 *******************************************************************************/
253 bool builtin_init(void)
255 TRACESUBSYSTEMINITIALIZATION("builtin_init");
257 /* initialize the builtin tables */
259 if (!builtintable_init())
262 /* sort builtin tables */
264 builtintable_sort_automatic();
270 /* builtintable_get_by_key *****************************************************
272 Returns a key for the given builtintable_entry object which is suitable
273 for retrieving the instance again by calling builtintable_get_by_key.
275 The key can be regarded fixed between multiple runs of the JVM.
277 *******************************************************************************/
279 s4 builtintable_get_key(builtintable_entry *bte)
284 entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
285 for (i = 0; i < entries; i++)
286 if (&builtintable_internal[i] == bte)
289 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
290 for (i = 0; i < entries; i++)
291 if (&builtintable_automatic[i] == bte)
294 entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
295 for (i = 0; i < entries; i++)
296 if (&builtintable_function[i] == bte)
300 entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
301 if (&builtintable_internal[0] <= bte
302 && &builtintable_internal[entries - 1] >= bte)
304 return (s4) (bte - &builtintable_internal[0]) + 1;
307 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
308 if (&builtintable_automatic[0] <= bte
309 && &builtintable_automatic[entries - 1] >= bte)
311 return -(s4) (bte - &builtintable_automatic[0]);
314 entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
315 if (&builtintable_function[0] <= bte
316 && &builtintable_function[entries - 1] >= bte)
318 return -1000 - (s4) (bte - &builtintable_function[0]);
321 /* builtintable_entry is not in our tables. */
327 /* builtintable_get_by_key *****************************************************
329 Retrieves an entry in the internal and automatic builtin functions tables
330 using a key that was retrived previously with builtintable_get_key()
332 *******************************************************************************/
334 builtintable_entry *builtintable_get_by_key(s4 key)
336 /* If key is positive it is the index into builtintable_internal. If it is
337 * negative it is the index into builtintable_automatic. If it is <= -1000
338 * it is the index into builtintable_function.
341 ? &builtintable_internal[key - 1]
342 : (key > -1000 ? &builtintable_automatic[-key] : &builtintable_function[-(1000 + key)]);
345 /* builtintable_get_internal ***************************************************
347 Finds an entry in the builtintable for internal functions and
348 returns the a pointer to the structure.
350 *******************************************************************************/
352 builtintable_entry *builtintable_get_internal(functionptr fp)
354 builtintable_entry *bte;
356 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
365 /* builtintable_get_automatic **************************************************
367 Finds an entry in the builtintable for functions which are replaced
368 automatically and returns the a pointer to the structure.
370 *******************************************************************************/
372 builtintable_entry *builtintable_get_automatic(s4 opcode)
374 builtintable_entry *first;
375 builtintable_entry *last;
376 builtintable_entry *middle;
380 /* calculate table size statically (`- 1' comment see builtintable.inc) */
382 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
384 first = builtintable_automatic;
385 last = builtintable_automatic + entries;
387 while (entries > 0) {
389 middle = first + half;
391 if (middle->opcode < opcode) {
399 return (first != last ? first : NULL);
403 /* builtintable_replace_function ***********************************************
407 *******************************************************************************/
409 #if defined(ENABLE_JIT)
410 bool builtintable_replace_function(void *iptr_)
413 builtintable_entry *bte;
416 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
418 /* get name and descriptor of the function */
421 case ICMD_INVOKESTATIC:
422 /* The instruction MUST be resolved, otherwise we run into
423 lazy loading troubles. Anyway, we should/can only replace
424 very VM-close functions. */
426 if (INSTRUCTION_IS_UNRESOLVED(iptr))
429 mr = iptr->sx.s23.s3.fmiref;
436 /* search the function table */
438 for (bte = builtintable_function; bte->fp != NULL; bte++) {
439 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
440 (mr->name == bte->name) &&
441 (mr->descriptor == bte->descriptor)) {
443 /* set the values in the instruction */
445 iptr->opc = bte->opcode;
446 iptr->sx.s23.s3.bte = bte;
448 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
449 iptr->flags.bits |= INS_FLAG_CHECK;
451 iptr->flags.bits &= ~INS_FLAG_CHECK;
459 #endif /* defined(ENABLE_JIT) */
462 /*============================================================================*/
463 /* INTERNAL BUILTIN FUNCTIONS */
464 /*============================================================================*/
466 /* builtin_instanceof **********************************************************
468 Checks if an object is an instance of some given class (or subclass
469 of that class). If class is an interface, checks if the interface
473 1......o is an instance of class or implements the interface
474 0......otherwise or if o == NULL
476 NOTE: This builtin can be called from NATIVE code only.
478 *******************************************************************************/
480 bool builtin_instanceof(java_handle_t *o, classinfo *c)
487 LLNI_class_get(o, oc);
489 return class_isanysubclass(oc, c);
494 /* builtin_checkcast ***********************************************************
496 The same as builtin_instanceof but with the exception
497 that 1 is returned when (o == NULL).
499 NOTE: This builtin can be called from NATIVE code only.
501 *******************************************************************************/
503 bool builtin_checkcast(java_handle_t *o, classinfo *c)
510 LLNI_class_get(o, oc);
512 if (class_isanysubclass(oc, c))
519 /* builtin_descriptorscompatible ***********************************************
521 Checks if two array type descriptors are assignment compatible.
524 1......target = desc is possible
527 *******************************************************************************/
529 static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
534 if (desc->arraytype != target->arraytype)
537 if (desc->arraytype != ARRAYTYPE_OBJECT)
540 /* {both arrays are arrays of references} */
542 if (desc->dimension == target->dimension) {
543 if (!desc->elementvftbl)
545 /* an array which contains elements of interface types is
546 allowed to be casted to Object (JOWENN)*/
548 if ((desc->elementvftbl->baseval < 0) &&
549 (target->elementvftbl->baseval == 1))
552 return class_isanysubclass(desc->elementvftbl->clazz,
553 target->elementvftbl->clazz);
556 if (desc->dimension < target->dimension)
559 /* {desc has higher dimension than target} */
561 return class_isanysubclass(pseudo_class_Arraystub,
562 target->elementvftbl->clazz);
566 /* builtin_arraycheckcast ******************************************************
568 Checks if an object is really a subtype of the requested array
569 type. The object has to be an array to begin with. For simple
570 arrays (int, short, double, etc.) the types have to match exactly.
571 For arrays of objects, the type of elements in the array has to be
572 a subtype (or the same type) of the requested element type. For
573 arrays of arrays (which in turn can again be arrays of arrays), the
574 types at the lowest level have to satisfy the corresponding sub
577 NOTE: This is a FAST builtin and can be called from JIT code only.
579 *******************************************************************************/
581 bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
583 arraydescriptor *desc;
588 desc = o->vftbl->arraydesc;
593 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
597 /* builtin_fast_arrayinstanceof ************************************************
599 NOTE: This is a FAST builtin and can be called from JIT code only.
601 *******************************************************************************/
603 bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
608 return builtin_fast_arraycheckcast(o, targetclass);
612 /* builtin_arrayinstanceof *****************************************************
614 NOTE: This builtin can be called from NATIVE code only.
616 *******************************************************************************/
618 bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
624 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
632 /* builtin_throw_exception *****************************************************
634 Sets the exception pointer with the thrown exception and prints some
635 debugging information.
637 NOTE: This is a FAST builtin and can be called from JIT code,
638 or from asm_vm_call_method.
640 *******************************************************************************/
642 void *builtin_throw_exception(java_object_t *xptr)
645 /* print exception trace */
647 if (opt_TraceExceptions)
648 trace_exception_builtin(xptr);
649 #endif /* !defined(NDEBUG) */
651 /* actually set the exception */
653 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
655 /* Return a NULL pointer. This is required for vm_call_method to
656 check for an exception. This is for convenience. */
662 /* builtin_retrieve_exception **************************************************
664 Gets and clears the exception pointer of the current thread.
667 the exception object, or NULL if no exception was thrown.
669 NOTE: This is a FAST builtin and can be called from JIT code,
670 or from the signal handlers.
672 *******************************************************************************/
674 java_object_t *builtin_retrieve_exception(void)
679 /* actually get and clear the exception */
681 h = exceptions_get_and_clear_exception();
688 /* builtin_canstore ************************************************************
690 Checks, if an object can be stored in an array.
694 0......otherwise (throws an ArrayStoreException)
696 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
698 *******************************************************************************/
700 bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
706 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
710 /* if not possible, throw an exception */
713 exceptions_throw_arraystoreexception();
719 /* builtin_fast_canstore *******************************************************
721 Checks, if an object can be stored in an array.
725 0......otherwise (no exception thrown!)
727 NOTE: This is a FAST builtin and can be called from JIT code only.
729 *******************************************************************************/
731 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
733 arraydescriptor *desc;
734 arraydescriptor *valuedesc;
735 vftbl_t *componentvftbl;
744 /* The following is guaranteed (by verifier checks):
746 * *) oa->...vftbl->arraydesc != NULL
747 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
748 * *) o->vftbl is not an interface vftbl
751 desc = oa->header.objheader.vftbl->arraydesc;
752 componentvftbl = desc->componentvftbl;
753 valuevftbl = o->vftbl;
754 valuedesc = valuevftbl->arraydesc;
756 if ((desc->dimension - 1) == 0) {
757 /* {oa is a one-dimensional array} */
758 /* {oa is an array of references} */
760 if (valuevftbl == componentvftbl)
763 linker_classrenumber_mutex->lock();
765 baseval = componentvftbl->baseval;
768 /* an array of interface references */
770 result = ((valuevftbl->interfacetablelength > -baseval) &&
771 (valuevftbl->interfacetable[baseval] != NULL));
774 diffval = valuevftbl->baseval - componentvftbl->baseval;
775 result = diffval <= (uint32_t) componentvftbl->diffval;
778 linker_classrenumber_mutex->unlock();
780 else if (valuedesc == NULL) {
781 /* {oa has dimension > 1} */
782 /* {componentvftbl->arraydesc != NULL} */
784 /* check if o is an array */
789 /* {o is an array} */
791 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
800 /* This is an optimized version where a is guaranteed to be one-dimensional */
801 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
803 arraydescriptor *desc;
804 vftbl_t *elementvftbl;
813 /* The following is guaranteed (by verifier checks):
815 * *) a->...vftbl->arraydesc != NULL
816 * *) a->...vftbl->arraydesc->elementvftbl != NULL
817 * *) a->...vftbl->arraydesc->dimension == 1
818 * *) o->vftbl is not an interface vftbl
821 desc = a->header.objheader.vftbl->arraydesc;
822 elementvftbl = desc->elementvftbl;
823 valuevftbl = o->vftbl;
825 /* {a is a one-dimensional array} */
827 if (valuevftbl == elementvftbl)
830 linker_classrenumber_mutex->lock();
832 baseval = elementvftbl->baseval;
835 /* an array of interface references */
836 result = ((valuevftbl->interfacetablelength > -baseval) &&
837 (valuevftbl->interfacetable[baseval] != NULL));
840 diffval = valuevftbl->baseval - elementvftbl->baseval;
841 result = diffval <= (uint32_t) elementvftbl->diffval;
844 linker_classrenumber_mutex->unlock();
850 /* This is an optimized version where a is guaranteed to be a
851 * one-dimensional array of a class type */
852 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
854 vftbl_t *elementvftbl;
862 /* The following is guaranteed (by verifier checks):
864 * *) a->...vftbl->arraydesc != NULL
865 * *) a->...vftbl->arraydesc->elementvftbl != NULL
866 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
867 * *) a->...vftbl->arraydesc->dimension == 1
868 * *) o->vftbl is not an interface vftbl
871 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
872 valuevftbl = o->vftbl;
874 /* {a is a one-dimensional array} */
876 if (valuevftbl == elementvftbl)
879 linker_classrenumber_mutex->lock();
881 diffval = valuevftbl->baseval - elementvftbl->baseval;
882 result = diffval <= (uint32_t) elementvftbl->diffval;
884 linker_classrenumber_mutex->unlock();
890 /* builtin_new *****************************************************************
892 Creates a new instance of class c on the heap.
895 pointer to the object, or NULL if no memory is available
897 NOTE: This builtin can be called from NATIVE code only.
899 *******************************************************************************/
901 java_handle_t *builtin_new(classinfo *c)
904 #if defined(ENABLE_RT_TIMING)
905 struct timespec time_start, time_end;
907 #if defined(ENABLE_CYCLES_STATS)
908 u8 cycles_start, cycles_end;
911 RT_TIMING_GET_TIME(time_start);
912 CYCLES_STATS_GET(cycles_start);
914 /* is the class loaded */
916 assert(c->state & CLASS_LOADED);
918 /* check if we can instantiate this class */
920 if (c->flags & ACC_ABSTRACT) {
921 exceptions_throw_instantiationerror(c);
925 /* is the class linked */
927 if (!(c->state & CLASS_LINKED))
931 if (!(c->state & CLASS_INITIALIZED)) {
934 log_message_class("Initialize class (from builtin_new): ", c);
937 if (!initialize_class(c))
941 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
947 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
948 /* XXX this is only a dirty hack to make Boehm work with handles */
950 o = LLNI_WRAP((java_object_t *) o);
953 LLNI_vftbl_direct(o) = c->vftbl;
955 #if defined(ENABLE_THREADS)
956 LLNI_DIRECT(o)->lockword.init();
959 CYCLES_STATS_GET(cycles_end);
960 RT_TIMING_GET_TIME(time_end);
962 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
963 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
968 #if defined(ENABLE_ESCAPE_REASON)
969 java_handle_t *builtin_escape_reason_new(classinfo *c) {
970 print_escape_reasons();
971 return builtin_java_new(c);
975 #if defined(ENABLE_TLH)
976 java_handle_t *builtin_tlh_new(classinfo *c)
979 # if defined(ENABLE_RT_TIMING)
980 struct timespec time_start, time_end;
982 # if defined(ENABLE_CYCLES_STATS)
983 u8 cycles_start, cycles_end;
986 RT_TIMING_GET_TIME(time_start);
987 CYCLES_STATS_GET(cycles_start);
989 /* is the class loaded */
991 assert(c->state & CLASS_LOADED);
993 /* check if we can instantiate this class */
995 if (c->flags & ACC_ABSTRACT) {
996 exceptions_throw_instantiationerror(c);
1000 /* is the class linked */
1002 if (!(c->state & CLASS_LINKED))
1006 if (!(c->state & CLASS_INITIALIZED)) {
1007 # if !defined(NDEBUG)
1009 log_message_class("Initialize class (from builtin_new): ", c);
1012 if (!initialize_class(c))
1017 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
1022 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1023 c->finalizer, true);
1029 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1030 /* XXX this is only a dirty hack to make Boehm work with handles */
1032 o = LLNI_WRAP((java_object_t *) o);
1035 LLNI_vftbl_direct(o) = c->vftbl;
1037 # if defined(ENABLE_THREADS)
1038 LLNI_DIRECT(o)->lockword.init();
1041 CYCLES_STATS_GET(cycles_end);
1042 RT_TIMING_GET_TIME(time_end);
1045 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1046 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1054 /* builtin_java_new ************************************************************
1056 NOTE: This is a SLOW builtin and can be called from JIT code only.
1058 *******************************************************************************/
1060 java_handle_t *builtin_java_new(java_handle_t *clazz)
1062 return builtin_new(LLNI_classinfo_unwrap(clazz));
1066 /* builtin_fast_new ************************************************************
1068 Creates a new instance of class c on the heap.
1071 pointer to the object, or NULL if no fast return
1072 is possible for any reason.
1074 NOTE: This is a FAST builtin and can be called from JIT code only.
1076 *******************************************************************************/
1078 java_object_t *builtin_fast_new(classinfo *c)
1081 #if defined(ENABLE_RT_TIMING)
1082 struct timespec time_start, time_end;
1084 #if defined(ENABLE_CYCLES_STATS)
1085 u8 cycles_start, cycles_end;
1088 RT_TIMING_GET_TIME(time_start);
1089 CYCLES_STATS_GET(cycles_start);
1091 /* is the class loaded */
1093 assert(c->state & CLASS_LOADED);
1095 /* check if we can instantiate this class */
1097 if (c->flags & ACC_ABSTRACT)
1100 /* is the class linked */
1102 if (!(c->state & CLASS_LINKED))
1105 if (!(c->state & CLASS_INITIALIZED))
1108 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1109 c->finalizer, false);
1114 o->vftbl = c->vftbl;
1116 #if defined(ENABLE_THREADS)
1117 LLNI_DIRECT(o)->lockword.init();
1120 CYCLES_STATS_GET(cycles_end);
1121 RT_TIMING_GET_TIME(time_end);
1123 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1124 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1130 /* builtin_newarray ************************************************************
1132 Creates an array with the given vftbl on the heap. This function
1133 takes as class argument an array class.
1136 pointer to the array or NULL if no memory is available
1138 NOTE: This builtin can be called from NATIVE code only.
1140 *******************************************************************************/
1142 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1144 arraydescriptor *desc;
1149 #if defined(ENABLE_RT_TIMING)
1150 struct timespec time_start, time_end;
1153 RT_TIMING_GET_TIME(time_start);
1155 desc = arrayclass->vftbl->arraydesc;
1156 dataoffset = desc->dataoffset;
1157 componentsize = desc->componentsize;
1160 exceptions_throw_negativearraysizeexception();
1164 actualsize = dataoffset + size * componentsize;
1166 /* check for overflow */
1168 if (((u4) actualsize) < ((u4) size)) {
1169 exceptions_throw_outofmemoryerror();
1173 a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1178 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1179 /* XXX this is only a dirty hack to make Boehm work with handles */
1181 a = LLNI_WRAP((java_object_t *) a);
1184 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1186 #if defined(ENABLE_THREADS)
1187 LLNI_DIRECT(a)->lockword.init();
1190 LLNI_array_size(a) = size;
1192 RT_TIMING_GET_TIME(time_end);
1193 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1199 /* builtin_java_newarray *******************************************************
1201 NOTE: This is a SLOW builtin and can be called from JIT code only.
1203 *******************************************************************************/
1205 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1207 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1211 /* builtin_anewarray ***********************************************************
1213 Creates an array of references to the given class type on the heap.
1216 pointer to the array or NULL if no memory is
1219 NOTE: This builtin can be called from NATIVE code only.
1221 *******************************************************************************/
1223 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1225 classinfo *arrayclass;
1227 /* is class loaded */
1229 assert(componentclass->state & CLASS_LOADED);
1231 /* is class linked */
1233 if (!(componentclass->state & CLASS_LINKED))
1234 if (!link_class(componentclass))
1237 arrayclass = class_array_of(componentclass, true);
1242 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1246 /* builtin_newarray_type ****************************************************
1248 Creates an array of [type]s on the heap.
1251 pointer to the array or NULL if no memory is available
1253 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1255 *******************************************************************************/
1257 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1258 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1260 return (java_handle_##type##array_t *) \
1261 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1264 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1265 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1266 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1267 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1268 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1269 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1270 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1271 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1274 /* builtin_multianewarray_intern ***********************************************
1276 Creates a multi-dimensional array on the heap. The dimensions are
1277 passed in an array of longs.
1280 n.............number of dimensions to create
1281 arrayclass....the array class
1282 dims..........array containing the size of each dimension to create
1285 pointer to the array or NULL if no memory is available
1287 ******************************************************************************/
1289 static java_handle_t *builtin_multianewarray_intern(int n,
1290 classinfo *arrayclass,
1295 classinfo *componentclass;
1298 /* create this dimension */
1300 size = (s4) dims[0];
1301 a = builtin_newarray(size, arrayclass);
1306 /* if this is the last dimension return */
1311 /* get the class of the components to create */
1313 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1315 /* The verifier guarantees that the dimension count is in the range. */
1317 /* create the component arrays */
1319 for (i = 0; i < size; i++) {
1321 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1322 /* we save an s4 to a s8 slot, 8-byte aligned */
1324 builtin_multianewarray_intern(n, componentclass, dims + 2);
1326 builtin_multianewarray_intern(n, componentclass, dims + 1);
1332 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1339 /* builtin_multianewarray ******************************************************
1341 Wrapper for builtin_multianewarray_intern which checks all
1342 dimensions before we start allocating.
1344 NOTE: This is a SLOW builtin and can be called from JIT code only.
1346 ******************************************************************************/
1348 java_handle_objectarray_t *builtin_multianewarray(int n,
1349 java_handle_t *arrayclazz,
1356 /* check all dimensions before doing anything */
1358 for (i = 0; i < n; i++) {
1359 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1360 /* we save an s4 to a s8 slot, 8-byte aligned */
1361 size = (s4) dims[i * 2];
1363 size = (s4) dims[i];
1367 exceptions_throw_negativearraysizeexception();
1372 c = LLNI_classinfo_unwrap(arrayclazz);
1374 /* now call the real function */
1376 return (java_handle_objectarray_t *)
1377 builtin_multianewarray_intern(n, c, dims);
1381 /* builtin_verbosecall_enter ***************************************************
1383 Print method call with arguments for -verbose:call.
1385 XXX: Remove mew once all archs use the new tracer!
1387 *******************************************************************************/
1389 #if !defined(NDEBUG)
1390 #ifdef TRACE_ARGS_NUM
1391 void builtin_verbosecall_enter(s8 a0, s8 a1,
1392 # if TRACE_ARGS_NUM >= 4
1395 # if TRACE_ARGS_NUM >= 6
1398 # if TRACE_ARGS_NUM == 8
1403 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1406 #endif /* !defined(NDEBUG) */
1409 /* builtin_verbosecall_exit ****************************************************
1411 Print method exit for -verbose:call.
1413 XXX: Remove mew once all archs use the new tracer!
1415 *******************************************************************************/
1417 #if !defined(NDEBUG)
1418 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1420 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1422 #endif /* !defined(NDEBUG) */
1425 /*============================================================================*/
1426 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1427 /*============================================================================*/
1429 /*********** Functions for integer divisions *****************************
1431 On some systems (eg. DEC ALPHA), integer division is not supported by the
1432 CPU. These helper functions implement the missing functionality.
1434 ******************************************************************************/
1436 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1437 s4 builtin_idiv(s4 a, s4 b)
1446 s4 builtin_irem(s4 a, s4 b)
1454 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1457 /* functions for long arithmetics **********************************************
1459 On systems where 64 bit Integers are not supported by the CPU,
1460 these functions are needed.
1462 ******************************************************************************/
1464 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1465 s8 builtin_ladd(s8 a, s8 b)
1474 s8 builtin_lsub(s8 a, s8 b)
1483 s8 builtin_lneg(s8 a)
1491 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1494 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1495 s8 builtin_lmul(s8 a, s8 b)
1503 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1506 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1507 s8 builtin_ldiv(s8 a, s8 b)
1516 s8 builtin_lrem(s8 a, s8 b)
1524 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1527 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1528 s8 builtin_lshl(s8 a, s4 b)
1537 s8 builtin_lshr(s8 a, s4 b)
1546 s8 builtin_lushr(s8 a, s4 b)
1550 c = ((u8) a) >> (b & 63);
1554 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1557 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1558 s8 builtin_land(s8 a, s8 b)
1567 s8 builtin_lor(s8 a, s8 b)
1576 s8 builtin_lxor(s8 a, s8 b)
1584 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1587 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1588 s4 builtin_lcmp(s8 a, s8 b)
1598 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1601 /* functions for unsupported floating instructions ****************************/
1603 /* used to convert FLT_xxx defines into float values */
1605 static inline float intBitsToFloat(s4 i)
1614 /* used to convert DBL_xxx defines into double values */
1616 static inline float longBitsToDouble(s8 l)
1626 float builtin_fadd(float a, float b)
1628 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1629 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1640 if (copysignf(1.0, a) == copysignf(1.0, b))
1643 return intBitsToFloat(FLT_NAN);
1649 float builtin_fsub(float a, float b)
1651 return builtin_fadd(a, builtin_fneg(b));
1655 float builtin_fmul(float a, float b)
1657 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1658 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1660 if (finitef(b)) return a * b;
1662 if (a == 0) return intBitsToFloat(FLT_NAN);
1663 else return copysignf(b, copysignf(1.0, b)*a);
1668 if (b == 0) return intBitsToFloat(FLT_NAN);
1669 else return copysignf(a, copysignf(1.0, a)*b);
1672 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1678 /* builtin_ddiv ****************************************************************
1680 Implementation as described in VM Spec.
1682 *******************************************************************************/
1684 float builtin_fdiv(float a, float b)
1688 /* If neither value1' nor value2' is NaN, the sign of the result */
1689 /* is positive if both values have the same sign, negative if the */
1690 /* values have different signs. */
1696 /* If either value1' or value2' is NaN, the result is NaN. */
1698 return intBitsToFloat(FLT_NAN);
1701 /* Division of a finite value by an infinity results in a */
1702 /* signed zero, with the sign-producing rule just given. */
1704 /* is sign equal? */
1706 if (copysignf(1.0, a) == copysignf(1.0, b))
1715 /* If either value1' or value2' is NaN, the result is NaN. */
1717 return intBitsToFloat(FLT_NAN);
1719 } else if (finitef(b)) {
1720 /* Division of an infinity by a finite value results in a signed */
1721 /* infinity, with the sign-producing rule just given. */
1723 /* is sign equal? */
1725 if (copysignf(1.0, a) == copysignf(1.0, b))
1726 return intBitsToFloat(FLT_POSINF);
1728 return intBitsToFloat(FLT_NEGINF);
1731 /* Division of an infinity by an infinity results in NaN. */
1733 return intBitsToFloat(FLT_NAN);
1739 float builtin_fneg(float a)
1741 if (isnanf(a)) return a;
1743 if (finitef(a)) return -a;
1744 else return copysignf(a, -copysignf(1.0, a));
1747 #endif /* !SUPPORT_FLOAT */
1750 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1751 s4 builtin_fcmpl(float a, float b)
1759 if (!finitef(a) || !finitef(b)) {
1760 a = finitef(a) ? 0 : copysignf(1.0, a);
1761 b = finitef(b) ? 0 : copysignf(1.0, b);
1774 s4 builtin_fcmpg(float a, float b)
1776 if (isnanf(a)) return 1;
1777 if (isnanf(b)) return 1;
1778 if (!finitef(a) || !finitef(b)) {
1779 a = finitef(a) ? 0 : copysignf(1.0, a);
1780 b = finitef(b) ? 0 : copysignf(1.0, b);
1782 if (a > b) return 1;
1783 if (a == b) return 0;
1786 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1789 float builtin_frem(float a, float b)
1795 /* functions for unsupported double instructions ******************************/
1798 double builtin_dadd(double a, double b)
1800 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1801 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1803 if (finite(b)) return a + b;
1807 if (finite(b)) return a;
1809 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1810 else return longBitsToDouble(DBL_NAN);
1816 double builtin_dsub(double a, double b)
1818 return builtin_dadd(a, builtin_dneg(b));
1822 double builtin_dmul(double a, double b)
1824 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1825 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1827 if (finite(b)) return a * b;
1829 if (a == 0) return longBitsToDouble(DBL_NAN);
1830 else return copysign(b, copysign(1.0, b) * a);
1835 if (b == 0) return longBitsToDouble(DBL_NAN);
1836 else return copysign(a, copysign(1.0, a) * b);
1839 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1845 /* builtin_ddiv ****************************************************************
1847 Implementation as described in VM Spec.
1849 *******************************************************************************/
1851 double builtin_ddiv(double a, double b)
1855 /* If neither value1' nor value2' is NaN, the sign of the result */
1856 /* is positive if both values have the same sign, negative if the */
1857 /* values have different signs. */
1863 /* If either value1' or value2' is NaN, the result is NaN. */
1865 return longBitsToDouble(DBL_NAN);
1868 /* Division of a finite value by an infinity results in a */
1869 /* signed zero, with the sign-producing rule just given. */
1871 /* is sign equal? */
1873 if (copysign(1.0, a) == copysign(1.0, b))
1882 /* If either value1' or value2' is NaN, the result is NaN. */
1884 return longBitsToDouble(DBL_NAN);
1886 } else if (finite(b)) {
1887 /* Division of an infinity by a finite value results in a signed */
1888 /* infinity, with the sign-producing rule just given. */
1890 /* is sign equal? */
1892 if (copysign(1.0, a) == copysign(1.0, b))
1893 return longBitsToDouble(DBL_POSINF);
1895 return longBitsToDouble(DBL_NEGINF);
1898 /* Division of an infinity by an infinity results in NaN. */
1900 return longBitsToDouble(DBL_NAN);
1906 /* builtin_dneg ****************************************************************
1908 Implemented as described in VM Spec.
1910 *******************************************************************************/
1912 double builtin_dneg(double a)
1915 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1922 /* If the operand is a zero, the result is the zero of opposite */
1928 /* If the operand is an infinity, the result is the infinity of */
1929 /* opposite sign. */
1931 return copysign(a, -copysign(1.0, a));
1935 #endif /* !SUPPORT_DOUBLE */
1938 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1939 s4 builtin_dcmpl(double a, double b)
1947 if (!finite(a) || !finite(b)) {
1948 a = finite(a) ? 0 : copysign(1.0, a);
1949 b = finite(b) ? 0 : copysign(1.0, b);
1962 s4 builtin_dcmpg(double a, double b)
1970 if (!finite(a) || !finite(b)) {
1971 a = finite(a) ? 0 : copysign(1.0, a);
1972 b = finite(b) ? 0 : copysign(1.0, b);
1983 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1986 double builtin_drem(double a, double b)
1992 /* conversion operations ******************************************************/
1994 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1995 float builtin_i2f(s4 a)
1997 float f = (float) a;
2000 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2003 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2004 double builtin_i2d(s4 a)
2006 double d = (double) a;
2009 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2012 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2013 float builtin_l2f(s8 a)
2015 float f = (float) a;
2018 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2021 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2022 double builtin_l2d(s8 a)
2024 double d = (double) a;
2027 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2030 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2031 s4 builtin_f2i(float a)
2035 i = builtin_d2i((double) a);
2046 if (a < (-2147483648))
2047 return (-2147483648);
2050 f = copysignf((float) 1.0, a);
2053 return (-2147483648); */
2055 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2058 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2059 s8 builtin_f2l(float a)
2063 l = builtin_d2l((double) a);
2070 if (a > 9223372036854775807L)
2071 return 9223372036854775807L;
2072 if (a < (-9223372036854775808L))
2073 return (-9223372036854775808L);
2078 f = copysignf((float) 1.0, a);
2080 return 9223372036854775807L;
2081 return (-9223372036854775808L); */
2083 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2086 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2087 s4 builtin_d2i(double a)
2092 if (a >= 2147483647)
2094 if (a <= (-2147483647-1))
2095 return (-2147483647-1);
2100 d = copysign(1.0, a);
2103 return (-2147483647-1);
2105 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2108 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2109 s8 builtin_d2l(double a)
2114 if (a >= 9223372036854775807LL)
2115 return 9223372036854775807LL;
2116 if (a <= (-9223372036854775807LL-1))
2117 return (-9223372036854775807LL-1);
2122 d = copysign(1.0, a);
2124 return 9223372036854775807LL;
2125 return (-9223372036854775807LL-1);
2127 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2130 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2131 double builtin_f2d(float a)
2133 if (finitef(a)) return (double) a;
2136 return longBitsToDouble(DBL_NAN);
2138 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2142 float builtin_d2f(double a)
2148 return intBitsToFloat(FLT_NAN);
2150 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2153 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2156 /*============================================================================*/
2157 /* AUTOMATICALLY REPLACED FUNCTIONS */
2158 /*============================================================================*/
2160 /* builtin_arraycopy ***********************************************************
2162 Builtin for java.lang.System.arraycopy.
2164 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2166 *******************************************************************************/
2168 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2169 java_handle_t *dest, s4 destStart, s4 len)
2171 arraydescriptor *sdesc;
2172 arraydescriptor *ddesc;
2175 if ((src == NULL) || (dest == NULL)) {
2176 exceptions_throw_nullpointerexception();
2180 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2181 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2183 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2184 exceptions_throw_arraystoreexception();
2188 // Check if offsets and length are positive.
2189 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2190 exceptions_throw_arrayindexoutofboundsexception();
2194 // Check if ranges are valid.
2195 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2196 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2197 exceptions_throw_arrayindexoutofboundsexception();
2206 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2207 /* We copy primitive values or references of exactly the same type */
2209 s4 dataoffset = sdesc->dataoffset;
2210 s4 componentsize = sdesc->componentsize;
2212 LLNI_CRITICAL_START;
2214 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2215 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2216 u1, (size_t) len * componentsize);
2221 /* We copy references of different type */
2223 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2224 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2226 if (destStart <= srcStart) {
2227 for (i = 0; i < len; i++) {
2230 o = array_objectarray_element_get(oas, srcStart + i);
2232 if (!builtin_canstore(oad, o))
2235 array_objectarray_element_set(oad, destStart + i, o);
2239 /* XXX this does not completely obey the specification!
2240 If an exception is thrown only the elements above the
2241 current index have been copied. The specification
2242 requires that only the elements *below* the current
2243 index have been copied before the throw. */
2245 for (i = len - 1; i >= 0; i--) {
2248 o = array_objectarray_element_get(oas, srcStart + i);
2250 if (!builtin_canstore(oad, o))
2253 array_objectarray_element_set(oad, destStart + i, o);
2260 /* builtin_nanotime ************************************************************
2262 Return the current time in nanoseconds.
2264 *******************************************************************************/
2266 s8 builtin_nanotime(void)
2271 if (gettimeofday(&tv, NULL) == -1)
2272 vm_abort("gettimeofday failed: %s", strerror(errno));
2274 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2276 return usecs * 1000;
2280 /* builtin_currenttimemillis ***************************************************
2282 Return the current time in milliseconds.
2284 *******************************************************************************/
2286 s8 builtin_currenttimemillis(void)
2290 msecs = builtin_nanotime() / 1000 / 1000;
2296 /* builtin_clone ***************************************************************
2298 Function for cloning objects or arrays.
2300 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2302 *******************************************************************************/
2304 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2306 arraydescriptor *ad;
2309 java_handle_t *co; /* cloned object header */
2311 /* get the array descriptor */
2313 ad = LLNI_vftbl_direct(o)->arraydesc;
2315 /* we are cloning an array */
2318 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2320 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2325 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2326 /* XXX this is only a dirty hack to make Boehm work with handles */
2328 co = LLNI_WRAP((java_object_t *) co);
2331 LLNI_CRITICAL_START;
2333 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2335 #if defined(ENABLE_GC_CACAO)
2336 heap_init_objectheader(LLNI_DIRECT(co), size);
2339 #if defined(ENABLE_THREADS)
2340 LLNI_DIRECT(co)->lockword.init();
2348 /* we are cloning a non-array */
2350 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2351 exceptions_throw_clonenotsupportedexception();
2355 /* get the class of the object */
2357 LLNI_class_get(o, c);
2359 /* create new object */
2361 co = builtin_new(c);
2366 LLNI_CRITICAL_START;
2368 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2370 #if defined(ENABLE_GC_CACAO)
2371 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2374 #if defined(ENABLE_THREADS)
2375 LLNI_DIRECT(co)->lockword.init();
2384 #if defined(ENABLE_CYCLES_STATS)
2385 void builtin_print_cycles_stats(FILE *file)
2387 fprintf(file,"builtin cylce count statistics:\n");
2389 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2390 CYCLES_STATS_PRINT(builtin_new ,file);
2394 #endif /* defined(ENABLE_CYCLES_STATS) */
2397 #if defined(ENABLE_VMLOG)
2399 #include <vmlog_cacao.c>
2404 * These are local overrides for various environment variables in Emacs.
2405 * Please do not remove this and leave it at the end of the file, where
2406 * Emacs will automagically detect them.
2407 * ---------------------------------------------------------------------
2410 * indent-tabs-mode: t
2414 * vim:noexpandtab:sw=4:ts=4: