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.hpp"
53 #include "native/llni.h"
55 #include "threads/lock.hpp"
56 #include "threads/mutex.hpp"
57 #include "threads/thread.hpp"
59 #include "toolbox/logging.hpp"
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.hpp"
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_internal ***************************************************
272 Finds an entry in the builtintable for internal functions and
273 returns the a pointer to the structure.
275 *******************************************************************************/
277 builtintable_entry *builtintable_get_internal(functionptr fp)
279 builtintable_entry *bte;
281 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
290 /* builtintable_get_automatic **************************************************
292 Finds an entry in the builtintable for functions which are replaced
293 automatically and returns the a pointer to the structure.
295 *******************************************************************************/
297 builtintable_entry *builtintable_get_automatic(s4 opcode)
299 builtintable_entry *first;
300 builtintable_entry *last;
301 builtintable_entry *middle;
305 /* calculate table size statically (`- 1' comment see builtintable.inc) */
307 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
309 first = builtintable_automatic;
310 last = builtintable_automatic + entries;
312 while (entries > 0) {
314 middle = first + half;
316 if (middle->opcode < opcode) {
324 return (first != last ? first : NULL);
328 /* builtintable_replace_function ***********************************************
332 *******************************************************************************/
334 #if defined(ENABLE_JIT)
335 bool builtintable_replace_function(void *iptr_)
338 builtintable_entry *bte;
341 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
343 /* get name and descriptor of the function */
346 case ICMD_INVOKESTATIC:
347 /* The instruction MUST be resolved, otherwise we run into
348 lazy loading troubles. Anyway, we should/can only replace
349 very VM-close functions. */
351 if (INSTRUCTION_IS_UNRESOLVED(iptr))
354 mr = iptr->sx.s23.s3.fmiref;
361 /* search the function table */
363 for (bte = builtintable_function; bte->fp != NULL; bte++) {
364 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
365 (mr->name == bte->name) &&
366 (mr->descriptor == bte->descriptor)) {
368 /* set the values in the instruction */
370 iptr->opc = bte->opcode;
371 iptr->sx.s23.s3.bte = bte;
373 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
374 iptr->flags.bits |= INS_FLAG_CHECK;
376 iptr->flags.bits &= ~INS_FLAG_CHECK;
384 #endif /* defined(ENABLE_JIT) */
387 /*============================================================================*/
388 /* INTERNAL BUILTIN FUNCTIONS */
389 /*============================================================================*/
391 /* builtin_instanceof **********************************************************
393 Checks if an object is an instance of some given class (or subclass
394 of that class). If class is an interface, checks if the interface
398 1......o is an instance of class or implements the interface
399 0......otherwise or if o == NULL
401 NOTE: This builtin can be called from NATIVE code only.
403 *******************************************************************************/
405 bool builtin_instanceof(java_handle_t *o, classinfo *c)
412 LLNI_class_get(o, oc);
414 return class_isanysubclass(oc, c);
419 /* builtin_checkcast ***********************************************************
421 The same as builtin_instanceof but with the exception
422 that 1 is returned when (o == NULL).
424 NOTE: This builtin can be called from NATIVE code only.
426 *******************************************************************************/
428 bool builtin_checkcast(java_handle_t *o, classinfo *c)
435 LLNI_class_get(o, oc);
437 if (class_isanysubclass(oc, c))
444 /* builtin_descriptorscompatible ***********************************************
446 Checks if two array type descriptors are assignment compatible.
449 1......target = desc is possible
452 *******************************************************************************/
454 static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
459 if (desc->arraytype != target->arraytype)
462 if (desc->arraytype != ARRAYTYPE_OBJECT)
465 /* {both arrays are arrays of references} */
467 if (desc->dimension == target->dimension) {
468 if (!desc->elementvftbl)
470 /* an array which contains elements of interface types is
471 allowed to be casted to Object (JOWENN)*/
473 if ((desc->elementvftbl->baseval < 0) &&
474 (target->elementvftbl->baseval == 1))
477 return class_isanysubclass(desc->elementvftbl->clazz,
478 target->elementvftbl->clazz);
481 if (desc->dimension < target->dimension)
484 /* {desc has higher dimension than target} */
486 return class_isanysubclass(pseudo_class_Arraystub,
487 target->elementvftbl->clazz);
491 /* builtin_arraycheckcast ******************************************************
493 Checks if an object is really a subtype of the requested array
494 type. The object has to be an array to begin with. For simple
495 arrays (int, short, double, etc.) the types have to match exactly.
496 For arrays of objects, the type of elements in the array has to be
497 a subtype (or the same type) of the requested element type. For
498 arrays of arrays (which in turn can again be arrays of arrays), the
499 types at the lowest level have to satisfy the corresponding sub
502 NOTE: This is a FAST builtin and can be called from JIT code only.
504 *******************************************************************************/
506 bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
508 arraydescriptor *desc;
513 desc = o->vftbl->arraydesc;
518 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
522 /* builtin_fast_arrayinstanceof ************************************************
524 NOTE: This is a FAST builtin and can be called from JIT code only.
526 *******************************************************************************/
528 bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
533 return builtin_fast_arraycheckcast(o, targetclass);
537 /* builtin_arrayinstanceof *****************************************************
539 NOTE: This builtin can be called from NATIVE code only.
541 *******************************************************************************/
543 bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
549 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
557 /* builtin_throw_exception *****************************************************
559 Sets the exception pointer with the thrown exception and prints some
560 debugging information.
562 NOTE: This is a FAST builtin and can be called from JIT code,
563 or from asm_vm_call_method.
565 *******************************************************************************/
567 void *builtin_throw_exception(java_object_t *xptr)
570 /* print exception trace */
572 if (opt_TraceExceptions)
573 trace_exception_builtin(xptr);
574 #endif /* !defined(NDEBUG) */
576 /* actually set the exception */
578 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
580 /* Return a NULL pointer. This is required for vm_call_method to
581 check for an exception. This is for convenience. */
587 /* builtin_retrieve_exception **************************************************
589 Gets and clears the exception pointer of the current thread.
592 the exception object, or NULL if no exception was thrown.
594 NOTE: This is a FAST builtin and can be called from JIT code,
595 or from the signal handlers.
597 *******************************************************************************/
599 java_object_t *builtin_retrieve_exception(void)
604 /* actually get and clear the exception */
606 h = exceptions_get_and_clear_exception();
613 /* builtin_canstore ************************************************************
615 Checks, if an object can be stored in an array.
619 0......otherwise (throws an ArrayStoreException)
621 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
623 *******************************************************************************/
625 bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
631 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
635 /* if not possible, throw an exception */
638 exceptions_throw_arraystoreexception();
644 /* fast_subtype_check **********************************************************
646 Checks if s is a subtype of t, using both the restricted subtype relation
647 and the overflow array (see Cliff Click and John Rose: Fast subtype checking
651 1......s is a subtype of t.
654 *******************************************************************************/
656 bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
658 if (s->subtype_display[t->subtype_depth] == t)
660 if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
662 return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
666 /* builtin_fast_canstore *******************************************************
668 Checks, if an object can be stored in an array.
672 0......otherwise (no exception thrown!)
674 NOTE: This is a FAST builtin and can be called from JIT code only.
676 *******************************************************************************/
678 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
680 arraydescriptor *desc;
681 arraydescriptor *valuedesc;
682 vftbl_t *componentvftbl;
690 /* The following is guaranteed (by verifier checks):
692 * *) oa->...vftbl->arraydesc != NULL
693 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
694 * *) o->vftbl is not an interface vftbl
697 desc = oa->header.objheader.vftbl->arraydesc;
698 componentvftbl = desc->componentvftbl;
699 valuevftbl = o->vftbl;
700 valuedesc = valuevftbl->arraydesc;
702 if ((desc->dimension - 1) == 0) {
703 /* {oa is a one-dimensional array} */
704 /* {oa is an array of references} */
706 if (valuevftbl == componentvftbl)
709 LOCK_CLASSRENUMBER_LOCK;
711 baseval = componentvftbl->baseval;
714 /* an array of interface references */
716 result = ((valuevftbl->interfacetablelength > -baseval) &&
717 (valuevftbl->interfacetable[baseval] != NULL));
721 result = fast_subtype_check(valuevftbl, componentvftbl);
723 uint32_t diffval = valuevftbl->baseval - componentvftbl->baseval;
724 result = diffval <= (uint32_t) componentvftbl->diffval;
728 UNLOCK_CLASSRENUMBER_LOCK;
730 else if (valuedesc == NULL) {
731 /* {oa has dimension > 1} */
732 /* {componentvftbl->arraydesc != NULL} */
734 /* check if o is an array */
739 /* {o is an array} */
741 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
750 /* This is an optimized version where a is guaranteed to be one-dimensional */
751 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
753 arraydescriptor *desc;
754 vftbl_t *elementvftbl;
762 /* The following is guaranteed (by verifier checks):
764 * *) a->...vftbl->arraydesc != NULL
765 * *) a->...vftbl->arraydesc->elementvftbl != NULL
766 * *) a->...vftbl->arraydesc->dimension == 1
767 * *) o->vftbl is not an interface vftbl
770 desc = a->header.objheader.vftbl->arraydesc;
771 elementvftbl = desc->elementvftbl;
772 valuevftbl = o->vftbl;
774 /* {a is a one-dimensional array} */
776 if (valuevftbl == elementvftbl)
779 LOCK_CLASSRENUMBER_LOCK;
781 baseval = elementvftbl->baseval;
784 /* an array of interface references */
785 result = ((valuevftbl->interfacetablelength > -baseval) &&
786 (valuevftbl->interfacetable[baseval] != NULL));
790 result = fast_subtype_check(valuevftbl, elementvftbl);
792 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
793 result = diffval <= (uint32_t) elementvftbl->diffval;
797 UNLOCK_CLASSRENUMBER_LOCK;
803 /* This is an optimized version where a is guaranteed to be a
804 * one-dimensional array of a class type */
805 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
807 vftbl_t *elementvftbl;
814 /* The following is guaranteed (by verifier checks):
816 * *) a->...vftbl->arraydesc != NULL
817 * *) a->...vftbl->arraydesc->elementvftbl != NULL
818 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
819 * *) a->...vftbl->arraydesc->dimension == 1
820 * *) o->vftbl is not an interface vftbl
823 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
824 valuevftbl = o->vftbl;
826 /* {a is a one-dimensional array} */
828 if (valuevftbl == elementvftbl)
831 LOCK_CLASSRENUMBER_LOCK;
834 result = fast_subtype_check(valuevftbl, elementvftbl);
836 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
837 result = diffval <= (uint32_t) elementvftbl->diffval;
840 UNLOCK_CLASSRENUMBER_LOCK;
846 /* builtin_new *****************************************************************
848 Creates a new instance of class c on the heap.
851 pointer to the object, or NULL if no memory is available
853 NOTE: This builtin can be called from NATIVE code only.
855 *******************************************************************************/
857 java_handle_t *builtin_new(classinfo *c)
860 #if defined(ENABLE_RT_TIMING)
861 struct timespec time_start, time_end;
863 #if defined(ENABLE_CYCLES_STATS)
864 u8 cycles_start, cycles_end;
867 RT_TIMING_GET_TIME(time_start);
868 CYCLES_STATS_GET(cycles_start);
870 /* is the class loaded */
872 assert(c->state & CLASS_LOADED);
874 /* check if we can instantiate this class */
876 if (c->flags & ACC_ABSTRACT) {
877 exceptions_throw_instantiationerror(c);
881 /* is the class linked */
883 if (!(c->state & CLASS_LINKED))
887 if (!(c->state & CLASS_INITIALIZED)) {
890 log_message_class("Initialize class (from builtin_new): ", c);
893 if (!initialize_class(c))
897 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
903 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
904 /* XXX this is only a dirty hack to make Boehm work with handles */
906 o = LLNI_WRAP((java_object_t *) o);
909 LLNI_vftbl_direct(o) = c->vftbl;
911 #if defined(ENABLE_THREADS)
912 LLNI_DIRECT(o)->lockword.init();
915 CYCLES_STATS_GET(cycles_end);
916 RT_TIMING_GET_TIME(time_end);
918 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
919 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
924 #if defined(ENABLE_ESCAPE_REASON)
925 java_handle_t *builtin_escape_reason_new(classinfo *c) {
926 print_escape_reasons();
927 return builtin_java_new(c);
931 #if defined(ENABLE_TLH)
932 java_handle_t *builtin_tlh_new(classinfo *c)
935 # if defined(ENABLE_RT_TIMING)
936 struct timespec time_start, time_end;
938 # if defined(ENABLE_CYCLES_STATS)
939 u8 cycles_start, cycles_end;
942 RT_TIMING_GET_TIME(time_start);
943 CYCLES_STATS_GET(cycles_start);
945 /* is the class loaded */
947 assert(c->state & CLASS_LOADED);
949 /* check if we can instantiate this class */
951 if (c->flags & ACC_ABSTRACT) {
952 exceptions_throw_instantiationerror(c);
956 /* is the class linked */
958 if (!(c->state & CLASS_LINKED))
962 if (!(c->state & CLASS_INITIALIZED)) {
963 # if !defined(NDEBUG)
965 log_message_class("Initialize class (from builtin_new): ", c);
968 if (!initialize_class(c))
973 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
978 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
985 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
986 /* XXX this is only a dirty hack to make Boehm work with handles */
988 o = LLNI_WRAP((java_object_t *) o);
991 LLNI_vftbl_direct(o) = c->vftbl;
993 # if defined(ENABLE_THREADS)
994 LLNI_DIRECT(o)->lockword.init();
997 CYCLES_STATS_GET(cycles_end);
998 RT_TIMING_GET_TIME(time_end);
1001 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1002 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1010 /* builtin_java_new ************************************************************
1012 NOTE: This is a SLOW builtin and can be called from JIT code only.
1014 *******************************************************************************/
1016 java_handle_t *builtin_java_new(java_handle_t *clazz)
1018 return builtin_new(LLNI_classinfo_unwrap(clazz));
1022 /* builtin_fast_new ************************************************************
1024 Creates a new instance of class c on the heap.
1027 pointer to the object, or NULL if no fast return
1028 is possible for any reason.
1030 NOTE: This is a FAST builtin and can be called from JIT code only.
1032 *******************************************************************************/
1034 java_object_t *builtin_fast_new(classinfo *c)
1037 #if defined(ENABLE_RT_TIMING)
1038 struct timespec time_start, time_end;
1040 #if defined(ENABLE_CYCLES_STATS)
1041 u8 cycles_start, cycles_end;
1044 RT_TIMING_GET_TIME(time_start);
1045 CYCLES_STATS_GET(cycles_start);
1047 /* is the class loaded */
1049 assert(c->state & CLASS_LOADED);
1051 /* check if we can instantiate this class */
1053 if (c->flags & ACC_ABSTRACT)
1056 /* is the class linked */
1058 if (!(c->state & CLASS_LINKED))
1061 if (!(c->state & CLASS_INITIALIZED))
1064 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1065 c->finalizer, false);
1070 o->vftbl = c->vftbl;
1072 #if defined(ENABLE_THREADS)
1073 LLNI_DIRECT(o)->lockword.init();
1076 CYCLES_STATS_GET(cycles_end);
1077 RT_TIMING_GET_TIME(time_end);
1079 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1080 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1086 /* builtin_newarray ************************************************************
1088 Creates an array with the given vftbl on the heap. This function
1089 takes as class argument an array class.
1092 pointer to the array or NULL if no memory is available
1094 NOTE: This builtin can be called from NATIVE code only.
1096 *******************************************************************************/
1098 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1100 arraydescriptor *desc;
1105 #if defined(ENABLE_RT_TIMING)
1106 struct timespec time_start, time_end;
1109 RT_TIMING_GET_TIME(time_start);
1111 desc = arrayclass->vftbl->arraydesc;
1112 dataoffset = desc->dataoffset;
1113 componentsize = desc->componentsize;
1116 exceptions_throw_negativearraysizeexception();
1120 actualsize = dataoffset + size * componentsize;
1122 /* check for overflow */
1124 if (((u4) actualsize) < ((u4) size)) {
1125 exceptions_throw_outofmemoryerror();
1129 a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1134 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1135 /* XXX this is only a dirty hack to make Boehm work with handles */
1137 a = LLNI_WRAP((java_object_t *) a);
1140 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1142 #if defined(ENABLE_THREADS)
1143 LLNI_DIRECT(a)->lockword.init();
1146 LLNI_array_size(a) = size;
1148 RT_TIMING_GET_TIME(time_end);
1149 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1155 /* builtin_java_newarray *******************************************************
1157 NOTE: This is a SLOW builtin and can be called from JIT code only.
1159 *******************************************************************************/
1161 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1163 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1167 /* builtin_anewarray ***********************************************************
1169 Creates an array of references to the given class type on the heap.
1172 pointer to the array or NULL if no memory is
1175 NOTE: This builtin can be called from NATIVE code only.
1177 *******************************************************************************/
1179 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1181 classinfo *arrayclass;
1183 /* is class loaded */
1185 assert(componentclass->state & CLASS_LOADED);
1187 /* is class linked */
1189 if (!(componentclass->state & CLASS_LINKED))
1190 if (!link_class(componentclass))
1193 arrayclass = class_array_of(componentclass, true);
1198 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1202 /* builtin_newarray_type ****************************************************
1204 Creates an array of [type]s on the heap.
1207 pointer to the array or NULL if no memory is available
1209 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1211 *******************************************************************************/
1213 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1214 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1216 return (java_handle_##type##array_t *) \
1217 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1220 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1221 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1222 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1223 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1224 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1225 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1226 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1227 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1230 /* builtin_multianewarray_intern ***********************************************
1232 Creates a multi-dimensional array on the heap. The dimensions are
1233 passed in an array of longs.
1236 n.............number of dimensions to create
1237 arrayclass....the array class
1238 dims..........array containing the size of each dimension to create
1241 pointer to the array or NULL if no memory is available
1243 ******************************************************************************/
1245 static java_handle_t *builtin_multianewarray_intern(int n,
1246 classinfo *arrayclass,
1251 classinfo *componentclass;
1254 /* create this dimension */
1256 size = (s4) dims[0];
1257 a = builtin_newarray(size, arrayclass);
1262 /* if this is the last dimension return */
1267 /* get the class of the components to create */
1269 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1271 /* The verifier guarantees that the dimension count is in the range. */
1273 /* create the component arrays */
1275 for (i = 0; i < size; i++) {
1277 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1278 /* we save an s4 to a s8 slot, 8-byte aligned */
1280 builtin_multianewarray_intern(n, componentclass, dims + 2);
1282 builtin_multianewarray_intern(n, componentclass, dims + 1);
1288 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1295 /* builtin_multianewarray ******************************************************
1297 Wrapper for builtin_multianewarray_intern which checks all
1298 dimensions before we start allocating.
1300 NOTE: This is a SLOW builtin and can be called from JIT code only.
1302 ******************************************************************************/
1304 java_handle_objectarray_t *builtin_multianewarray(int n,
1305 java_handle_t *arrayclazz,
1312 /* check all dimensions before doing anything */
1314 for (i = 0; i < n; i++) {
1315 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1316 /* we save an s4 to a s8 slot, 8-byte aligned */
1317 size = (s4) dims[i * 2];
1319 size = (s4) dims[i];
1323 exceptions_throw_negativearraysizeexception();
1328 c = LLNI_classinfo_unwrap(arrayclazz);
1330 /* now call the real function */
1332 return (java_handle_objectarray_t *)
1333 builtin_multianewarray_intern(n, c, dims);
1337 /* builtin_verbosecall_enter ***************************************************
1339 Print method call with arguments for -verbose:call.
1341 XXX: Remove mew once all archs use the new tracer!
1343 *******************************************************************************/
1345 #if !defined(NDEBUG)
1346 #ifdef TRACE_ARGS_NUM
1347 void builtin_verbosecall_enter(s8 a0, s8 a1,
1348 # if TRACE_ARGS_NUM >= 4
1351 # if TRACE_ARGS_NUM >= 6
1354 # if TRACE_ARGS_NUM == 8
1359 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1362 #endif /* !defined(NDEBUG) */
1365 /* builtin_verbosecall_exit ****************************************************
1367 Print method exit for -verbose:call.
1369 XXX: Remove mew once all archs use the new tracer!
1371 *******************************************************************************/
1373 #if !defined(NDEBUG)
1374 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1376 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1378 #endif /* !defined(NDEBUG) */
1381 /*============================================================================*/
1382 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1383 /*============================================================================*/
1385 /*********** Functions for integer divisions *****************************
1387 On some systems (eg. DEC ALPHA), integer division is not supported by the
1388 CPU. These helper functions implement the missing functionality.
1390 ******************************************************************************/
1392 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1393 s4 builtin_idiv(s4 a, s4 b)
1402 s4 builtin_irem(s4 a, s4 b)
1410 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1413 /* functions for long arithmetics **********************************************
1415 On systems where 64 bit Integers are not supported by the CPU,
1416 these functions are needed.
1418 ******************************************************************************/
1420 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1421 s8 builtin_ladd(s8 a, s8 b)
1430 s8 builtin_lsub(s8 a, s8 b)
1439 s8 builtin_lneg(s8 a)
1447 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1450 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1451 s8 builtin_lmul(s8 a, s8 b)
1459 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1462 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1463 s8 builtin_ldiv(s8 a, s8 b)
1472 s8 builtin_lrem(s8 a, s8 b)
1480 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1483 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1484 s8 builtin_lshl(s8 a, s4 b)
1493 s8 builtin_lshr(s8 a, s4 b)
1502 s8 builtin_lushr(s8 a, s4 b)
1506 c = ((u8) a) >> (b & 63);
1510 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1513 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1514 s8 builtin_land(s8 a, s8 b)
1523 s8 builtin_lor(s8 a, s8 b)
1532 s8 builtin_lxor(s8 a, s8 b)
1540 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1543 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1544 s4 builtin_lcmp(s8 a, s8 b)
1554 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1557 /* functions for unsupported floating instructions ****************************/
1559 /* used to convert FLT_xxx defines into float values */
1561 static inline float intBitsToFloat(s4 i)
1570 /* used to convert DBL_xxx defines into double values */
1572 static inline float longBitsToDouble(s8 l)
1582 float builtin_fadd(float a, float b)
1584 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1585 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1596 if (copysignf(1.0, a) == copysignf(1.0, b))
1599 return intBitsToFloat(FLT_NAN);
1605 float builtin_fsub(float a, float b)
1607 return builtin_fadd(a, builtin_fneg(b));
1611 float builtin_fmul(float a, float b)
1613 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1614 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1616 if (finitef(b)) return a * b;
1618 if (a == 0) return intBitsToFloat(FLT_NAN);
1619 else return copysignf(b, copysignf(1.0, b)*a);
1624 if (b == 0) return intBitsToFloat(FLT_NAN);
1625 else return copysignf(a, copysignf(1.0, a)*b);
1628 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1634 /* builtin_ddiv ****************************************************************
1636 Implementation as described in VM Spec.
1638 *******************************************************************************/
1640 float builtin_fdiv(float a, float b)
1644 /* If neither value1' nor value2' is NaN, the sign of the result */
1645 /* is positive if both values have the same sign, negative if the */
1646 /* values have different signs. */
1652 /* If either value1' or value2' is NaN, the result is NaN. */
1654 return intBitsToFloat(FLT_NAN);
1657 /* Division of a finite value by an infinity results in a */
1658 /* signed zero, with the sign-producing rule just given. */
1660 /* is sign equal? */
1662 if (copysignf(1.0, a) == copysignf(1.0, b))
1671 /* If either value1' or value2' is NaN, the result is NaN. */
1673 return intBitsToFloat(FLT_NAN);
1675 } else if (finitef(b)) {
1676 /* Division of an infinity by a finite value results in a signed */
1677 /* infinity, with the sign-producing rule just given. */
1679 /* is sign equal? */
1681 if (copysignf(1.0, a) == copysignf(1.0, b))
1682 return intBitsToFloat(FLT_POSINF);
1684 return intBitsToFloat(FLT_NEGINF);
1687 /* Division of an infinity by an infinity results in NaN. */
1689 return intBitsToFloat(FLT_NAN);
1695 float builtin_fneg(float a)
1697 if (isnanf(a)) return a;
1699 if (finitef(a)) return -a;
1700 else return copysignf(a, -copysignf(1.0, a));
1703 #endif /* !SUPPORT_FLOAT */
1706 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1707 s4 builtin_fcmpl(float a, float b)
1715 if (!finitef(a) || !finitef(b)) {
1716 a = finitef(a) ? 0 : copysignf(1.0, a);
1717 b = finitef(b) ? 0 : copysignf(1.0, b);
1730 s4 builtin_fcmpg(float a, float b)
1732 if (isnanf(a)) return 1;
1733 if (isnanf(b)) return 1;
1734 if (!finitef(a) || !finitef(b)) {
1735 a = finitef(a) ? 0 : copysignf(1.0, a);
1736 b = finitef(b) ? 0 : copysignf(1.0, b);
1738 if (a > b) return 1;
1739 if (a == b) return 0;
1742 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1745 float builtin_frem(float a, float b)
1751 /* functions for unsupported double instructions ******************************/
1754 double builtin_dadd(double a, double b)
1756 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1757 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1759 if (finite(b)) return a + b;
1763 if (finite(b)) return a;
1765 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1766 else return longBitsToDouble(DBL_NAN);
1772 double builtin_dsub(double a, double b)
1774 return builtin_dadd(a, builtin_dneg(b));
1778 double builtin_dmul(double a, double b)
1780 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1781 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1783 if (finite(b)) return a * b;
1785 if (a == 0) return longBitsToDouble(DBL_NAN);
1786 else return copysign(b, copysign(1.0, b) * a);
1791 if (b == 0) return longBitsToDouble(DBL_NAN);
1792 else return copysign(a, copysign(1.0, a) * b);
1795 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1801 /* builtin_ddiv ****************************************************************
1803 Implementation as described in VM Spec.
1805 *******************************************************************************/
1807 double builtin_ddiv(double a, double b)
1811 /* If neither value1' nor value2' is NaN, the sign of the result */
1812 /* is positive if both values have the same sign, negative if the */
1813 /* values have different signs. */
1819 /* If either value1' or value2' is NaN, the result is NaN. */
1821 return longBitsToDouble(DBL_NAN);
1824 /* Division of a finite value by an infinity results in a */
1825 /* signed zero, with the sign-producing rule just given. */
1827 /* is sign equal? */
1829 if (copysign(1.0, a) == copysign(1.0, b))
1838 /* If either value1' or value2' is NaN, the result is NaN. */
1840 return longBitsToDouble(DBL_NAN);
1842 } else if (finite(b)) {
1843 /* Division of an infinity by a finite value results in a signed */
1844 /* infinity, with the sign-producing rule just given. */
1846 /* is sign equal? */
1848 if (copysign(1.0, a) == copysign(1.0, b))
1849 return longBitsToDouble(DBL_POSINF);
1851 return longBitsToDouble(DBL_NEGINF);
1854 /* Division of an infinity by an infinity results in NaN. */
1856 return longBitsToDouble(DBL_NAN);
1862 /* builtin_dneg ****************************************************************
1864 Implemented as described in VM Spec.
1866 *******************************************************************************/
1868 double builtin_dneg(double a)
1871 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1878 /* If the operand is a zero, the result is the zero of opposite */
1884 /* If the operand is an infinity, the result is the infinity of */
1885 /* opposite sign. */
1887 return copysign(a, -copysign(1.0, a));
1891 #endif /* !SUPPORT_DOUBLE */
1894 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1895 s4 builtin_dcmpl(double a, double b)
1903 if (!finite(a) || !finite(b)) {
1904 a = finite(a) ? 0 : copysign(1.0, a);
1905 b = finite(b) ? 0 : copysign(1.0, b);
1918 s4 builtin_dcmpg(double a, double b)
1926 if (!finite(a) || !finite(b)) {
1927 a = finite(a) ? 0 : copysign(1.0, a);
1928 b = finite(b) ? 0 : copysign(1.0, b);
1939 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1942 double builtin_drem(double a, double b)
1948 /* conversion operations ******************************************************/
1950 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1951 float builtin_i2f(s4 a)
1953 float f = (float) a;
1956 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
1959 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
1960 double builtin_i2d(s4 a)
1962 double d = (double) a;
1965 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
1968 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
1969 float builtin_l2f(s8 a)
1971 float f = (float) a;
1974 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
1977 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
1978 double builtin_l2d(s8 a)
1980 double d = (double) a;
1983 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
1986 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1987 s4 builtin_f2i(float a)
1991 i = builtin_d2i((double) a);
2002 if (a < (-2147483648))
2003 return (-2147483648);
2006 f = copysignf((float) 1.0, a);
2009 return (-2147483648); */
2011 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2014 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2015 s8 builtin_f2l(float a)
2019 l = builtin_d2l((double) a);
2026 if (a > 9223372036854775807L)
2027 return 9223372036854775807L;
2028 if (a < (-9223372036854775808L))
2029 return (-9223372036854775808L);
2034 f = copysignf((float) 1.0, a);
2036 return 9223372036854775807L;
2037 return (-9223372036854775808L); */
2039 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2042 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2043 s4 builtin_d2i(double a)
2048 if (a >= 2147483647)
2050 if (a <= (-2147483647-1))
2051 return (-2147483647-1);
2056 d = copysign(1.0, a);
2059 return (-2147483647-1);
2061 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2064 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2065 s8 builtin_d2l(double a)
2070 if (a >= 9223372036854775807LL)
2071 return 9223372036854775807LL;
2072 if (a <= (-9223372036854775807LL-1))
2073 return (-9223372036854775807LL-1);
2078 d = copysign(1.0, a);
2080 return 9223372036854775807LL;
2081 return (-9223372036854775807LL-1);
2083 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2086 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2087 double builtin_f2d(float a)
2089 if (finitef(a)) return (double) a;
2092 return longBitsToDouble(DBL_NAN);
2094 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2098 float builtin_d2f(double a)
2104 return intBitsToFloat(FLT_NAN);
2106 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2109 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2112 /*============================================================================*/
2113 /* AUTOMATICALLY REPLACED FUNCTIONS */
2114 /*============================================================================*/
2116 /* builtin_arraycopy ***********************************************************
2118 Builtin for java.lang.System.arraycopy.
2120 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2122 *******************************************************************************/
2124 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2125 java_handle_t *dest, s4 destStart, s4 len)
2127 arraydescriptor *sdesc;
2128 arraydescriptor *ddesc;
2131 if ((src == NULL) || (dest == NULL)) {
2132 exceptions_throw_nullpointerexception();
2136 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2137 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2139 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2140 exceptions_throw_arraystoreexception();
2144 // Check if offsets and length are positive.
2145 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2146 exceptions_throw_arrayindexoutofboundsexception();
2150 // Check if ranges are valid.
2151 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2152 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2153 exceptions_throw_arrayindexoutofboundsexception();
2162 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2163 /* We copy primitive values or references of exactly the same type */
2165 s4 dataoffset = sdesc->dataoffset;
2166 s4 componentsize = sdesc->componentsize;
2168 LLNI_CRITICAL_START;
2170 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2171 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2172 u1, (size_t) len * componentsize);
2177 /* We copy references of different type */
2179 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2180 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2182 if (destStart <= srcStart) {
2183 for (i = 0; i < len; i++) {
2186 o = array_objectarray_element_get(oas, srcStart + i);
2188 if (!builtin_canstore(oad, o))
2191 array_objectarray_element_set(oad, destStart + i, o);
2195 /* XXX this does not completely obey the specification!
2196 If an exception is thrown only the elements above the
2197 current index have been copied. The specification
2198 requires that only the elements *below* the current
2199 index have been copied before the throw. */
2201 for (i = len - 1; i >= 0; i--) {
2204 o = array_objectarray_element_get(oas, srcStart + i);
2206 if (!builtin_canstore(oad, o))
2209 array_objectarray_element_set(oad, destStart + i, o);
2216 /* builtin_nanotime ************************************************************
2218 Return the current time in nanoseconds.
2220 *******************************************************************************/
2222 s8 builtin_nanotime(void)
2227 if (gettimeofday(&tv, NULL) == -1)
2228 vm_abort("gettimeofday failed: %s", strerror(errno));
2230 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2232 return usecs * 1000;
2236 /* builtin_currenttimemillis ***************************************************
2238 Return the current time in milliseconds.
2240 *******************************************************************************/
2242 s8 builtin_currenttimemillis(void)
2246 msecs = builtin_nanotime() / 1000 / 1000;
2252 /* builtin_clone ***************************************************************
2254 Function for cloning objects or arrays.
2256 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2258 *******************************************************************************/
2260 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2262 arraydescriptor *ad;
2265 java_handle_t *co; /* cloned object header */
2267 /* get the array descriptor */
2269 ad = LLNI_vftbl_direct(o)->arraydesc;
2271 /* we are cloning an array */
2274 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2276 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2281 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2282 /* XXX this is only a dirty hack to make Boehm work with handles */
2284 co = LLNI_WRAP((java_object_t *) co);
2287 LLNI_CRITICAL_START;
2289 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2291 #if defined(ENABLE_GC_CACAO)
2292 heap_init_objectheader(LLNI_DIRECT(co), size);
2295 #if defined(ENABLE_THREADS)
2296 LLNI_DIRECT(co)->lockword.init();
2304 /* we are cloning a non-array */
2306 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2307 exceptions_throw_clonenotsupportedexception();
2311 /* get the class of the object */
2313 LLNI_class_get(o, c);
2315 /* create new object */
2317 co = builtin_new(c);
2322 LLNI_CRITICAL_START;
2324 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2326 #if defined(ENABLE_GC_CACAO)
2327 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2330 #if defined(ENABLE_THREADS)
2331 LLNI_DIRECT(co)->lockword.init();
2340 #if defined(ENABLE_CYCLES_STATS)
2341 void builtin_print_cycles_stats(FILE *file)
2343 fprintf(file,"builtin cylce count statistics:\n");
2345 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2346 CYCLES_STATS_PRINT(builtin_new ,file);
2350 #endif /* defined(ENABLE_CYCLES_STATS) */
2353 #if defined(ENABLE_VMLOG)
2355 #include <vmlog_cacao.c>
2360 * These are local overrides for various environment variables in Emacs.
2361 * Please do not remove this and leave it at the end of the file, where
2362 * Emacs will automagically detect them.
2363 * ---------------------------------------------------------------------
2366 * indent-tabs-mode: t
2370 * vim:noexpandtab:sw=4:ts=4: