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 /* builtin_fast_canstore *******************************************************
646 Checks, if an object can be stored in an array.
650 0......otherwise (no exception thrown!)
652 NOTE: This is a FAST builtin and can be called from JIT code only.
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;
665 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
667 arraydescriptor *desc;
668 arraydescriptor *valuedesc;
669 vftbl_t *componentvftbl;
678 /* The following is guaranteed (by verifier checks):
680 * *) oa->...vftbl->arraydesc != NULL
681 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
682 * *) o->vftbl is not an interface vftbl
685 desc = oa->header.objheader.vftbl->arraydesc;
686 componentvftbl = desc->componentvftbl;
687 valuevftbl = o->vftbl;
688 valuedesc = valuevftbl->arraydesc;
690 if ((desc->dimension - 1) == 0) {
691 /* {oa is a one-dimensional array} */
692 /* {oa is an array of references} */
694 if (valuevftbl == componentvftbl)
697 baseval = componentvftbl->baseval;
700 /* an array of interface references */
702 result = ((valuevftbl->interfacetablelength > -baseval) &&
703 (valuevftbl->interfacetable[baseval] != NULL));
706 result = fast_subtype_check(valuevftbl, componentvftbl);
709 else if (valuedesc == NULL) {
710 /* {oa has dimension > 1} */
711 /* {componentvftbl->arraydesc != NULL} */
713 /* check if o is an array */
718 /* {o is an array} */
720 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
729 /* This is an optimized version where a is guaranteed to be one-dimensional */
730 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
732 arraydescriptor *desc;
733 vftbl_t *elementvftbl;
742 /* The following is guaranteed (by verifier checks):
744 * *) a->...vftbl->arraydesc != NULL
745 * *) a->...vftbl->arraydesc->elementvftbl != NULL
746 * *) a->...vftbl->arraydesc->dimension == 1
747 * *) o->vftbl is not an interface vftbl
750 desc = a->header.objheader.vftbl->arraydesc;
751 elementvftbl = desc->elementvftbl;
752 valuevftbl = o->vftbl;
754 /* {a is a one-dimensional array} */
756 if (valuevftbl == elementvftbl)
759 baseval = elementvftbl->baseval;
762 /* an array of interface references */
763 result = ((valuevftbl->interfacetablelength > -baseval) &&
764 (valuevftbl->interfacetable[baseval] != NULL));
767 result = fast_subtype_check(valuevftbl, elementvftbl);
774 /* This is an optimized version where a is guaranteed to be a
775 * one-dimensional array of a class type */
776 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
778 vftbl_t *elementvftbl;
786 /* The following is guaranteed (by verifier checks):
788 * *) a->...vftbl->arraydesc != NULL
789 * *) a->...vftbl->arraydesc->elementvftbl != NULL
790 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
791 * *) a->...vftbl->arraydesc->dimension == 1
792 * *) o->vftbl is not an interface vftbl
795 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
796 valuevftbl = o->vftbl;
798 /* {a is a one-dimensional array} */
800 if (valuevftbl == elementvftbl)
803 result = fast_subtype_check(valuevftbl, elementvftbl);
809 /* builtin_new *****************************************************************
811 Creates a new instance of class c on the heap.
814 pointer to the object, or NULL if no memory is available
816 NOTE: This builtin can be called from NATIVE code only.
818 *******************************************************************************/
820 java_handle_t *builtin_new(classinfo *c)
823 #if defined(ENABLE_RT_TIMING)
824 struct timespec time_start, time_end;
826 #if defined(ENABLE_CYCLES_STATS)
827 u8 cycles_start, cycles_end;
830 RT_TIMING_GET_TIME(time_start);
831 CYCLES_STATS_GET(cycles_start);
833 /* is the class loaded */
835 assert(c->state & CLASS_LOADED);
837 /* check if we can instantiate this class */
839 if (c->flags & ACC_ABSTRACT) {
840 exceptions_throw_instantiationerror(c);
844 /* is the class linked */
846 if (!(c->state & CLASS_LINKED))
850 if (!(c->state & CLASS_INITIALIZED)) {
853 log_message_class("Initialize class (from builtin_new): ", c);
856 if (!initialize_class(c))
860 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
866 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
867 /* XXX this is only a dirty hack to make Boehm work with handles */
869 o = LLNI_WRAP((java_object_t *) o);
872 LLNI_vftbl_direct(o) = c->vftbl;
874 #if defined(ENABLE_THREADS)
875 LLNI_DIRECT(o)->lockword.init();
878 CYCLES_STATS_GET(cycles_end);
879 RT_TIMING_GET_TIME(time_end);
881 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
882 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
887 #if defined(ENABLE_ESCAPE_REASON)
888 java_handle_t *builtin_escape_reason_new(classinfo *c) {
889 print_escape_reasons();
890 return builtin_java_new(c);
894 #if defined(ENABLE_TLH)
895 java_handle_t *builtin_tlh_new(classinfo *c)
898 # if defined(ENABLE_RT_TIMING)
899 struct timespec time_start, time_end;
901 # if defined(ENABLE_CYCLES_STATS)
902 u8 cycles_start, cycles_end;
905 RT_TIMING_GET_TIME(time_start);
906 CYCLES_STATS_GET(cycles_start);
908 /* is the class loaded */
910 assert(c->state & CLASS_LOADED);
912 /* check if we can instantiate this class */
914 if (c->flags & ACC_ABSTRACT) {
915 exceptions_throw_instantiationerror(c);
919 /* is the class linked */
921 if (!(c->state & CLASS_LINKED))
925 if (!(c->state & CLASS_INITIALIZED)) {
926 # if !defined(NDEBUG)
928 log_message_class("Initialize class (from builtin_new): ", c);
931 if (!initialize_class(c))
936 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
941 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
948 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
949 /* XXX this is only a dirty hack to make Boehm work with handles */
951 o = LLNI_WRAP((java_object_t *) o);
954 LLNI_vftbl_direct(o) = c->vftbl;
956 # if defined(ENABLE_THREADS)
957 LLNI_DIRECT(o)->lockword.init();
960 CYCLES_STATS_GET(cycles_end);
961 RT_TIMING_GET_TIME(time_end);
964 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
965 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
973 /* builtin_java_new ************************************************************
975 NOTE: This is a SLOW builtin and can be called from JIT code only.
977 *******************************************************************************/
979 java_handle_t *builtin_java_new(java_handle_t *clazz)
981 return builtin_new(LLNI_classinfo_unwrap(clazz));
985 /* builtin_fast_new ************************************************************
987 Creates a new instance of class c on the heap.
990 pointer to the object, or NULL if no fast return
991 is possible for any reason.
993 NOTE: This is a FAST builtin and can be called from JIT code only.
995 *******************************************************************************/
997 java_object_t *builtin_fast_new(classinfo *c)
1000 #if defined(ENABLE_RT_TIMING)
1001 struct timespec time_start, time_end;
1003 #if defined(ENABLE_CYCLES_STATS)
1004 u8 cycles_start, cycles_end;
1007 RT_TIMING_GET_TIME(time_start);
1008 CYCLES_STATS_GET(cycles_start);
1010 /* is the class loaded */
1012 assert(c->state & CLASS_LOADED);
1014 /* check if we can instantiate this class */
1016 if (c->flags & ACC_ABSTRACT)
1019 /* is the class linked */
1021 if (!(c->state & CLASS_LINKED))
1024 if (!(c->state & CLASS_INITIALIZED))
1027 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1028 c->finalizer, false);
1033 o->vftbl = c->vftbl;
1035 #if defined(ENABLE_THREADS)
1036 LLNI_DIRECT(o)->lockword.init();
1039 CYCLES_STATS_GET(cycles_end);
1040 RT_TIMING_GET_TIME(time_end);
1042 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1043 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1049 /* builtin_newarray ************************************************************
1051 Creates an array with the given vftbl on the heap. This function
1052 takes as class argument an array class.
1055 pointer to the array or NULL if no memory is available
1057 NOTE: This builtin can be called from NATIVE code only.
1059 *******************************************************************************/
1061 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1063 arraydescriptor *desc;
1068 #if defined(ENABLE_RT_TIMING)
1069 struct timespec time_start, time_end;
1072 RT_TIMING_GET_TIME(time_start);
1074 desc = arrayclass->vftbl->arraydesc;
1075 dataoffset = desc->dataoffset;
1076 componentsize = desc->componentsize;
1079 exceptions_throw_negativearraysizeexception();
1083 actualsize = dataoffset + size * componentsize;
1085 /* check for overflow */
1087 if (((u4) actualsize) < ((u4) size)) {
1088 exceptions_throw_outofmemoryerror();
1092 a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1097 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1098 /* XXX this is only a dirty hack to make Boehm work with handles */
1100 a = LLNI_WRAP((java_object_t *) a);
1103 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1105 #if defined(ENABLE_THREADS)
1106 LLNI_DIRECT(a)->lockword.init();
1109 LLNI_array_size(a) = size;
1111 RT_TIMING_GET_TIME(time_end);
1112 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1118 /* builtin_java_newarray *******************************************************
1120 NOTE: This is a SLOW builtin and can be called from JIT code only.
1122 *******************************************************************************/
1124 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1126 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1130 /* builtin_anewarray ***********************************************************
1132 Creates an array of references to the given class type on the heap.
1135 pointer to the array or NULL if no memory is
1138 NOTE: This builtin can be called from NATIVE code only.
1140 *******************************************************************************/
1142 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1144 classinfo *arrayclass;
1146 /* is class loaded */
1148 assert(componentclass->state & CLASS_LOADED);
1150 /* is class linked */
1152 if (!(componentclass->state & CLASS_LINKED))
1153 if (!link_class(componentclass))
1156 arrayclass = class_array_of(componentclass, true);
1161 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1165 /* builtin_newarray_type ****************************************************
1167 Creates an array of [type]s on the heap.
1170 pointer to the array or NULL if no memory is available
1172 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1174 *******************************************************************************/
1176 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1177 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1179 return (java_handle_##type##array_t *) \
1180 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1183 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1184 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1185 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1186 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1187 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1188 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1189 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1190 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1193 /* builtin_multianewarray_intern ***********************************************
1195 Creates a multi-dimensional array on the heap. The dimensions are
1196 passed in an array of longs.
1199 n.............number of dimensions to create
1200 arrayclass....the array class
1201 dims..........array containing the size of each dimension to create
1204 pointer to the array or NULL if no memory is available
1206 ******************************************************************************/
1208 static java_handle_t *builtin_multianewarray_intern(int n,
1209 classinfo *arrayclass,
1214 classinfo *componentclass;
1217 /* create this dimension */
1219 size = (s4) dims[0];
1220 a = builtin_newarray(size, arrayclass);
1225 /* if this is the last dimension return */
1230 /* get the class of the components to create */
1232 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1234 /* The verifier guarantees that the dimension count is in the range. */
1236 /* create the component arrays */
1238 for (i = 0; i < size; i++) {
1240 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1241 /* we save an s4 to a s8 slot, 8-byte aligned */
1243 builtin_multianewarray_intern(n, componentclass, dims + 2);
1245 builtin_multianewarray_intern(n, componentclass, dims + 1);
1251 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1258 /* builtin_multianewarray ******************************************************
1260 Wrapper for builtin_multianewarray_intern which checks all
1261 dimensions before we start allocating.
1263 NOTE: This is a SLOW builtin and can be called from JIT code only.
1265 ******************************************************************************/
1267 java_handle_objectarray_t *builtin_multianewarray(int n,
1268 java_handle_t *arrayclazz,
1275 /* check all dimensions before doing anything */
1277 for (i = 0; i < n; i++) {
1278 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1279 /* we save an s4 to a s8 slot, 8-byte aligned */
1280 size = (s4) dims[i * 2];
1282 size = (s4) dims[i];
1286 exceptions_throw_negativearraysizeexception();
1291 c = LLNI_classinfo_unwrap(arrayclazz);
1293 /* now call the real function */
1295 return (java_handle_objectarray_t *)
1296 builtin_multianewarray_intern(n, c, dims);
1300 /* builtin_verbosecall_enter ***************************************************
1302 Print method call with arguments for -verbose:call.
1304 XXX: Remove mew once all archs use the new tracer!
1306 *******************************************************************************/
1308 #if !defined(NDEBUG)
1309 #ifdef TRACE_ARGS_NUM
1310 void builtin_verbosecall_enter(s8 a0, s8 a1,
1311 # if TRACE_ARGS_NUM >= 4
1314 # if TRACE_ARGS_NUM >= 6
1317 # if TRACE_ARGS_NUM == 8
1322 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1325 #endif /* !defined(NDEBUG) */
1328 /* builtin_verbosecall_exit ****************************************************
1330 Print method exit for -verbose:call.
1332 XXX: Remove mew once all archs use the new tracer!
1334 *******************************************************************************/
1336 #if !defined(NDEBUG)
1337 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1339 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1341 #endif /* !defined(NDEBUG) */
1344 /*============================================================================*/
1345 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1346 /*============================================================================*/
1348 /*********** Functions for integer divisions *****************************
1350 On some systems (eg. DEC ALPHA), integer division is not supported by the
1351 CPU. These helper functions implement the missing functionality.
1353 ******************************************************************************/
1355 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1356 s4 builtin_idiv(s4 a, s4 b)
1365 s4 builtin_irem(s4 a, s4 b)
1373 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1376 /* functions for long arithmetics **********************************************
1378 On systems where 64 bit Integers are not supported by the CPU,
1379 these functions are needed.
1381 ******************************************************************************/
1383 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1384 s8 builtin_ladd(s8 a, s8 b)
1393 s8 builtin_lsub(s8 a, s8 b)
1402 s8 builtin_lneg(s8 a)
1410 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1413 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1414 s8 builtin_lmul(s8 a, s8 b)
1422 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1425 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1426 s8 builtin_ldiv(s8 a, s8 b)
1435 s8 builtin_lrem(s8 a, s8 b)
1443 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1446 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1447 s8 builtin_lshl(s8 a, s4 b)
1456 s8 builtin_lshr(s8 a, s4 b)
1465 s8 builtin_lushr(s8 a, s4 b)
1469 c = ((u8) a) >> (b & 63);
1473 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1476 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1477 s8 builtin_land(s8 a, s8 b)
1486 s8 builtin_lor(s8 a, s8 b)
1495 s8 builtin_lxor(s8 a, s8 b)
1503 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1506 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1507 s4 builtin_lcmp(s8 a, s8 b)
1517 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1520 /* functions for unsupported floating instructions ****************************/
1522 /* used to convert FLT_xxx defines into float values */
1524 static inline float intBitsToFloat(s4 i)
1533 /* used to convert DBL_xxx defines into double values */
1535 static inline float longBitsToDouble(s8 l)
1545 float builtin_fadd(float a, float b)
1547 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1548 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1559 if (copysignf(1.0, a) == copysignf(1.0, b))
1562 return intBitsToFloat(FLT_NAN);
1568 float builtin_fsub(float a, float b)
1570 return builtin_fadd(a, builtin_fneg(b));
1574 float builtin_fmul(float a, float b)
1576 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1577 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1579 if (finitef(b)) return a * b;
1581 if (a == 0) return intBitsToFloat(FLT_NAN);
1582 else return copysignf(b, copysignf(1.0, b)*a);
1587 if (b == 0) return intBitsToFloat(FLT_NAN);
1588 else return copysignf(a, copysignf(1.0, a)*b);
1591 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1597 /* builtin_ddiv ****************************************************************
1599 Implementation as described in VM Spec.
1601 *******************************************************************************/
1603 float builtin_fdiv(float a, float b)
1607 /* If neither value1' nor value2' is NaN, the sign of the result */
1608 /* is positive if both values have the same sign, negative if the */
1609 /* values have different signs. */
1615 /* If either value1' or value2' is NaN, the result is NaN. */
1617 return intBitsToFloat(FLT_NAN);
1620 /* Division of a finite value by an infinity results in a */
1621 /* signed zero, with the sign-producing rule just given. */
1623 /* is sign equal? */
1625 if (copysignf(1.0, a) == copysignf(1.0, b))
1634 /* If either value1' or value2' is NaN, the result is NaN. */
1636 return intBitsToFloat(FLT_NAN);
1638 } else if (finitef(b)) {
1639 /* Division of an infinity by a finite value results in a signed */
1640 /* infinity, with the sign-producing rule just given. */
1642 /* is sign equal? */
1644 if (copysignf(1.0, a) == copysignf(1.0, b))
1645 return intBitsToFloat(FLT_POSINF);
1647 return intBitsToFloat(FLT_NEGINF);
1650 /* Division of an infinity by an infinity results in NaN. */
1652 return intBitsToFloat(FLT_NAN);
1658 float builtin_fneg(float a)
1660 if (isnanf(a)) return a;
1662 if (finitef(a)) return -a;
1663 else return copysignf(a, -copysignf(1.0, a));
1666 #endif /* !SUPPORT_FLOAT */
1669 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1670 s4 builtin_fcmpl(float a, float b)
1678 if (!finitef(a) || !finitef(b)) {
1679 a = finitef(a) ? 0 : copysignf(1.0, a);
1680 b = finitef(b) ? 0 : copysignf(1.0, b);
1693 s4 builtin_fcmpg(float a, float b)
1695 if (isnanf(a)) return 1;
1696 if (isnanf(b)) return 1;
1697 if (!finitef(a) || !finitef(b)) {
1698 a = finitef(a) ? 0 : copysignf(1.0, a);
1699 b = finitef(b) ? 0 : copysignf(1.0, b);
1701 if (a > b) return 1;
1702 if (a == b) return 0;
1705 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1708 float builtin_frem(float a, float b)
1714 /* functions for unsupported double instructions ******************************/
1717 double builtin_dadd(double a, double b)
1719 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1720 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1722 if (finite(b)) return a + b;
1726 if (finite(b)) return a;
1728 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1729 else return longBitsToDouble(DBL_NAN);
1735 double builtin_dsub(double a, double b)
1737 return builtin_dadd(a, builtin_dneg(b));
1741 double builtin_dmul(double a, double b)
1743 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1744 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1746 if (finite(b)) return a * b;
1748 if (a == 0) return longBitsToDouble(DBL_NAN);
1749 else return copysign(b, copysign(1.0, b) * a);
1754 if (b == 0) return longBitsToDouble(DBL_NAN);
1755 else return copysign(a, copysign(1.0, a) * b);
1758 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1764 /* builtin_ddiv ****************************************************************
1766 Implementation as described in VM Spec.
1768 *******************************************************************************/
1770 double builtin_ddiv(double a, double b)
1774 /* If neither value1' nor value2' is NaN, the sign of the result */
1775 /* is positive if both values have the same sign, negative if the */
1776 /* values have different signs. */
1782 /* If either value1' or value2' is NaN, the result is NaN. */
1784 return longBitsToDouble(DBL_NAN);
1787 /* Division of a finite value by an infinity results in a */
1788 /* signed zero, with the sign-producing rule just given. */
1790 /* is sign equal? */
1792 if (copysign(1.0, a) == copysign(1.0, b))
1801 /* If either value1' or value2' is NaN, the result is NaN. */
1803 return longBitsToDouble(DBL_NAN);
1805 } else if (finite(b)) {
1806 /* Division of an infinity by a finite value results in a signed */
1807 /* infinity, with the sign-producing rule just given. */
1809 /* is sign equal? */
1811 if (copysign(1.0, a) == copysign(1.0, b))
1812 return longBitsToDouble(DBL_POSINF);
1814 return longBitsToDouble(DBL_NEGINF);
1817 /* Division of an infinity by an infinity results in NaN. */
1819 return longBitsToDouble(DBL_NAN);
1825 /* builtin_dneg ****************************************************************
1827 Implemented as described in VM Spec.
1829 *******************************************************************************/
1831 double builtin_dneg(double a)
1834 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1841 /* If the operand is a zero, the result is the zero of opposite */
1847 /* If the operand is an infinity, the result is the infinity of */
1848 /* opposite sign. */
1850 return copysign(a, -copysign(1.0, a));
1854 #endif /* !SUPPORT_DOUBLE */
1857 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1858 s4 builtin_dcmpl(double a, double b)
1866 if (!finite(a) || !finite(b)) {
1867 a = finite(a) ? 0 : copysign(1.0, a);
1868 b = finite(b) ? 0 : copysign(1.0, b);
1881 s4 builtin_dcmpg(double a, double b)
1889 if (!finite(a) || !finite(b)) {
1890 a = finite(a) ? 0 : copysign(1.0, a);
1891 b = finite(b) ? 0 : copysign(1.0, b);
1902 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1905 double builtin_drem(double a, double b)
1911 /* conversion operations ******************************************************/
1913 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1914 float builtin_i2f(s4 a)
1916 float f = (float) a;
1919 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
1922 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
1923 double builtin_i2d(s4 a)
1925 double d = (double) a;
1928 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
1931 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
1932 float builtin_l2f(s8 a)
1934 float f = (float) a;
1937 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
1940 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
1941 double builtin_l2d(s8 a)
1943 double d = (double) a;
1946 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
1949 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1950 s4 builtin_f2i(float a)
1954 i = builtin_d2i((double) a);
1965 if (a < (-2147483648))
1966 return (-2147483648);
1969 f = copysignf((float) 1.0, a);
1972 return (-2147483648); */
1974 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
1977 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
1978 s8 builtin_f2l(float a)
1982 l = builtin_d2l((double) a);
1989 if (a > 9223372036854775807L)
1990 return 9223372036854775807L;
1991 if (a < (-9223372036854775808L))
1992 return (-9223372036854775808L);
1997 f = copysignf((float) 1.0, a);
1999 return 9223372036854775807L;
2000 return (-9223372036854775808L); */
2002 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2005 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2006 s4 builtin_d2i(double a)
2011 if (a >= 2147483647)
2013 if (a <= (-2147483647-1))
2014 return (-2147483647-1);
2019 d = copysign(1.0, a);
2022 return (-2147483647-1);
2024 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2027 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2028 s8 builtin_d2l(double a)
2033 if (a >= 9223372036854775807LL)
2034 return 9223372036854775807LL;
2035 if (a <= (-9223372036854775807LL-1))
2036 return (-9223372036854775807LL-1);
2041 d = copysign(1.0, a);
2043 return 9223372036854775807LL;
2044 return (-9223372036854775807LL-1);
2046 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2049 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2050 double builtin_f2d(float a)
2052 if (finitef(a)) return (double) a;
2055 return longBitsToDouble(DBL_NAN);
2057 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2061 float builtin_d2f(double a)
2067 return intBitsToFloat(FLT_NAN);
2069 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2072 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2075 /*============================================================================*/
2076 /* AUTOMATICALLY REPLACED FUNCTIONS */
2077 /*============================================================================*/
2079 /* builtin_arraycopy ***********************************************************
2081 Builtin for java.lang.System.arraycopy.
2083 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2085 *******************************************************************************/
2087 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2088 java_handle_t *dest, s4 destStart, s4 len)
2090 arraydescriptor *sdesc;
2091 arraydescriptor *ddesc;
2094 if ((src == NULL) || (dest == NULL)) {
2095 exceptions_throw_nullpointerexception();
2099 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2100 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2102 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2103 exceptions_throw_arraystoreexception();
2107 // Check if offsets and length are positive.
2108 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2109 exceptions_throw_arrayindexoutofboundsexception();
2113 // Check if ranges are valid.
2114 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2115 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2116 exceptions_throw_arrayindexoutofboundsexception();
2125 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2126 /* We copy primitive values or references of exactly the same type */
2128 s4 dataoffset = sdesc->dataoffset;
2129 s4 componentsize = sdesc->componentsize;
2131 LLNI_CRITICAL_START;
2133 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2134 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2135 u1, (size_t) len * componentsize);
2140 /* We copy references of different type */
2142 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2143 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2145 if (destStart <= srcStart) {
2146 for (i = 0; i < len; i++) {
2149 o = array_objectarray_element_get(oas, srcStart + i);
2151 if (!builtin_canstore(oad, o))
2154 array_objectarray_element_set(oad, destStart + i, o);
2158 /* XXX this does not completely obey the specification!
2159 If an exception is thrown only the elements above the
2160 current index have been copied. The specification
2161 requires that only the elements *below* the current
2162 index have been copied before the throw. */
2164 for (i = len - 1; i >= 0; i--) {
2167 o = array_objectarray_element_get(oas, srcStart + i);
2169 if (!builtin_canstore(oad, o))
2172 array_objectarray_element_set(oad, destStart + i, o);
2179 /* builtin_nanotime ************************************************************
2181 Return the current time in nanoseconds.
2183 *******************************************************************************/
2185 s8 builtin_nanotime(void)
2190 if (gettimeofday(&tv, NULL) == -1)
2191 vm_abort("gettimeofday failed: %s", strerror(errno));
2193 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2195 return usecs * 1000;
2199 /* builtin_currenttimemillis ***************************************************
2201 Return the current time in milliseconds.
2203 *******************************************************************************/
2205 s8 builtin_currenttimemillis(void)
2209 msecs = builtin_nanotime() / 1000 / 1000;
2215 /* builtin_clone ***************************************************************
2217 Function for cloning objects or arrays.
2219 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2221 *******************************************************************************/
2223 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2225 arraydescriptor *ad;
2228 java_handle_t *co; /* cloned object header */
2230 /* get the array descriptor */
2232 ad = LLNI_vftbl_direct(o)->arraydesc;
2234 /* we are cloning an array */
2237 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2239 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2244 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2245 /* XXX this is only a dirty hack to make Boehm work with handles */
2247 co = LLNI_WRAP((java_object_t *) co);
2250 LLNI_CRITICAL_START;
2252 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2254 #if defined(ENABLE_GC_CACAO)
2255 heap_init_objectheader(LLNI_DIRECT(co), size);
2258 #if defined(ENABLE_THREADS)
2259 LLNI_DIRECT(co)->lockword.init();
2267 /* we are cloning a non-array */
2269 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2270 exceptions_throw_clonenotsupportedexception();
2274 /* get the class of the object */
2276 LLNI_class_get(o, c);
2278 /* create new object */
2280 co = builtin_new(c);
2285 LLNI_CRITICAL_START;
2287 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2289 #if defined(ENABLE_GC_CACAO)
2290 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2293 #if defined(ENABLE_THREADS)
2294 LLNI_DIRECT(co)->lockword.init();
2303 #if defined(ENABLE_CYCLES_STATS)
2304 void builtin_print_cycles_stats(FILE *file)
2306 fprintf(file,"builtin cylce count statistics:\n");
2308 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2309 CYCLES_STATS_PRINT(builtin_new ,file);
2313 #endif /* defined(ENABLE_CYCLES_STATS) */
2316 #if defined(ENABLE_VMLOG)
2318 #include <vmlog_cacao.c>
2323 * These are local overrides for various environment variables in Emacs.
2324 * Please do not remove this and leave it at the end of the file, where
2325 * Emacs will automagically detect them.
2326 * ---------------------------------------------------------------------
2329 * indent-tabs-mode: t
2333 * vim:noexpandtab:sw=4:ts=4: