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.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 the restricted subtype relation (see
647 Cliff Click and John Rose: Fast subtype checking in the Hotspot JVM.)
650 1......s is a subtype of t.
653 *******************************************************************************/
655 bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
657 if (s->subtype_display[t->subtype_depth] == t)
659 if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
661 return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
665 /* builtin_fast_canstore *******************************************************
667 Checks, if an object can be stored in an array.
671 0......otherwise (no exception thrown!)
673 NOTE: This is a FAST builtin and can be called from JIT code only.
675 *******************************************************************************/
677 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
679 arraydescriptor *desc;
680 arraydescriptor *valuedesc;
681 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 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;
763 /* The following is guaranteed (by verifier checks):
765 * *) a->...vftbl->arraydesc != NULL
766 * *) a->...vftbl->arraydesc->elementvftbl != NULL
767 * *) a->...vftbl->arraydesc->dimension == 1
768 * *) o->vftbl is not an interface vftbl
771 desc = a->header.objheader.vftbl->arraydesc;
772 elementvftbl = desc->elementvftbl;
773 valuevftbl = o->vftbl;
775 /* {a is a one-dimensional array} */
777 if (valuevftbl == elementvftbl)
780 LOCK_CLASSRENUMBER_LOCK;
782 baseval = elementvftbl->baseval;
785 /* an array of interface references */
786 result = ((valuevftbl->interfacetablelength > -baseval) &&
787 (valuevftbl->interfacetable[baseval] != NULL));
791 result = fast_subtype_check(valuevftbl, elementvftbl);
793 diffval = valuevftbl->baseval - elementvftbl->baseval;
794 result = diffval <= (uint32_t) elementvftbl->diffval;
798 UNLOCK_CLASSRENUMBER_LOCK;
804 /* This is an optimized version where a is guaranteed to be a
805 * one-dimensional array of a class type */
806 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
808 vftbl_t *elementvftbl;
816 /* The following is guaranteed (by verifier checks):
818 * *) a->...vftbl->arraydesc != NULL
819 * *) a->...vftbl->arraydesc->elementvftbl != NULL
820 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
821 * *) a->...vftbl->arraydesc->dimension == 1
822 * *) o->vftbl is not an interface vftbl
825 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
826 valuevftbl = o->vftbl;
828 /* {a is a one-dimensional array} */
830 if (valuevftbl == elementvftbl)
833 LOCK_CLASSRENUMBER_LOCK;
836 result = fast_subtype_check(valuevftbl, elementvftbl);
838 diffval = valuevftbl->baseval - elementvftbl->baseval;
839 result = diffval <= (uint32_t) elementvftbl->diffval;
842 UNLOCK_CLASSRENUMBER_LOCK;
848 /* builtin_new *****************************************************************
850 Creates a new instance of class c on the heap.
853 pointer to the object, or NULL if no memory is available
855 NOTE: This builtin can be called from NATIVE code only.
857 *******************************************************************************/
859 java_handle_t *builtin_new(classinfo *c)
862 #if defined(ENABLE_RT_TIMING)
863 struct timespec time_start, time_end;
865 #if defined(ENABLE_CYCLES_STATS)
866 u8 cycles_start, cycles_end;
869 RT_TIMING_GET_TIME(time_start);
870 CYCLES_STATS_GET(cycles_start);
872 /* is the class loaded */
874 assert(c->state & CLASS_LOADED);
876 /* check if we can instantiate this class */
878 if (c->flags & ACC_ABSTRACT) {
879 exceptions_throw_instantiationerror(c);
883 /* is the class linked */
885 if (!(c->state & CLASS_LINKED))
889 if (!(c->state & CLASS_INITIALIZED)) {
892 log_message_class("Initialize class (from builtin_new): ", c);
895 if (!initialize_class(c))
899 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
905 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
906 /* XXX this is only a dirty hack to make Boehm work with handles */
908 o = LLNI_WRAP((java_object_t *) o);
911 LLNI_vftbl_direct(o) = c->vftbl;
913 #if defined(ENABLE_THREADS)
914 LLNI_DIRECT(o)->lockword.init();
917 CYCLES_STATS_GET(cycles_end);
918 RT_TIMING_GET_TIME(time_end);
920 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
921 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
926 #if defined(ENABLE_ESCAPE_REASON)
927 java_handle_t *builtin_escape_reason_new(classinfo *c) {
928 print_escape_reasons();
929 return builtin_java_new(c);
933 #if defined(ENABLE_TLH)
934 java_handle_t *builtin_tlh_new(classinfo *c)
937 # if defined(ENABLE_RT_TIMING)
938 struct timespec time_start, time_end;
940 # if defined(ENABLE_CYCLES_STATS)
941 u8 cycles_start, cycles_end;
944 RT_TIMING_GET_TIME(time_start);
945 CYCLES_STATS_GET(cycles_start);
947 /* is the class loaded */
949 assert(c->state & CLASS_LOADED);
951 /* check if we can instantiate this class */
953 if (c->flags & ACC_ABSTRACT) {
954 exceptions_throw_instantiationerror(c);
958 /* is the class linked */
960 if (!(c->state & CLASS_LINKED))
964 if (!(c->state & CLASS_INITIALIZED)) {
965 # if !defined(NDEBUG)
967 log_message_class("Initialize class (from builtin_new): ", c);
970 if (!initialize_class(c))
975 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
980 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
987 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
988 /* XXX this is only a dirty hack to make Boehm work with handles */
990 o = LLNI_WRAP((java_object_t *) o);
993 LLNI_vftbl_direct(o) = c->vftbl;
995 # if defined(ENABLE_THREADS)
996 LLNI_DIRECT(o)->lockword.init();
999 CYCLES_STATS_GET(cycles_end);
1000 RT_TIMING_GET_TIME(time_end);
1003 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1004 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1012 /* builtin_java_new ************************************************************
1014 NOTE: This is a SLOW builtin and can be called from JIT code only.
1016 *******************************************************************************/
1018 java_handle_t *builtin_java_new(java_handle_t *clazz)
1020 return builtin_new(LLNI_classinfo_unwrap(clazz));
1024 /* builtin_fast_new ************************************************************
1026 Creates a new instance of class c on the heap.
1029 pointer to the object, or NULL if no fast return
1030 is possible for any reason.
1032 NOTE: This is a FAST builtin and can be called from JIT code only.
1034 *******************************************************************************/
1036 java_object_t *builtin_fast_new(classinfo *c)
1039 #if defined(ENABLE_RT_TIMING)
1040 struct timespec time_start, time_end;
1042 #if defined(ENABLE_CYCLES_STATS)
1043 u8 cycles_start, cycles_end;
1046 RT_TIMING_GET_TIME(time_start);
1047 CYCLES_STATS_GET(cycles_start);
1049 /* is the class loaded */
1051 assert(c->state & CLASS_LOADED);
1053 /* check if we can instantiate this class */
1055 if (c->flags & ACC_ABSTRACT)
1058 /* is the class linked */
1060 if (!(c->state & CLASS_LINKED))
1063 if (!(c->state & CLASS_INITIALIZED))
1066 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1067 c->finalizer, false);
1072 o->vftbl = c->vftbl;
1074 #if defined(ENABLE_THREADS)
1075 LLNI_DIRECT(o)->lockword.init();
1078 CYCLES_STATS_GET(cycles_end);
1079 RT_TIMING_GET_TIME(time_end);
1081 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1082 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1088 /* builtin_newarray ************************************************************
1090 Creates an array with the given vftbl on the heap. This function
1091 takes as class argument an array class.
1094 pointer to the array or NULL if no memory is available
1096 NOTE: This builtin can be called from NATIVE code only.
1098 *******************************************************************************/
1100 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1102 arraydescriptor *desc;
1107 #if defined(ENABLE_RT_TIMING)
1108 struct timespec time_start, time_end;
1111 RT_TIMING_GET_TIME(time_start);
1113 desc = arrayclass->vftbl->arraydesc;
1114 dataoffset = desc->dataoffset;
1115 componentsize = desc->componentsize;
1118 exceptions_throw_negativearraysizeexception();
1122 actualsize = dataoffset + size * componentsize;
1124 /* check for overflow */
1126 if (((u4) actualsize) < ((u4) size)) {
1127 exceptions_throw_outofmemoryerror();
1131 a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1136 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1137 /* XXX this is only a dirty hack to make Boehm work with handles */
1139 a = LLNI_WRAP((java_object_t *) a);
1142 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1144 #if defined(ENABLE_THREADS)
1145 LLNI_DIRECT(a)->lockword.init();
1148 LLNI_array_size(a) = size;
1150 RT_TIMING_GET_TIME(time_end);
1151 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1157 /* builtin_java_newarray *******************************************************
1159 NOTE: This is a SLOW builtin and can be called from JIT code only.
1161 *******************************************************************************/
1163 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1165 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1169 /* builtin_anewarray ***********************************************************
1171 Creates an array of references to the given class type on the heap.
1174 pointer to the array or NULL if no memory is
1177 NOTE: This builtin can be called from NATIVE code only.
1179 *******************************************************************************/
1181 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1183 classinfo *arrayclass;
1185 /* is class loaded */
1187 assert(componentclass->state & CLASS_LOADED);
1189 /* is class linked */
1191 if (!(componentclass->state & CLASS_LINKED))
1192 if (!link_class(componentclass))
1195 arrayclass = class_array_of(componentclass, true);
1200 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1204 /* builtin_newarray_type ****************************************************
1206 Creates an array of [type]s on the heap.
1209 pointer to the array or NULL if no memory is available
1211 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1213 *******************************************************************************/
1215 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1216 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1218 return (java_handle_##type##array_t *) \
1219 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1222 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1223 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1224 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1225 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1226 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1227 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1228 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1229 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1232 /* builtin_multianewarray_intern ***********************************************
1234 Creates a multi-dimensional array on the heap. The dimensions are
1235 passed in an array of longs.
1238 n.............number of dimensions to create
1239 arrayclass....the array class
1240 dims..........array containing the size of each dimension to create
1243 pointer to the array or NULL if no memory is available
1245 ******************************************************************************/
1247 static java_handle_t *builtin_multianewarray_intern(int n,
1248 classinfo *arrayclass,
1253 classinfo *componentclass;
1256 /* create this dimension */
1258 size = (s4) dims[0];
1259 a = builtin_newarray(size, arrayclass);
1264 /* if this is the last dimension return */
1269 /* get the class of the components to create */
1271 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1273 /* The verifier guarantees that the dimension count is in the range. */
1275 /* create the component arrays */
1277 for (i = 0; i < size; i++) {
1279 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1280 /* we save an s4 to a s8 slot, 8-byte aligned */
1282 builtin_multianewarray_intern(n, componentclass, dims + 2);
1284 builtin_multianewarray_intern(n, componentclass, dims + 1);
1290 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1297 /* builtin_multianewarray ******************************************************
1299 Wrapper for builtin_multianewarray_intern which checks all
1300 dimensions before we start allocating.
1302 NOTE: This is a SLOW builtin and can be called from JIT code only.
1304 ******************************************************************************/
1306 java_handle_objectarray_t *builtin_multianewarray(int n,
1307 java_handle_t *arrayclazz,
1314 /* check all dimensions before doing anything */
1316 for (i = 0; i < n; i++) {
1317 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1318 /* we save an s4 to a s8 slot, 8-byte aligned */
1319 size = (s4) dims[i * 2];
1321 size = (s4) dims[i];
1325 exceptions_throw_negativearraysizeexception();
1330 c = LLNI_classinfo_unwrap(arrayclazz);
1332 /* now call the real function */
1334 return (java_handle_objectarray_t *)
1335 builtin_multianewarray_intern(n, c, dims);
1339 /* builtin_verbosecall_enter ***************************************************
1341 Print method call with arguments for -verbose:call.
1343 XXX: Remove mew once all archs use the new tracer!
1345 *******************************************************************************/
1347 #if !defined(NDEBUG)
1348 #ifdef TRACE_ARGS_NUM
1349 void builtin_verbosecall_enter(s8 a0, s8 a1,
1350 # if TRACE_ARGS_NUM >= 4
1353 # if TRACE_ARGS_NUM >= 6
1356 # if TRACE_ARGS_NUM == 8
1361 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1364 #endif /* !defined(NDEBUG) */
1367 /* builtin_verbosecall_exit ****************************************************
1369 Print method exit for -verbose:call.
1371 XXX: Remove mew once all archs use the new tracer!
1373 *******************************************************************************/
1375 #if !defined(NDEBUG)
1376 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1378 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1380 #endif /* !defined(NDEBUG) */
1383 /*============================================================================*/
1384 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1385 /*============================================================================*/
1387 /*********** Functions for integer divisions *****************************
1389 On some systems (eg. DEC ALPHA), integer division is not supported by the
1390 CPU. These helper functions implement the missing functionality.
1392 ******************************************************************************/
1394 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1395 s4 builtin_idiv(s4 a, s4 b)
1404 s4 builtin_irem(s4 a, s4 b)
1412 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1415 /* functions for long arithmetics **********************************************
1417 On systems where 64 bit Integers are not supported by the CPU,
1418 these functions are needed.
1420 ******************************************************************************/
1422 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1423 s8 builtin_ladd(s8 a, s8 b)
1432 s8 builtin_lsub(s8 a, s8 b)
1441 s8 builtin_lneg(s8 a)
1449 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1452 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1453 s8 builtin_lmul(s8 a, s8 b)
1461 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1464 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1465 s8 builtin_ldiv(s8 a, s8 b)
1474 s8 builtin_lrem(s8 a, s8 b)
1482 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1485 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1486 s8 builtin_lshl(s8 a, s4 b)
1495 s8 builtin_lshr(s8 a, s4 b)
1504 s8 builtin_lushr(s8 a, s4 b)
1508 c = ((u8) a) >> (b & 63);
1512 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1515 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1516 s8 builtin_land(s8 a, s8 b)
1525 s8 builtin_lor(s8 a, s8 b)
1534 s8 builtin_lxor(s8 a, s8 b)
1542 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1545 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1546 s4 builtin_lcmp(s8 a, s8 b)
1556 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1559 /* functions for unsupported floating instructions ****************************/
1561 /* used to convert FLT_xxx defines into float values */
1563 static inline float intBitsToFloat(s4 i)
1572 /* used to convert DBL_xxx defines into double values */
1574 static inline float longBitsToDouble(s8 l)
1584 float builtin_fadd(float a, float b)
1586 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1587 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1598 if (copysignf(1.0, a) == copysignf(1.0, b))
1601 return intBitsToFloat(FLT_NAN);
1607 float builtin_fsub(float a, float b)
1609 return builtin_fadd(a, builtin_fneg(b));
1613 float builtin_fmul(float a, float b)
1615 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1616 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1618 if (finitef(b)) return a * b;
1620 if (a == 0) return intBitsToFloat(FLT_NAN);
1621 else return copysignf(b, copysignf(1.0, b)*a);
1626 if (b == 0) return intBitsToFloat(FLT_NAN);
1627 else return copysignf(a, copysignf(1.0, a)*b);
1630 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1636 /* builtin_ddiv ****************************************************************
1638 Implementation as described in VM Spec.
1640 *******************************************************************************/
1642 float builtin_fdiv(float a, float b)
1646 /* If neither value1' nor value2' is NaN, the sign of the result */
1647 /* is positive if both values have the same sign, negative if the */
1648 /* values have different signs. */
1654 /* If either value1' or value2' is NaN, the result is NaN. */
1656 return intBitsToFloat(FLT_NAN);
1659 /* Division of a finite value by an infinity results in a */
1660 /* signed zero, with the sign-producing rule just given. */
1662 /* is sign equal? */
1664 if (copysignf(1.0, a) == copysignf(1.0, b))
1673 /* If either value1' or value2' is NaN, the result is NaN. */
1675 return intBitsToFloat(FLT_NAN);
1677 } else if (finitef(b)) {
1678 /* Division of an infinity by a finite value results in a signed */
1679 /* infinity, with the sign-producing rule just given. */
1681 /* is sign equal? */
1683 if (copysignf(1.0, a) == copysignf(1.0, b))
1684 return intBitsToFloat(FLT_POSINF);
1686 return intBitsToFloat(FLT_NEGINF);
1689 /* Division of an infinity by an infinity results in NaN. */
1691 return intBitsToFloat(FLT_NAN);
1697 float builtin_fneg(float a)
1699 if (isnanf(a)) return a;
1701 if (finitef(a)) return -a;
1702 else return copysignf(a, -copysignf(1.0, a));
1705 #endif /* !SUPPORT_FLOAT */
1708 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1709 s4 builtin_fcmpl(float a, float b)
1717 if (!finitef(a) || !finitef(b)) {
1718 a = finitef(a) ? 0 : copysignf(1.0, a);
1719 b = finitef(b) ? 0 : copysignf(1.0, b);
1732 s4 builtin_fcmpg(float a, float b)
1734 if (isnanf(a)) return 1;
1735 if (isnanf(b)) return 1;
1736 if (!finitef(a) || !finitef(b)) {
1737 a = finitef(a) ? 0 : copysignf(1.0, a);
1738 b = finitef(b) ? 0 : copysignf(1.0, b);
1740 if (a > b) return 1;
1741 if (a == b) return 0;
1744 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1747 float builtin_frem(float a, float b)
1753 /* functions for unsupported double instructions ******************************/
1756 double builtin_dadd(double a, double b)
1758 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1759 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1761 if (finite(b)) return a + b;
1765 if (finite(b)) return a;
1767 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1768 else return longBitsToDouble(DBL_NAN);
1774 double builtin_dsub(double a, double b)
1776 return builtin_dadd(a, builtin_dneg(b));
1780 double builtin_dmul(double a, double b)
1782 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1783 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1785 if (finite(b)) return a * b;
1787 if (a == 0) return longBitsToDouble(DBL_NAN);
1788 else return copysign(b, copysign(1.0, b) * a);
1793 if (b == 0) return longBitsToDouble(DBL_NAN);
1794 else return copysign(a, copysign(1.0, a) * b);
1797 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1803 /* builtin_ddiv ****************************************************************
1805 Implementation as described in VM Spec.
1807 *******************************************************************************/
1809 double builtin_ddiv(double a, double b)
1813 /* If neither value1' nor value2' is NaN, the sign of the result */
1814 /* is positive if both values have the same sign, negative if the */
1815 /* values have different signs. */
1821 /* If either value1' or value2' is NaN, the result is NaN. */
1823 return longBitsToDouble(DBL_NAN);
1826 /* Division of a finite value by an infinity results in a */
1827 /* signed zero, with the sign-producing rule just given. */
1829 /* is sign equal? */
1831 if (copysign(1.0, a) == copysign(1.0, b))
1840 /* If either value1' or value2' is NaN, the result is NaN. */
1842 return longBitsToDouble(DBL_NAN);
1844 } else if (finite(b)) {
1845 /* Division of an infinity by a finite value results in a signed */
1846 /* infinity, with the sign-producing rule just given. */
1848 /* is sign equal? */
1850 if (copysign(1.0, a) == copysign(1.0, b))
1851 return longBitsToDouble(DBL_POSINF);
1853 return longBitsToDouble(DBL_NEGINF);
1856 /* Division of an infinity by an infinity results in NaN. */
1858 return longBitsToDouble(DBL_NAN);
1864 /* builtin_dneg ****************************************************************
1866 Implemented as described in VM Spec.
1868 *******************************************************************************/
1870 double builtin_dneg(double a)
1873 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1880 /* If the operand is a zero, the result is the zero of opposite */
1886 /* If the operand is an infinity, the result is the infinity of */
1887 /* opposite sign. */
1889 return copysign(a, -copysign(1.0, a));
1893 #endif /* !SUPPORT_DOUBLE */
1896 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1897 s4 builtin_dcmpl(double a, double b)
1905 if (!finite(a) || !finite(b)) {
1906 a = finite(a) ? 0 : copysign(1.0, a);
1907 b = finite(b) ? 0 : copysign(1.0, b);
1920 s4 builtin_dcmpg(double a, double b)
1928 if (!finite(a) || !finite(b)) {
1929 a = finite(a) ? 0 : copysign(1.0, a);
1930 b = finite(b) ? 0 : copysign(1.0, b);
1941 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1944 double builtin_drem(double a, double b)
1950 /* conversion operations ******************************************************/
1952 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1953 float builtin_i2f(s4 a)
1955 float f = (float) a;
1958 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
1961 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
1962 double builtin_i2d(s4 a)
1964 double d = (double) a;
1967 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
1970 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
1971 float builtin_l2f(s8 a)
1973 float f = (float) a;
1976 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
1979 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
1980 double builtin_l2d(s8 a)
1982 double d = (double) a;
1985 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
1988 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1989 s4 builtin_f2i(float a)
1993 i = builtin_d2i((double) a);
2004 if (a < (-2147483648))
2005 return (-2147483648);
2008 f = copysignf((float) 1.0, a);
2011 return (-2147483648); */
2013 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2016 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2017 s8 builtin_f2l(float a)
2021 l = builtin_d2l((double) a);
2028 if (a > 9223372036854775807L)
2029 return 9223372036854775807L;
2030 if (a < (-9223372036854775808L))
2031 return (-9223372036854775808L);
2036 f = copysignf((float) 1.0, a);
2038 return 9223372036854775807L;
2039 return (-9223372036854775808L); */
2041 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2044 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2045 s4 builtin_d2i(double a)
2050 if (a >= 2147483647)
2052 if (a <= (-2147483647-1))
2053 return (-2147483647-1);
2058 d = copysign(1.0, a);
2061 return (-2147483647-1);
2063 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2066 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2067 s8 builtin_d2l(double a)
2072 if (a >= 9223372036854775807LL)
2073 return 9223372036854775807LL;
2074 if (a <= (-9223372036854775807LL-1))
2075 return (-9223372036854775807LL-1);
2080 d = copysign(1.0, a);
2082 return 9223372036854775807LL;
2083 return (-9223372036854775807LL-1);
2085 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2088 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2089 double builtin_f2d(float a)
2091 if (finitef(a)) return (double) a;
2094 return longBitsToDouble(DBL_NAN);
2096 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2100 float builtin_d2f(double a)
2106 return intBitsToFloat(FLT_NAN);
2108 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2111 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2114 /*============================================================================*/
2115 /* AUTOMATICALLY REPLACED FUNCTIONS */
2116 /*============================================================================*/
2118 /* builtin_arraycopy ***********************************************************
2120 Builtin for java.lang.System.arraycopy.
2122 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2124 *******************************************************************************/
2126 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2127 java_handle_t *dest, s4 destStart, s4 len)
2129 arraydescriptor *sdesc;
2130 arraydescriptor *ddesc;
2133 if ((src == NULL) || (dest == NULL)) {
2134 exceptions_throw_nullpointerexception();
2138 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2139 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2141 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2142 exceptions_throw_arraystoreexception();
2146 // Check if offsets and length are positive.
2147 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2148 exceptions_throw_arrayindexoutofboundsexception();
2152 // Check if ranges are valid.
2153 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2154 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2155 exceptions_throw_arrayindexoutofboundsexception();
2164 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2165 /* We copy primitive values or references of exactly the same type */
2167 s4 dataoffset = sdesc->dataoffset;
2168 s4 componentsize = sdesc->componentsize;
2170 LLNI_CRITICAL_START;
2172 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2173 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2174 u1, (size_t) len * componentsize);
2179 /* We copy references of different type */
2181 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2182 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2184 if (destStart <= srcStart) {
2185 for (i = 0; i < len; i++) {
2188 o = array_objectarray_element_get(oas, srcStart + i);
2190 if (!builtin_canstore(oad, o))
2193 array_objectarray_element_set(oad, destStart + i, o);
2197 /* XXX this does not completely obey the specification!
2198 If an exception is thrown only the elements above the
2199 current index have been copied. The specification
2200 requires that only the elements *below* the current
2201 index have been copied before the throw. */
2203 for (i = len - 1; i >= 0; i--) {
2206 o = array_objectarray_element_get(oas, srcStart + i);
2208 if (!builtin_canstore(oad, o))
2211 array_objectarray_element_set(oad, destStart + i, o);
2218 /* builtin_nanotime ************************************************************
2220 Return the current time in nanoseconds.
2222 *******************************************************************************/
2224 s8 builtin_nanotime(void)
2229 if (gettimeofday(&tv, NULL) == -1)
2230 vm_abort("gettimeofday failed: %s", strerror(errno));
2232 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2234 return usecs * 1000;
2238 /* builtin_currenttimemillis ***************************************************
2240 Return the current time in milliseconds.
2242 *******************************************************************************/
2244 s8 builtin_currenttimemillis(void)
2248 msecs = builtin_nanotime() / 1000 / 1000;
2254 /* builtin_clone ***************************************************************
2256 Function for cloning objects or arrays.
2258 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2260 *******************************************************************************/
2262 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2264 arraydescriptor *ad;
2267 java_handle_t *co; /* cloned object header */
2269 /* get the array descriptor */
2271 ad = LLNI_vftbl_direct(o)->arraydesc;
2273 /* we are cloning an array */
2276 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2278 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2283 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2284 /* XXX this is only a dirty hack to make Boehm work with handles */
2286 co = LLNI_WRAP((java_object_t *) co);
2289 LLNI_CRITICAL_START;
2291 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2293 #if defined(ENABLE_GC_CACAO)
2294 heap_init_objectheader(LLNI_DIRECT(co), size);
2297 #if defined(ENABLE_THREADS)
2298 LLNI_DIRECT(co)->lockword.init();
2306 /* we are cloning a non-array */
2308 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2309 exceptions_throw_clonenotsupportedexception();
2313 /* get the class of the object */
2315 LLNI_class_get(o, c);
2317 /* create new object */
2319 co = builtin_new(c);
2324 LLNI_CRITICAL_START;
2326 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2328 #if defined(ENABLE_GC_CACAO)
2329 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2332 #if defined(ENABLE_THREADS)
2333 LLNI_DIRECT(co)->lockword.init();
2342 #if defined(ENABLE_CYCLES_STATS)
2343 void builtin_print_cycles_stats(FILE *file)
2345 fprintf(file,"builtin cylce count statistics:\n");
2347 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2348 CYCLES_STATS_PRINT(builtin_new ,file);
2352 #endif /* defined(ENABLE_CYCLES_STATS) */
2355 #if defined(ENABLE_VMLOG)
2357 #include <vmlog_cacao.c>
2362 * These are local overrides for various environment variables in Emacs.
2363 * Please do not remove this and leave it at the end of the file, where
2364 * Emacs will automagically detect them.
2365 * ---------------------------------------------------------------------
2368 * indent-tabs-mode: t
2372 * vim:noexpandtab:sw=4:ts=4: