1 /* src/vm/jit/builtin.cpp - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Contains C functions for JavaVM Instructions that cannot be
24 translated to machine language directly. Consequently, the
25 generated machine code for these instructions contains function
26 calls instead of machine instructions, using the C calling
45 #include "fdlibm/fdlibm.h"
46 #if defined(__CYGWIN__) && defined(Bias)
51 #include "mm/memory.hpp"
53 #include "native/llni.h"
55 #include "threads/lock.hpp"
56 #include "threads/mutex.hpp"
57 #include "threads/thread.hpp"
59 #include "toolbox/logging.hpp"
60 #include "toolbox/util.h"
62 #include "vm/array.hpp"
63 #include "vm/jit/builtin.hpp"
64 #include "vm/class.hpp"
65 #include "vm/cycles-stats.h"
66 #include "vm/exceptions.hpp"
67 #include "vm/global.h"
68 #include "vm/globals.hpp"
69 #include "vm/initialize.hpp"
70 #include "vm/linker.hpp"
71 #include "vm/loader.hpp"
72 #include "vm/options.h"
73 #include "vm/primitive.hpp"
74 #include "vm/rt-timing.h"
75 #include "vm/string.hpp"
77 #include "vm/jit/asmpart.h"
78 #include "vm/jit/stubs.hpp"
79 #include "vm/jit/trace.hpp"
81 #if defined(ENABLE_VMLOG)
82 #include <vmlog_cacao.h>
86 /* include builtin tables *****************************************************/
88 #include "vm/jit/builtintable.inc"
91 CYCLES_STATS_DECLARE(builtin_new ,100,5)
92 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
95 /*============================================================================*/
96 /* BUILTIN TABLE MANAGEMENT FUNCTIONS */
97 /*============================================================================*/
99 /* builtintable_init ***********************************************************
101 Parse the descriptors of builtin functions and create the parsed
104 *******************************************************************************/
106 static bool builtintable_init(void)
108 descriptor_pool *descpool;
109 builtintable_entry *bte;
112 // Create new dump memory area.
115 /* create a new descriptor pool */
117 descpool = descriptor_pool_new(class_java_lang_Object);
119 /* add some entries we need */
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
124 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
127 /* first add all descriptors to the pool */
129 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
130 bte->name = utf_new_char(bte->cname);
131 bte->descriptor = utf_new_char(bte->cdescriptor);
133 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
137 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
138 bte->descriptor = utf_new_char(bte->cdescriptor);
140 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
144 for (bte = builtintable_function; bte->fp != NULL; bte++) {
145 bte->classname = utf_new_char(bte->cclassname);
146 bte->name = utf_new_char(bte->cname);
147 bte->descriptor = utf_new_char(bte->cdescriptor);
149 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
153 /* create the class reference table */
155 (void) descriptor_pool_create_classrefs(descpool, NULL);
157 /* allocate space for the parsed descriptors */
159 descriptor_pool_alloc_parsed_descriptors(descpool);
161 /* Now parse all descriptors. NOTE: builtin-functions are treated
162 like static methods (no `this' pointer). */
164 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
166 descriptor_pool_parse_method_descriptor(descpool,
168 ACC_STATIC | ACC_METHOD_BUILTIN,
171 /* generate a builtin stub if we need one */
173 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
174 m = method_new_builtin(bte);
175 BuiltinStub::generate(m, bte);
179 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
181 descriptor_pool_parse_method_descriptor(descpool,
183 ACC_STATIC | ACC_METHOD_BUILTIN,
186 /* no stubs should be needed for this table */
188 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
191 for (bte = builtintable_function; bte->fp != NULL; bte++) {
193 descriptor_pool_parse_method_descriptor(descpool,
195 ACC_STATIC | ACC_METHOD_BUILTIN,
198 /* generate a builtin stub if we need one */
200 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
201 m = method_new_builtin(bte);
202 BuiltinStub::generate(m, bte);
210 /* builtintable_comparator *****************************************************
212 qsort comparator for the automatic builtin table.
214 *******************************************************************************/
216 static int builtintable_comparator(const void *a, const void *b)
218 builtintable_entry *bte1;
219 builtintable_entry *bte2;
221 bte1 = (builtintable_entry *) a;
222 bte2 = (builtintable_entry *) b;
224 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
228 /* builtintable_sort_automatic *************************************************
230 Sorts the automatic builtin table.
232 *******************************************************************************/
234 static void builtintable_sort_automatic(void)
238 /* calculate table size statically (`- 1' comment see builtintable.inc) */
240 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
242 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
243 builtintable_comparator);
247 /* builtin_init ****************************************************************
249 Initialize the global table of builtin functions.
251 *******************************************************************************/
253 bool builtin_init(void)
255 TRACESUBSYSTEMINITIALIZATION("builtin_init");
257 /* initialize the builtin tables */
259 if (!builtintable_init())
262 /* sort builtin tables */
264 builtintable_sort_automatic();
270 /* builtintable_get_internal ***************************************************
272 Finds an entry in the builtintable for internal functions and
273 returns the a pointer to the structure.
275 *******************************************************************************/
277 builtintable_entry *builtintable_get_internal(functionptr fp)
279 builtintable_entry *bte;
281 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
290 /* builtintable_get_automatic **************************************************
292 Finds an entry in the builtintable for functions which are replaced
293 automatically and returns the a pointer to the structure.
295 *******************************************************************************/
297 builtintable_entry *builtintable_get_automatic(s4 opcode)
299 builtintable_entry *first;
300 builtintable_entry *last;
301 builtintable_entry *middle;
305 /* calculate table size statically (`- 1' comment see builtintable.inc) */
307 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
309 first = builtintable_automatic;
310 last = builtintable_automatic + entries;
312 while (entries > 0) {
314 middle = first + half;
316 if (middle->opcode < opcode) {
324 return (first != last ? first : NULL);
328 /* builtintable_replace_function ***********************************************
332 *******************************************************************************/
334 #if defined(ENABLE_JIT)
335 bool builtintable_replace_function(void *iptr_)
338 builtintable_entry *bte;
341 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
343 /* get name and descriptor of the function */
346 case ICMD_INVOKESTATIC:
347 /* The instruction MUST be resolved, otherwise we run into
348 lazy loading troubles. Anyway, we should/can only replace
349 very VM-close functions. */
351 if (INSTRUCTION_IS_UNRESOLVED(iptr))
354 mr = iptr->sx.s23.s3.fmiref;
361 /* search the function table */
363 for (bte = builtintable_function; bte->fp != NULL; bte++) {
364 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
365 (mr->name == bte->name) &&
366 (mr->descriptor == bte->descriptor)) {
368 /* set the values in the instruction */
370 iptr->opc = bte->opcode;
371 iptr->sx.s23.s3.bte = bte;
373 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
374 iptr->flags.bits |= INS_FLAG_CHECK;
376 iptr->flags.bits &= ~INS_FLAG_CHECK;
384 #endif /* defined(ENABLE_JIT) */
387 /*============================================================================*/
388 /* INTERNAL BUILTIN FUNCTIONS */
389 /*============================================================================*/
391 /* builtin_instanceof **********************************************************
393 Checks if an object is an instance of some given class (or subclass
394 of that class). If class is an interface, checks if the interface
398 1......o is an instance of class or implements the interface
399 0......otherwise or if o == NULL
401 NOTE: This builtin can be called from NATIVE code only.
403 *******************************************************************************/
405 bool builtin_instanceof(java_handle_t *o, classinfo *c)
412 LLNI_class_get(o, oc);
414 return class_isanysubclass(oc, c);
419 /* builtin_checkcast ***********************************************************
421 The same as builtin_instanceof but with the exception
422 that 1 is returned when (o == NULL).
424 NOTE: This builtin can be called from NATIVE code only.
426 *******************************************************************************/
428 bool builtin_checkcast(java_handle_t *o, classinfo *c)
435 LLNI_class_get(o, oc);
437 if (class_isanysubclass(oc, c))
444 /* builtin_arraycheckcast ******************************************************
446 Checks if an object is really a subtype of the requested array
447 type. The object has to be an array to begin with. For simple
448 arrays (int, short, double, etc.) the types have to match exactly.
449 For arrays of objects, the type of elements in the array has to be
450 a subtype (or the same type) of the requested element type. For
451 arrays of arrays (which in turn can again be arrays of arrays), the
452 types at the lowest level have to satisfy the corresponding sub
455 NOTE: This is a FAST builtin and can be called from JIT code only.
457 *******************************************************************************/
459 bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
461 arraydescriptor *desc;
466 desc = o->vftbl->arraydesc;
471 return class_is_arraycompatible(desc, targetclass->vftbl->arraydesc);
475 /* builtin_fast_arrayinstanceof ************************************************
477 NOTE: This is a FAST builtin and can be called from JIT code only.
479 *******************************************************************************/
481 bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
486 return builtin_fast_arraycheckcast(o, targetclass);
490 /* builtin_arrayinstanceof *****************************************************
492 NOTE: This builtin can be called from NATIVE code only.
494 *******************************************************************************/
496 bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
502 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
510 /* builtin_throw_exception *****************************************************
512 Sets the exception pointer with the thrown exception and prints some
513 debugging information.
515 NOTE: This is a FAST builtin and can be called from JIT code,
516 or from asm_vm_call_method.
518 *******************************************************************************/
520 void *builtin_throw_exception(java_object_t *xptr)
523 /* print exception trace */
525 if (opt_TraceExceptions)
526 trace_exception_builtin(xptr);
527 #endif /* !defined(NDEBUG) */
529 /* actually set the exception */
531 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
533 /* Return a NULL pointer. This is required for vm_call_method to
534 check for an exception. This is for convenience. */
540 /* builtin_retrieve_exception **************************************************
542 Gets and clears the exception pointer of the current thread.
545 the exception object, or NULL if no exception was thrown.
547 NOTE: This is a FAST builtin and can be called from JIT code,
548 or from the signal handlers.
550 *******************************************************************************/
552 java_object_t *builtin_retrieve_exception(void)
557 /* actually get and clear the exception */
559 h = exceptions_get_and_clear_exception();
566 /* builtin_canstore ************************************************************
568 Checks, if an object can be stored in an array.
572 0......otherwise (throws an ArrayStoreException)
574 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
576 *******************************************************************************/
578 bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
584 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
588 /* if not possible, throw an exception */
591 exceptions_throw_arraystoreexception();
597 /* fast_subtype_check **********************************************************
599 Checks if s is a subtype of t, using both the restricted subtype relation
600 and the overflow array (see Cliff Click and John Rose: Fast subtype checking
604 1......s is a subtype of t.
607 *******************************************************************************/
609 bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
611 if (s->subtype_display[t->subtype_depth] == t)
613 if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
615 return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
619 /* builtin_fast_canstore *******************************************************
621 Checks, if an object can be stored in an array.
625 0......otherwise (no exception thrown!)
627 NOTE: This is a FAST builtin and can be called from JIT code only.
629 *******************************************************************************/
631 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
633 arraydescriptor *desc;
634 arraydescriptor *valuedesc;
635 vftbl_t *componentvftbl;
643 /* The following is guaranteed (by verifier checks):
645 * *) oa->...vftbl->arraydesc != NULL
646 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
647 * *) o->vftbl is not an interface vftbl
650 desc = oa->header.objheader.vftbl->arraydesc;
651 componentvftbl = desc->componentvftbl;
652 valuevftbl = o->vftbl;
653 valuedesc = valuevftbl->arraydesc;
655 if ((desc->dimension - 1) == 0) {
656 /* {oa is a one-dimensional array} */
657 /* {oa is an array of references} */
659 if (valuevftbl == componentvftbl)
662 LOCK_CLASSRENUMBER_LOCK;
664 baseval = componentvftbl->baseval;
667 /* an array of interface references */
669 result = ((valuevftbl->interfacetablelength > -baseval) &&
670 (valuevftbl->interfacetable[baseval] != NULL));
674 result = fast_subtype_check(valuevftbl, componentvftbl);
676 uint32_t diffval = valuevftbl->baseval - componentvftbl->baseval;
677 result = diffval <= (uint32_t) componentvftbl->diffval;
681 UNLOCK_CLASSRENUMBER_LOCK;
683 else if (valuedesc == NULL) {
684 /* {oa has dimension > 1} */
685 /* {componentvftbl->arraydesc != NULL} */
687 /* check if o is an array */
692 /* {o is an array} */
694 result = class_is_arraycompatible(valuedesc, componentvftbl->arraydesc);
703 /* This is an optimized version where a is guaranteed to be one-dimensional */
704 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
706 arraydescriptor *desc;
707 vftbl_t *elementvftbl;
715 /* The following is guaranteed (by verifier checks):
717 * *) a->...vftbl->arraydesc != NULL
718 * *) a->...vftbl->arraydesc->elementvftbl != NULL
719 * *) a->...vftbl->arraydesc->dimension == 1
720 * *) o->vftbl is not an interface vftbl
723 desc = a->header.objheader.vftbl->arraydesc;
724 elementvftbl = desc->elementvftbl;
725 valuevftbl = o->vftbl;
727 /* {a is a one-dimensional array} */
729 if (valuevftbl == elementvftbl)
732 LOCK_CLASSRENUMBER_LOCK;
734 baseval = elementvftbl->baseval;
737 /* an array of interface references */
738 result = ((valuevftbl->interfacetablelength > -baseval) &&
739 (valuevftbl->interfacetable[baseval] != NULL));
743 result = fast_subtype_check(valuevftbl, elementvftbl);
745 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
746 result = diffval <= (uint32_t) elementvftbl->diffval;
750 UNLOCK_CLASSRENUMBER_LOCK;
756 /* This is an optimized version where a is guaranteed to be a
757 * one-dimensional array of a class type */
758 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
760 vftbl_t *elementvftbl;
767 /* The following is guaranteed (by verifier checks):
769 * *) a->...vftbl->arraydesc != NULL
770 * *) a->...vftbl->arraydesc->elementvftbl != NULL
771 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
772 * *) a->...vftbl->arraydesc->dimension == 1
773 * *) o->vftbl is not an interface vftbl
776 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
777 valuevftbl = o->vftbl;
779 /* {a is a one-dimensional array} */
781 if (valuevftbl == elementvftbl)
784 LOCK_CLASSRENUMBER_LOCK;
787 result = fast_subtype_check(valuevftbl, elementvftbl);
789 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
790 result = diffval <= (uint32_t) elementvftbl->diffval;
793 UNLOCK_CLASSRENUMBER_LOCK;
799 /* builtin_new *****************************************************************
801 Creates a new instance of class c on the heap.
804 pointer to the object, or NULL if no memory is available
806 NOTE: This builtin can be called from NATIVE code only.
808 *******************************************************************************/
810 java_handle_t *builtin_new(classinfo *c)
813 #if defined(ENABLE_RT_TIMING)
814 struct timespec time_start, time_end;
816 #if defined(ENABLE_CYCLES_STATS)
817 u8 cycles_start, cycles_end;
820 RT_TIMING_GET_TIME(time_start);
821 CYCLES_STATS_GET(cycles_start);
823 /* is the class loaded */
825 assert(c->state & CLASS_LOADED);
827 /* check if we can instantiate this class */
829 if (c->flags & ACC_ABSTRACT) {
830 exceptions_throw_instantiationerror(c);
834 /* is the class linked */
836 if (!(c->state & CLASS_LINKED))
840 if (!(c->state & CLASS_INITIALIZED)) {
843 log_message_class("Initialize class (from builtin_new): ", c);
846 if (!initialize_class(c))
850 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
856 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
857 /* XXX this is only a dirty hack to make Boehm work with handles */
859 o = LLNI_WRAP((java_object_t *) o);
862 LLNI_vftbl_direct(o) = c->vftbl;
864 #if defined(ENABLE_THREADS)
865 LLNI_DIRECT(o)->lockword.init();
868 CYCLES_STATS_GET(cycles_end);
869 RT_TIMING_GET_TIME(time_end);
871 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
872 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
877 #if defined(ENABLE_ESCAPE_REASON)
878 java_handle_t *builtin_escape_reason_new(classinfo *c) {
879 print_escape_reasons();
880 return builtin_java_new(c);
884 #if defined(ENABLE_TLH)
885 java_handle_t *builtin_tlh_new(classinfo *c)
888 # if defined(ENABLE_RT_TIMING)
889 struct timespec time_start, time_end;
891 # if defined(ENABLE_CYCLES_STATS)
892 u8 cycles_start, cycles_end;
895 RT_TIMING_GET_TIME(time_start);
896 CYCLES_STATS_GET(cycles_start);
898 /* is the class loaded */
900 assert(c->state & CLASS_LOADED);
902 /* check if we can instantiate this class */
904 if (c->flags & ACC_ABSTRACT) {
905 exceptions_throw_instantiationerror(c);
909 /* is the class linked */
911 if (!(c->state & CLASS_LINKED))
915 if (!(c->state & CLASS_INITIALIZED)) {
916 # if !defined(NDEBUG)
918 log_message_class("Initialize class (from builtin_new): ", c);
921 if (!initialize_class(c))
926 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
931 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
938 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
939 /* XXX this is only a dirty hack to make Boehm work with handles */
941 o = LLNI_WRAP((java_object_t *) o);
944 LLNI_vftbl_direct(o) = c->vftbl;
946 # if defined(ENABLE_THREADS)
947 LLNI_DIRECT(o)->lockword.init();
950 CYCLES_STATS_GET(cycles_end);
951 RT_TIMING_GET_TIME(time_end);
954 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
955 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
963 /* builtin_java_new ************************************************************
965 NOTE: This is a SLOW builtin and can be called from JIT code only.
967 *******************************************************************************/
969 java_handle_t *builtin_java_new(java_handle_t *clazz)
971 return builtin_new(LLNI_classinfo_unwrap(clazz));
975 /* builtin_fast_new ************************************************************
977 Creates a new instance of class c on the heap.
980 pointer to the object, or NULL if no fast return
981 is possible for any reason.
983 NOTE: This is a FAST builtin and can be called from JIT code only.
985 *******************************************************************************/
987 java_object_t *builtin_fast_new(classinfo *c)
990 #if defined(ENABLE_RT_TIMING)
991 struct timespec time_start, time_end;
993 #if defined(ENABLE_CYCLES_STATS)
994 u8 cycles_start, cycles_end;
997 RT_TIMING_GET_TIME(time_start);
998 CYCLES_STATS_GET(cycles_start);
1000 /* is the class loaded */
1002 assert(c->state & CLASS_LOADED);
1004 /* check if we can instantiate this class */
1006 if (c->flags & ACC_ABSTRACT)
1009 /* is the class linked */
1011 if (!(c->state & CLASS_LINKED))
1014 if (!(c->state & CLASS_INITIALIZED))
1017 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1018 c->finalizer, false);
1023 o->vftbl = c->vftbl;
1025 #if defined(ENABLE_THREADS)
1026 LLNI_DIRECT(o)->lockword.init();
1029 CYCLES_STATS_GET(cycles_end);
1030 RT_TIMING_GET_TIME(time_end);
1032 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1033 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1039 /* builtin_newarray ************************************************************
1041 Creates an array with the given vftbl on the heap. This function
1042 takes as class argument an array class.
1045 pointer to the array or NULL if no memory is available
1047 NOTE: This builtin can be called from NATIVE code only.
1049 *******************************************************************************/
1051 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1053 arraydescriptor *desc;
1058 #if defined(ENABLE_RT_TIMING)
1059 struct timespec time_start, time_end;
1062 RT_TIMING_GET_TIME(time_start);
1064 desc = arrayclass->vftbl->arraydesc;
1065 dataoffset = desc->dataoffset;
1066 componentsize = desc->componentsize;
1069 exceptions_throw_negativearraysizeexception();
1073 actualsize = dataoffset + size * componentsize;
1075 /* check for overflow */
1077 if (((u4) actualsize) < ((u4) size)) {
1078 exceptions_throw_outofmemoryerror();
1082 a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1087 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1088 /* XXX this is only a dirty hack to make Boehm work with handles */
1090 a = LLNI_WRAP((java_object_t *) a);
1093 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1095 #if defined(ENABLE_THREADS)
1096 LLNI_DIRECT(a)->lockword.init();
1099 LLNI_array_size(a) = size;
1101 RT_TIMING_GET_TIME(time_end);
1102 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1108 /* builtin_java_newarray *******************************************************
1110 NOTE: This is a SLOW builtin and can be called from JIT code only.
1112 *******************************************************************************/
1114 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1116 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1120 /* builtin_anewarray ***********************************************************
1122 Creates an array of references to the given class type on the heap.
1125 pointer to the array or NULL if no memory is
1128 NOTE: This builtin can be called from NATIVE code only.
1130 *******************************************************************************/
1132 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1134 classinfo *arrayclass;
1136 /* is class loaded */
1138 assert(componentclass->state & CLASS_LOADED);
1140 /* is class linked */
1142 if (!(componentclass->state & CLASS_LINKED))
1143 if (!link_class(componentclass))
1146 arrayclass = class_array_of(componentclass, true);
1151 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1155 /* builtin_newarray_type ****************************************************
1157 Creates an array of [type]s on the heap.
1160 pointer to the array or NULL if no memory is available
1162 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1164 *******************************************************************************/
1166 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1167 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1169 return (java_handle_##type##array_t *) \
1170 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1173 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1174 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1175 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1176 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1177 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1178 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1179 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1180 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1183 /* builtin_multianewarray_intern ***********************************************
1185 Creates a multi-dimensional array on the heap. The dimensions are
1186 passed in an array of longs.
1189 n.............number of dimensions to create
1190 arrayclass....the array class
1191 dims..........array containing the size of each dimension to create
1194 pointer to the array or NULL if no memory is available
1196 ******************************************************************************/
1198 static java_handle_t *builtin_multianewarray_intern(int n,
1199 classinfo *arrayclass,
1204 classinfo *componentclass;
1207 /* create this dimension */
1209 size = (s4) dims[0];
1210 a = builtin_newarray(size, arrayclass);
1215 /* if this is the last dimension return */
1220 /* get the class of the components to create */
1222 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1224 /* The verifier guarantees that the dimension count is in the range. */
1226 /* create the component arrays */
1228 for (i = 0; i < size; i++) {
1230 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1231 /* we save an s4 to a s8 slot, 8-byte aligned */
1233 builtin_multianewarray_intern(n, componentclass, dims + 2);
1235 builtin_multianewarray_intern(n, componentclass, dims + 1);
1241 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1248 /* builtin_multianewarray ******************************************************
1250 Wrapper for builtin_multianewarray_intern which checks all
1251 dimensions before we start allocating.
1253 NOTE: This is a SLOW builtin and can be called from JIT code only.
1255 ******************************************************************************/
1257 java_handle_objectarray_t *builtin_multianewarray(int n,
1258 java_handle_t *arrayclazz,
1265 /* check all dimensions before doing anything */
1267 for (i = 0; i < n; i++) {
1268 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1269 /* we save an s4 to a s8 slot, 8-byte aligned */
1270 size = (s4) dims[i * 2];
1272 size = (s4) dims[i];
1276 exceptions_throw_negativearraysizeexception();
1281 c = LLNI_classinfo_unwrap(arrayclazz);
1283 /* now call the real function */
1285 return (java_handle_objectarray_t *)
1286 builtin_multianewarray_intern(n, c, dims);
1290 /* builtin_verbosecall_enter ***************************************************
1292 Print method call with arguments for -verbose:call.
1294 XXX: Remove mew once all archs use the new tracer!
1296 *******************************************************************************/
1298 #if !defined(NDEBUG)
1299 #ifdef TRACE_ARGS_NUM
1300 void builtin_verbosecall_enter(s8 a0, s8 a1,
1301 # if TRACE_ARGS_NUM >= 4
1304 # if TRACE_ARGS_NUM >= 6
1307 # if TRACE_ARGS_NUM == 8
1312 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1315 #endif /* !defined(NDEBUG) */
1318 /* builtin_verbosecall_exit ****************************************************
1320 Print method exit for -verbose:call.
1322 XXX: Remove mew once all archs use the new tracer!
1324 *******************************************************************************/
1326 #if !defined(NDEBUG)
1327 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1329 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1331 #endif /* !defined(NDEBUG) */
1334 /*============================================================================*/
1335 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1336 /*============================================================================*/
1338 /*********** Functions for integer divisions *****************************
1340 On some systems (eg. DEC ALPHA), integer division is not supported by the
1341 CPU. These helper functions implement the missing functionality.
1343 ******************************************************************************/
1345 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1346 s4 builtin_idiv(s4 a, s4 b)
1355 s4 builtin_irem(s4 a, s4 b)
1363 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1366 /* functions for long arithmetics **********************************************
1368 On systems where 64 bit Integers are not supported by the CPU,
1369 these functions are needed.
1371 ******************************************************************************/
1373 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1374 s8 builtin_ladd(s8 a, s8 b)
1383 s8 builtin_lsub(s8 a, s8 b)
1392 s8 builtin_lneg(s8 a)
1400 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1403 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1404 s8 builtin_lmul(s8 a, s8 b)
1412 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1415 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1416 s8 builtin_ldiv(s8 a, s8 b)
1425 s8 builtin_lrem(s8 a, s8 b)
1433 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1436 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1437 s8 builtin_lshl(s8 a, s4 b)
1446 s8 builtin_lshr(s8 a, s4 b)
1455 s8 builtin_lushr(s8 a, s4 b)
1459 c = ((u8) a) >> (b & 63);
1463 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1466 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1467 s8 builtin_land(s8 a, s8 b)
1476 s8 builtin_lor(s8 a, s8 b)
1485 s8 builtin_lxor(s8 a, s8 b)
1493 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1496 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1497 s4 builtin_lcmp(s8 a, s8 b)
1507 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1510 /* functions for unsupported floating instructions ****************************/
1512 /* used to convert FLT_xxx defines into float values */
1514 static inline float intBitsToFloat(s4 i)
1523 /* used to convert DBL_xxx defines into double values */
1525 static inline float longBitsToDouble(s8 l)
1535 float builtin_fadd(float a, float b)
1537 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1538 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1549 if (copysignf(1.0, a) == copysignf(1.0, b))
1552 return intBitsToFloat(FLT_NAN);
1558 float builtin_fsub(float a, float b)
1560 return builtin_fadd(a, builtin_fneg(b));
1564 float builtin_fmul(float a, float b)
1566 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1567 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1569 if (finitef(b)) return a * b;
1571 if (a == 0) return intBitsToFloat(FLT_NAN);
1572 else return copysignf(b, copysignf(1.0, b)*a);
1577 if (b == 0) return intBitsToFloat(FLT_NAN);
1578 else return copysignf(a, copysignf(1.0, a)*b);
1581 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1587 /* builtin_ddiv ****************************************************************
1589 Implementation as described in VM Spec.
1591 *******************************************************************************/
1593 float builtin_fdiv(float a, float b)
1597 /* If neither value1' nor value2' is NaN, the sign of the result */
1598 /* is positive if both values have the same sign, negative if the */
1599 /* values have different signs. */
1605 /* If either value1' or value2' is NaN, the result is NaN. */
1607 return intBitsToFloat(FLT_NAN);
1610 /* Division of a finite value by an infinity results in a */
1611 /* signed zero, with the sign-producing rule just given. */
1613 /* is sign equal? */
1615 if (copysignf(1.0, a) == copysignf(1.0, b))
1624 /* If either value1' or value2' is NaN, the result is NaN. */
1626 return intBitsToFloat(FLT_NAN);
1628 } else if (finitef(b)) {
1629 /* Division of an infinity by a finite value results in a signed */
1630 /* infinity, with the sign-producing rule just given. */
1632 /* is sign equal? */
1634 if (copysignf(1.0, a) == copysignf(1.0, b))
1635 return intBitsToFloat(FLT_POSINF);
1637 return intBitsToFloat(FLT_NEGINF);
1640 /* Division of an infinity by an infinity results in NaN. */
1642 return intBitsToFloat(FLT_NAN);
1648 float builtin_fneg(float a)
1650 if (isnanf(a)) return a;
1652 if (finitef(a)) return -a;
1653 else return copysignf(a, -copysignf(1.0, a));
1656 #endif /* !SUPPORT_FLOAT */
1659 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1660 s4 builtin_fcmpl(float a, float b)
1668 if (!finitef(a) || !finitef(b)) {
1669 a = finitef(a) ? 0 : copysignf(1.0, a);
1670 b = finitef(b) ? 0 : copysignf(1.0, b);
1683 s4 builtin_fcmpg(float a, float b)
1685 if (isnanf(a)) return 1;
1686 if (isnanf(b)) return 1;
1687 if (!finitef(a) || !finitef(b)) {
1688 a = finitef(a) ? 0 : copysignf(1.0, a);
1689 b = finitef(b) ? 0 : copysignf(1.0, b);
1691 if (a > b) return 1;
1692 if (a == b) return 0;
1695 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1698 float builtin_frem(float a, float b)
1704 /* functions for unsupported double instructions ******************************/
1707 double builtin_dadd(double a, double b)
1709 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1710 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1712 if (finite(b)) return a + b;
1716 if (finite(b)) return a;
1718 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1719 else return longBitsToDouble(DBL_NAN);
1725 double builtin_dsub(double a, double b)
1727 return builtin_dadd(a, builtin_dneg(b));
1731 double builtin_dmul(double a, double b)
1733 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1734 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1736 if (finite(b)) return a * b;
1738 if (a == 0) return longBitsToDouble(DBL_NAN);
1739 else return copysign(b, copysign(1.0, b) * a);
1744 if (b == 0) return longBitsToDouble(DBL_NAN);
1745 else return copysign(a, copysign(1.0, a) * b);
1748 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1754 /* builtin_ddiv ****************************************************************
1756 Implementation as described in VM Spec.
1758 *******************************************************************************/
1760 double builtin_ddiv(double a, double b)
1764 /* If neither value1' nor value2' is NaN, the sign of the result */
1765 /* is positive if both values have the same sign, negative if the */
1766 /* values have different signs. */
1772 /* If either value1' or value2' is NaN, the result is NaN. */
1774 return longBitsToDouble(DBL_NAN);
1777 /* Division of a finite value by an infinity results in a */
1778 /* signed zero, with the sign-producing rule just given. */
1780 /* is sign equal? */
1782 if (copysign(1.0, a) == copysign(1.0, b))
1791 /* If either value1' or value2' is NaN, the result is NaN. */
1793 return longBitsToDouble(DBL_NAN);
1795 } else if (finite(b)) {
1796 /* Division of an infinity by a finite value results in a signed */
1797 /* infinity, with the sign-producing rule just given. */
1799 /* is sign equal? */
1801 if (copysign(1.0, a) == copysign(1.0, b))
1802 return longBitsToDouble(DBL_POSINF);
1804 return longBitsToDouble(DBL_NEGINF);
1807 /* Division of an infinity by an infinity results in NaN. */
1809 return longBitsToDouble(DBL_NAN);
1815 /* builtin_dneg ****************************************************************
1817 Implemented as described in VM Spec.
1819 *******************************************************************************/
1821 double builtin_dneg(double a)
1824 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1831 /* If the operand is a zero, the result is the zero of opposite */
1837 /* If the operand is an infinity, the result is the infinity of */
1838 /* opposite sign. */
1840 return copysign(a, -copysign(1.0, a));
1844 #endif /* !SUPPORT_DOUBLE */
1847 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1848 s4 builtin_dcmpl(double a, double b)
1856 if (!finite(a) || !finite(b)) {
1857 a = finite(a) ? 0 : copysign(1.0, a);
1858 b = finite(b) ? 0 : copysign(1.0, b);
1871 s4 builtin_dcmpg(double a, double b)
1879 if (!finite(a) || !finite(b)) {
1880 a = finite(a) ? 0 : copysign(1.0, a);
1881 b = finite(b) ? 0 : copysign(1.0, b);
1892 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1895 double builtin_drem(double a, double b)
1901 /* conversion operations ******************************************************/
1903 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1904 float builtin_i2f(s4 a)
1906 float f = (float) a;
1909 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
1912 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
1913 double builtin_i2d(s4 a)
1915 double d = (double) a;
1918 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
1921 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
1922 float builtin_l2f(s8 a)
1924 float f = (float) a;
1927 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
1930 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
1931 double builtin_l2d(s8 a)
1933 double d = (double) a;
1936 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
1939 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1940 s4 builtin_f2i(float a)
1944 i = builtin_d2i((double) a);
1955 if (a < (-2147483648))
1956 return (-2147483648);
1959 f = copysignf((float) 1.0, a);
1962 return (-2147483648); */
1964 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
1967 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
1968 s8 builtin_f2l(float a)
1972 l = builtin_d2l((double) a);
1979 if (a > 9223372036854775807L)
1980 return 9223372036854775807L;
1981 if (a < (-9223372036854775808L))
1982 return (-9223372036854775808L);
1987 f = copysignf((float) 1.0, a);
1989 return 9223372036854775807L;
1990 return (-9223372036854775808L); */
1992 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
1995 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1996 s4 builtin_d2i(double a)
2001 if (a >= 2147483647)
2003 if (a <= (-2147483647-1))
2004 return (-2147483647-1);
2009 d = copysign(1.0, a);
2012 return (-2147483647-1);
2014 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2017 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2018 s8 builtin_d2l(double a)
2023 if (a >= 9223372036854775807LL)
2024 return 9223372036854775807LL;
2025 if (a <= (-9223372036854775807LL-1))
2026 return (-9223372036854775807LL-1);
2031 d = copysign(1.0, a);
2033 return 9223372036854775807LL;
2034 return (-9223372036854775807LL-1);
2036 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2039 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2040 double builtin_f2d(float a)
2042 if (finitef(a)) return (double) a;
2045 return longBitsToDouble(DBL_NAN);
2047 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2051 float builtin_d2f(double a)
2057 return intBitsToFloat(FLT_NAN);
2059 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2062 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2065 /*============================================================================*/
2066 /* AUTOMATICALLY REPLACED FUNCTIONS */
2067 /*============================================================================*/
2069 /* builtin_arraycopy ***********************************************************
2071 Builtin for java.lang.System.arraycopy.
2073 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2075 *******************************************************************************/
2077 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2078 java_handle_t *dest, s4 destStart, s4 len)
2080 arraydescriptor *sdesc;
2081 arraydescriptor *ddesc;
2084 if ((src == NULL) || (dest == NULL)) {
2085 exceptions_throw_nullpointerexception();
2089 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2090 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2092 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2093 exceptions_throw_arraystoreexception();
2097 // Check if offsets and length are positive.
2098 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2099 exceptions_throw_arrayindexoutofboundsexception();
2103 // Check if ranges are valid.
2104 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2105 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2106 exceptions_throw_arrayindexoutofboundsexception();
2115 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2116 /* We copy primitive values or references of exactly the same type */
2118 s4 dataoffset = sdesc->dataoffset;
2119 s4 componentsize = sdesc->componentsize;
2121 LLNI_CRITICAL_START;
2123 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2124 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2125 u1, (size_t) len * componentsize);
2130 /* We copy references of different type */
2132 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2133 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2135 if (destStart <= srcStart) {
2136 for (i = 0; i < len; i++) {
2139 o = array_objectarray_element_get(oas, srcStart + i);
2141 if (!builtin_canstore(oad, o))
2144 array_objectarray_element_set(oad, destStart + i, o);
2148 /* XXX this does not completely obey the specification!
2149 If an exception is thrown only the elements above the
2150 current index have been copied. The specification
2151 requires that only the elements *below* the current
2152 index have been copied before the throw. */
2154 for (i = len - 1; i >= 0; i--) {
2157 o = array_objectarray_element_get(oas, srcStart + i);
2159 if (!builtin_canstore(oad, o))
2162 array_objectarray_element_set(oad, destStart + i, o);
2169 /* builtin_nanotime ************************************************************
2171 Return the current time in nanoseconds.
2173 *******************************************************************************/
2175 s8 builtin_nanotime(void)
2180 if (gettimeofday(&tv, NULL) == -1)
2181 vm_abort("gettimeofday failed: %s", strerror(errno));
2183 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2185 return usecs * 1000;
2189 /* builtin_currenttimemillis ***************************************************
2191 Return the current time in milliseconds.
2193 *******************************************************************************/
2195 s8 builtin_currenttimemillis(void)
2199 msecs = builtin_nanotime() / 1000 / 1000;
2205 /* builtin_clone ***************************************************************
2207 Function for cloning objects or arrays.
2209 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2211 *******************************************************************************/
2213 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2215 arraydescriptor *ad;
2218 java_handle_t *co; /* cloned object header */
2220 /* get the array descriptor */
2222 ad = LLNI_vftbl_direct(o)->arraydesc;
2224 /* we are cloning an array */
2227 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2229 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2234 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2235 /* XXX this is only a dirty hack to make Boehm work with handles */
2237 co = LLNI_WRAP((java_object_t *) co);
2240 LLNI_CRITICAL_START;
2242 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2244 #if defined(ENABLE_GC_CACAO)
2245 heap_init_objectheader(LLNI_DIRECT(co), size);
2248 #if defined(ENABLE_THREADS)
2249 LLNI_DIRECT(co)->lockword.init();
2257 /* we are cloning a non-array */
2259 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2260 exceptions_throw_clonenotsupportedexception();
2264 /* get the class of the object */
2266 LLNI_class_get(o, c);
2268 /* create new object */
2270 co = builtin_new(c);
2275 LLNI_CRITICAL_START;
2277 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2279 #if defined(ENABLE_GC_CACAO)
2280 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2283 #if defined(ENABLE_THREADS)
2284 LLNI_DIRECT(co)->lockword.init();
2293 #if defined(ENABLE_CYCLES_STATS)
2294 void builtin_print_cycles_stats(FILE *file)
2296 fprintf(file,"builtin cylce count statistics:\n");
2298 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2299 CYCLES_STATS_PRINT(builtin_new ,file);
2303 #endif /* defined(ENABLE_CYCLES_STATS) */
2306 #if defined(ENABLE_VMLOG)
2308 #include <vmlog_cacao.c>
2313 * These are local overrides for various environment variables in Emacs.
2314 * Please do not remove this and leave it at the end of the file, where
2315 * Emacs will automagically detect them.
2316 * ---------------------------------------------------------------------
2319 * indent-tabs-mode: t
2323 * vim:noexpandtab:sw=4:ts=4: