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-common.h"
56 #include "threads/mutex.hpp"
57 #include "threads/thread.hpp"
59 #include "toolbox/logging.h"
60 #include "toolbox/util.h"
63 #include "vm/jit/builtin.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.h"
70 #include "vm/linker.h"
71 #include "vm/loader.hpp"
72 #include "vm/options.h"
73 #include "vm/primitive.hpp"
74 #include "vm/rt-timing.h"
75 #include "vm/string.hpp"
77 #include "vm/jit/asmpart.h"
78 #include "vm/jit/stubs.hpp"
79 #include "vm/jit/trace.hpp"
81 #if defined(ENABLE_VMLOG)
82 #include <vmlog_cacao.h>
86 /* include builtin tables *****************************************************/
88 #include "vm/jit/builtintable.inc"
91 CYCLES_STATS_DECLARE(builtin_new ,100,5)
92 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
95 /*============================================================================*/
96 /* BUILTIN TABLE MANAGEMENT FUNCTIONS */
97 /*============================================================================*/
99 /* builtintable_init ***********************************************************
101 Parse the descriptors of builtin functions and create the parsed
104 *******************************************************************************/
106 static bool builtintable_init(void)
108 descriptor_pool *descpool;
109 builtintable_entry *bte;
112 // Create new dump memory area.
115 /* create a new descriptor pool */
117 descpool = descriptor_pool_new(class_java_lang_Object);
119 /* add some entries we need */
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
124 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
127 /* first add all descriptors to the pool */
129 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
130 bte->name = utf_new_char(bte->cname);
131 bte->descriptor = utf_new_char(bte->cdescriptor);
133 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
137 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
138 bte->descriptor = utf_new_char(bte->cdescriptor);
140 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
144 for (bte = builtintable_function; bte->fp != NULL; bte++) {
145 bte->classname = utf_new_char(bte->cclassname);
146 bte->name = utf_new_char(bte->cname);
147 bte->descriptor = utf_new_char(bte->cdescriptor);
149 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
153 /* create the class reference table */
155 (void) descriptor_pool_create_classrefs(descpool, NULL);
157 /* allocate space for the parsed descriptors */
159 descriptor_pool_alloc_parsed_descriptors(descpool);
161 /* Now parse all descriptors. NOTE: builtin-functions are treated
162 like static methods (no `this' pointer). */
164 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
166 descriptor_pool_parse_method_descriptor(descpool,
168 ACC_STATIC | ACC_METHOD_BUILTIN,
171 /* generate a builtin stub if we need one */
173 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
174 m = method_new_builtin(bte);
175 BuiltinStub::generate(m, bte);
179 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
181 descriptor_pool_parse_method_descriptor(descpool,
183 ACC_STATIC | ACC_METHOD_BUILTIN,
186 /* no stubs should be needed for this table */
188 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
191 for (bte = builtintable_function; bte->fp != NULL; bte++) {
193 descriptor_pool_parse_method_descriptor(descpool,
195 ACC_STATIC | ACC_METHOD_BUILTIN,
198 /* generate a builtin stub if we need one */
200 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
201 m = method_new_builtin(bte);
202 BuiltinStub::generate(m, bte);
210 /* builtintable_comparator *****************************************************
212 qsort comparator for the automatic builtin table.
214 *******************************************************************************/
216 static int builtintable_comparator(const void *a, const void *b)
218 builtintable_entry *bte1;
219 builtintable_entry *bte2;
221 bte1 = (builtintable_entry *) a;
222 bte2 = (builtintable_entry *) b;
224 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
228 /* builtintable_sort_automatic *************************************************
230 Sorts the automatic builtin table.
232 *******************************************************************************/
234 static void builtintable_sort_automatic(void)
238 /* calculate table size statically (`- 1' comment see builtintable.inc) */
240 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
242 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
243 builtintable_comparator);
247 /* builtin_init ****************************************************************
249 Initialize the global table of builtin functions.
251 *******************************************************************************/
253 bool builtin_init(void)
255 TRACESUBSYSTEMINITIALIZATION("builtin_init");
257 /* initialize the builtin tables */
259 if (!builtintable_init())
262 /* sort builtin tables */
264 builtintable_sort_automatic();
270 /* builtintable_get_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)
659 if (s->subtype_display[t->subtype_depth] == t)
661 if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
663 for (i=0; i<s->subtype_overflow_length; i++)
664 if (s->subtype_overflow[i] == t)
669 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
671 arraydescriptor *desc;
672 arraydescriptor *valuedesc;
673 vftbl_t *componentvftbl;
682 /* The following is guaranteed (by verifier checks):
684 * *) oa->...vftbl->arraydesc != NULL
685 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
686 * *) o->vftbl is not an interface vftbl
689 desc = oa->header.objheader.vftbl->arraydesc;
690 componentvftbl = desc->componentvftbl;
691 valuevftbl = o->vftbl;
692 valuedesc = valuevftbl->arraydesc;
694 if ((desc->dimension - 1) == 0) {
695 /* {oa is a one-dimensional array} */
696 /* {oa is an array of references} */
698 if (valuevftbl == componentvftbl)
701 baseval = componentvftbl->baseval;
704 /* an array of interface references */
706 result = ((valuevftbl->interfacetablelength > -baseval) &&
707 (valuevftbl->interfacetable[baseval] != NULL));
710 result = fast_subtype_check(valuevftbl, componentvftbl);
713 else if (valuedesc == NULL) {
714 /* {oa has dimension > 1} */
715 /* {componentvftbl->arraydesc != NULL} */
717 /* check if o is an array */
722 /* {o is an array} */
724 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
733 /* This is an optimized version where a is guaranteed to be one-dimensional */
734 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
736 arraydescriptor *desc;
737 vftbl_t *elementvftbl;
746 /* The following is guaranteed (by verifier checks):
748 * *) a->...vftbl->arraydesc != NULL
749 * *) a->...vftbl->arraydesc->elementvftbl != NULL
750 * *) a->...vftbl->arraydesc->dimension == 1
751 * *) o->vftbl is not an interface vftbl
754 desc = a->header.objheader.vftbl->arraydesc;
755 elementvftbl = desc->elementvftbl;
756 valuevftbl = o->vftbl;
758 /* {a is a one-dimensional array} */
760 if (valuevftbl == elementvftbl)
763 baseval = elementvftbl->baseval;
766 /* an array of interface references */
767 result = ((valuevftbl->interfacetablelength > -baseval) &&
768 (valuevftbl->interfacetable[baseval] != NULL));
771 result = fast_subtype_check(valuevftbl, elementvftbl);
778 /* This is an optimized version where a is guaranteed to be a
779 * one-dimensional array of a class type */
780 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
782 vftbl_t *elementvftbl;
790 /* The following is guaranteed (by verifier checks):
792 * *) a->...vftbl->arraydesc != NULL
793 * *) a->...vftbl->arraydesc->elementvftbl != NULL
794 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
795 * *) a->...vftbl->arraydesc->dimension == 1
796 * *) o->vftbl is not an interface vftbl
799 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
800 valuevftbl = o->vftbl;
802 /* {a is a one-dimensional array} */
804 if (valuevftbl == elementvftbl)
807 result = fast_subtype_check(valuevftbl, elementvftbl);
813 /* builtin_new *****************************************************************
815 Creates a new instance of class c on the heap.
818 pointer to the object, or NULL if no memory is available
820 NOTE: This builtin can be called from NATIVE code only.
822 *******************************************************************************/
824 java_handle_t *builtin_new(classinfo *c)
827 #if defined(ENABLE_RT_TIMING)
828 struct timespec time_start, time_end;
830 #if defined(ENABLE_CYCLES_STATS)
831 u8 cycles_start, cycles_end;
834 RT_TIMING_GET_TIME(time_start);
835 CYCLES_STATS_GET(cycles_start);
837 /* is the class loaded */
839 assert(c->state & CLASS_LOADED);
841 /* check if we can instantiate this class */
843 if (c->flags & ACC_ABSTRACT) {
844 exceptions_throw_instantiationerror(c);
848 /* is the class linked */
850 if (!(c->state & CLASS_LINKED))
854 if (!(c->state & CLASS_INITIALIZED)) {
857 log_message_class("Initialize class (from builtin_new): ", c);
860 if (!initialize_class(c))
864 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
870 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
871 /* XXX this is only a dirty hack to make Boehm work with handles */
873 o = LLNI_WRAP((java_object_t *) o);
876 LLNI_vftbl_direct(o) = c->vftbl;
878 #if defined(ENABLE_THREADS)
879 lock_init_object_lock(LLNI_DIRECT(o));
882 CYCLES_STATS_GET(cycles_end);
883 RT_TIMING_GET_TIME(time_end);
885 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
886 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
891 #if defined(ENABLE_ESCAPE_REASON)
892 java_handle_t *builtin_escape_reason_new(classinfo *c) {
893 print_escape_reasons();
894 return builtin_java_new(c);
898 #if defined(ENABLE_TLH)
899 java_handle_t *builtin_tlh_new(classinfo *c)
902 # if defined(ENABLE_RT_TIMING)
903 struct timespec time_start, time_end;
905 # if defined(ENABLE_CYCLES_STATS)
906 u8 cycles_start, cycles_end;
909 RT_TIMING_GET_TIME(time_start);
910 CYCLES_STATS_GET(cycles_start);
912 /* is the class loaded */
914 assert(c->state & CLASS_LOADED);
916 /* check if we can instantiate this class */
918 if (c->flags & ACC_ABSTRACT) {
919 exceptions_throw_instantiationerror(c);
923 /* is the class linked */
925 if (!(c->state & CLASS_LINKED))
929 if (!(c->state & CLASS_INITIALIZED)) {
930 # if !defined(NDEBUG)
932 log_message_class("Initialize class (from builtin_new): ", c);
935 if (!initialize_class(c))
940 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
945 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
952 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
953 /* XXX this is only a dirty hack to make Boehm work with handles */
955 o = LLNI_WRAP((java_object_t *) o);
958 LLNI_vftbl_direct(o) = c->vftbl;
960 # if defined(ENABLE_THREADS)
961 lock_init_object_lock(LLNI_DIRECT(o));
964 CYCLES_STATS_GET(cycles_end);
965 RT_TIMING_GET_TIME(time_end);
968 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
969 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
977 /* builtin_java_new ************************************************************
979 NOTE: This is a SLOW builtin and can be called from JIT code only.
981 *******************************************************************************/
983 java_handle_t *builtin_java_new(java_handle_t *clazz)
985 return builtin_new(LLNI_classinfo_unwrap(clazz));
989 /* builtin_fast_new ************************************************************
991 Creates a new instance of class c on the heap.
994 pointer to the object, or NULL if no fast return
995 is possible for any reason.
997 NOTE: This is a FAST builtin and can be called from JIT code only.
999 *******************************************************************************/
1001 java_object_t *builtin_fast_new(classinfo *c)
1004 #if defined(ENABLE_RT_TIMING)
1005 struct timespec time_start, time_end;
1007 #if defined(ENABLE_CYCLES_STATS)
1008 u8 cycles_start, cycles_end;
1011 RT_TIMING_GET_TIME(time_start);
1012 CYCLES_STATS_GET(cycles_start);
1014 /* is the class loaded */
1016 assert(c->state & CLASS_LOADED);
1018 /* check if we can instantiate this class */
1020 if (c->flags & ACC_ABSTRACT)
1023 /* is the class linked */
1025 if (!(c->state & CLASS_LINKED))
1028 if (!(c->state & CLASS_INITIALIZED))
1031 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1032 c->finalizer, false);
1037 o->vftbl = c->vftbl;
1039 #if defined(ENABLE_THREADS)
1040 lock_init_object_lock(o);
1043 CYCLES_STATS_GET(cycles_end);
1044 RT_TIMING_GET_TIME(time_end);
1046 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1047 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1053 /* builtin_newarray ************************************************************
1055 Creates an array with the given vftbl on the heap. This function
1056 takes as class argument an array class.
1059 pointer to the array or NULL if no memory is available
1061 NOTE: This builtin can be called from NATIVE code only.
1063 *******************************************************************************/
1065 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1067 arraydescriptor *desc;
1072 #if defined(ENABLE_RT_TIMING)
1073 struct timespec time_start, time_end;
1076 RT_TIMING_GET_TIME(time_start);
1078 desc = arrayclass->vftbl->arraydesc;
1079 dataoffset = desc->dataoffset;
1080 componentsize = desc->componentsize;
1083 exceptions_throw_negativearraysizeexception();
1087 actualsize = dataoffset + size * componentsize;
1089 /* check for overflow */
1091 if (((u4) actualsize) < ((u4) size)) {
1092 exceptions_throw_outofmemoryerror();
1096 a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1101 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1102 /* XXX this is only a dirty hack to make Boehm work with handles */
1104 a = LLNI_WRAP((java_object_t *) a);
1107 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1109 #if defined(ENABLE_THREADS)
1110 lock_init_object_lock(LLNI_DIRECT(a));
1113 LLNI_array_size(a) = size;
1115 RT_TIMING_GET_TIME(time_end);
1116 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1122 /* builtin_java_newarray *******************************************************
1124 NOTE: This is a SLOW builtin and can be called from JIT code only.
1126 *******************************************************************************/
1128 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1130 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1134 /* builtin_anewarray ***********************************************************
1136 Creates an array of references to the given class type on the heap.
1139 pointer to the array or NULL if no memory is
1142 NOTE: This builtin can be called from NATIVE code only.
1144 *******************************************************************************/
1146 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1148 classinfo *arrayclass;
1150 /* is class loaded */
1152 assert(componentclass->state & CLASS_LOADED);
1154 /* is class linked */
1156 if (!(componentclass->state & CLASS_LINKED))
1157 if (!link_class(componentclass))
1160 arrayclass = class_array_of(componentclass, true);
1165 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1169 /* builtin_newarray_type ****************************************************
1171 Creates an array of [type]s on the heap.
1174 pointer to the array or NULL if no memory is available
1176 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1178 *******************************************************************************/
1180 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1181 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1183 return (java_handle_##type##array_t *) \
1184 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1187 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1188 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1189 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1190 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1191 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1192 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1193 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1194 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1197 /* builtin_multianewarray_intern ***********************************************
1199 Creates a multi-dimensional array on the heap. The dimensions are
1200 passed in an array of longs.
1203 n.............number of dimensions to create
1204 arrayclass....the array class
1205 dims..........array containing the size of each dimension to create
1208 pointer to the array or NULL if no memory is available
1210 ******************************************************************************/
1212 static java_handle_t *builtin_multianewarray_intern(int n,
1213 classinfo *arrayclass,
1218 classinfo *componentclass;
1221 /* create this dimension */
1223 size = (s4) dims[0];
1224 a = builtin_newarray(size, arrayclass);
1229 /* if this is the last dimension return */
1234 /* get the class of the components to create */
1236 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1238 /* The verifier guarantees that the dimension count is in the range. */
1240 /* create the component arrays */
1242 for (i = 0; i < size; i++) {
1244 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1245 /* we save an s4 to a s8 slot, 8-byte aligned */
1247 builtin_multianewarray_intern(n, componentclass, dims + 2);
1249 builtin_multianewarray_intern(n, componentclass, dims + 1);
1255 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1262 /* builtin_multianewarray ******************************************************
1264 Wrapper for builtin_multianewarray_intern which checks all
1265 dimensions before we start allocating.
1267 NOTE: This is a SLOW builtin and can be called from JIT code only.
1269 ******************************************************************************/
1271 java_handle_objectarray_t *builtin_multianewarray(int n,
1272 java_handle_t *arrayclazz,
1279 /* check all dimensions before doing anything */
1281 for (i = 0; i < n; i++) {
1282 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1283 /* we save an s4 to a s8 slot, 8-byte aligned */
1284 size = (s4) dims[i * 2];
1286 size = (s4) dims[i];
1290 exceptions_throw_negativearraysizeexception();
1295 c = LLNI_classinfo_unwrap(arrayclazz);
1297 /* now call the real function */
1299 return (java_handle_objectarray_t *)
1300 builtin_multianewarray_intern(n, c, dims);
1304 /* builtin_verbosecall_enter ***************************************************
1306 Print method call with arguments for -verbose:call.
1308 XXX: Remove mew once all archs use the new tracer!
1310 *******************************************************************************/
1312 #if !defined(NDEBUG)
1313 #ifdef TRACE_ARGS_NUM
1314 void builtin_verbosecall_enter(s8 a0, s8 a1,
1315 # if TRACE_ARGS_NUM >= 4
1318 # if TRACE_ARGS_NUM >= 6
1321 # if TRACE_ARGS_NUM == 8
1326 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1329 #endif /* !defined(NDEBUG) */
1332 /* builtin_verbosecall_exit ****************************************************
1334 Print method exit for -verbose:call.
1336 XXX: Remove mew once all archs use the new tracer!
1338 *******************************************************************************/
1340 #if !defined(NDEBUG)
1341 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1343 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1345 #endif /* !defined(NDEBUG) */
1348 /*============================================================================*/
1349 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1350 /*============================================================================*/
1352 /*********** Functions for integer divisions *****************************
1354 On some systems (eg. DEC ALPHA), integer division is not supported by the
1355 CPU. These helper functions implement the missing functionality.
1357 ******************************************************************************/
1359 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1360 s4 builtin_idiv(s4 a, s4 b)
1369 s4 builtin_irem(s4 a, s4 b)
1377 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1380 /* functions for long arithmetics **********************************************
1382 On systems where 64 bit Integers are not supported by the CPU,
1383 these functions are needed.
1385 ******************************************************************************/
1387 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1388 s8 builtin_ladd(s8 a, s8 b)
1401 s8 builtin_lsub(s8 a, s8 b)
1414 s8 builtin_lneg(s8 a)
1426 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1429 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1430 s8 builtin_lmul(s8 a, s8 b)
1442 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1445 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1446 s8 builtin_ldiv(s8 a, s8 b)
1459 s8 builtin_lrem(s8 a, s8 b)
1471 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1474 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1475 s8 builtin_lshl(s8 a, s4 b)
1488 s8 builtin_lshr(s8 a, s4 b)
1501 s8 builtin_lushr(s8 a, s4 b)
1506 c = ((u8) a) >> (b & 63);
1513 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1516 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1517 s8 builtin_land(s8 a, s8 b)
1530 s8 builtin_lor(s8 a, s8 b)
1543 s8 builtin_lxor(s8 a, s8 b)
1555 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1558 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1559 s4 builtin_lcmp(s8 a, s8 b)
1573 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1576 /* functions for unsupported floating instructions ****************************/
1578 /* used to convert FLT_xxx defines into float values */
1580 static inline float intBitsToFloat(s4 i)
1589 /* used to convert DBL_xxx defines into double values */
1591 static inline float longBitsToDouble(s8 l)
1601 float builtin_fadd(float a, float b)
1603 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1604 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1615 if (copysignf(1.0, a) == copysignf(1.0, b))
1618 return intBitsToFloat(FLT_NAN);
1624 float builtin_fsub(float a, float b)
1626 return builtin_fadd(a, builtin_fneg(b));
1630 float builtin_fmul(float a, float b)
1632 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1633 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1635 if (finitef(b)) return a * b;
1637 if (a == 0) return intBitsToFloat(FLT_NAN);
1638 else return copysignf(b, copysignf(1.0, b)*a);
1643 if (b == 0) return intBitsToFloat(FLT_NAN);
1644 else return copysignf(a, copysignf(1.0, a)*b);
1647 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1653 /* builtin_ddiv ****************************************************************
1655 Implementation as described in VM Spec.
1657 *******************************************************************************/
1659 float builtin_fdiv(float a, float b)
1663 /* If neither value1' nor value2' is NaN, the sign of the result */
1664 /* is positive if both values have the same sign, negative if the */
1665 /* values have different signs. */
1671 /* If either value1' or value2' is NaN, the result is NaN. */
1673 return intBitsToFloat(FLT_NAN);
1676 /* Division of a finite value by an infinity results in a */
1677 /* signed zero, with the sign-producing rule just given. */
1679 /* is sign equal? */
1681 if (copysignf(1.0, a) == copysignf(1.0, b))
1690 /* If either value1' or value2' is NaN, the result is NaN. */
1692 return intBitsToFloat(FLT_NAN);
1694 } else if (finitef(b)) {
1695 /* Division of an infinity by a finite value results in a signed */
1696 /* infinity, with the sign-producing rule just given. */
1698 /* is sign equal? */
1700 if (copysignf(1.0, a) == copysignf(1.0, b))
1701 return intBitsToFloat(FLT_POSINF);
1703 return intBitsToFloat(FLT_NEGINF);
1706 /* Division of an infinity by an infinity results in NaN. */
1708 return intBitsToFloat(FLT_NAN);
1714 float builtin_fneg(float a)
1716 if (isnanf(a)) return a;
1718 if (finitef(a)) return -a;
1719 else return copysignf(a, -copysignf(1.0, a));
1722 #endif /* !SUPPORT_FLOAT */
1725 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1726 s4 builtin_fcmpl(float a, float b)
1734 if (!finitef(a) || !finitef(b)) {
1735 a = finitef(a) ? 0 : copysignf(1.0, a);
1736 b = finitef(b) ? 0 : copysignf(1.0, b);
1749 s4 builtin_fcmpg(float a, float b)
1751 if (isnanf(a)) return 1;
1752 if (isnanf(b)) return 1;
1753 if (!finitef(a) || !finitef(b)) {
1754 a = finitef(a) ? 0 : copysignf(1.0, a);
1755 b = finitef(b) ? 0 : copysignf(1.0, b);
1757 if (a > b) return 1;
1758 if (a == b) return 0;
1761 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1764 float builtin_frem(float a, float b)
1770 /* functions for unsupported double instructions ******************************/
1773 double builtin_dadd(double a, double b)
1775 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1776 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1778 if (finite(b)) return a + b;
1782 if (finite(b)) return a;
1784 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1785 else return longBitsToDouble(DBL_NAN);
1791 double builtin_dsub(double a, double b)
1793 return builtin_dadd(a, builtin_dneg(b));
1797 double builtin_dmul(double a, double b)
1799 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1800 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1802 if (finite(b)) return a * b;
1804 if (a == 0) return longBitsToDouble(DBL_NAN);
1805 else return copysign(b, copysign(1.0, b) * a);
1810 if (b == 0) return longBitsToDouble(DBL_NAN);
1811 else return copysign(a, copysign(1.0, a) * b);
1814 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1820 /* builtin_ddiv ****************************************************************
1822 Implementation as described in VM Spec.
1824 *******************************************************************************/
1826 double builtin_ddiv(double a, double b)
1830 /* If neither value1' nor value2' is NaN, the sign of the result */
1831 /* is positive if both values have the same sign, negative if the */
1832 /* values have different signs. */
1838 /* If either value1' or value2' is NaN, the result is NaN. */
1840 return longBitsToDouble(DBL_NAN);
1843 /* Division of a finite value by an infinity results in a */
1844 /* signed zero, with the sign-producing rule just given. */
1846 /* is sign equal? */
1848 if (copysign(1.0, a) == copysign(1.0, b))
1857 /* If either value1' or value2' is NaN, the result is NaN. */
1859 return longBitsToDouble(DBL_NAN);
1861 } else if (finite(b)) {
1862 /* Division of an infinity by a finite value results in a signed */
1863 /* infinity, with the sign-producing rule just given. */
1865 /* is sign equal? */
1867 if (copysign(1.0, a) == copysign(1.0, b))
1868 return longBitsToDouble(DBL_POSINF);
1870 return longBitsToDouble(DBL_NEGINF);
1873 /* Division of an infinity by an infinity results in NaN. */
1875 return longBitsToDouble(DBL_NAN);
1881 /* builtin_dneg ****************************************************************
1883 Implemented as described in VM Spec.
1885 *******************************************************************************/
1887 double builtin_dneg(double a)
1890 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1897 /* If the operand is a zero, the result is the zero of opposite */
1903 /* If the operand is an infinity, the result is the infinity of */
1904 /* opposite sign. */
1906 return copysign(a, -copysign(1.0, a));
1910 #endif /* !SUPPORT_DOUBLE */
1913 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1914 s4 builtin_dcmpl(double a, double b)
1922 if (!finite(a) || !finite(b)) {
1923 a = finite(a) ? 0 : copysign(1.0, a);
1924 b = finite(b) ? 0 : copysign(1.0, b);
1937 s4 builtin_dcmpg(double a, double b)
1945 if (!finite(a) || !finite(b)) {
1946 a = finite(a) ? 0 : copysign(1.0, a);
1947 b = finite(b) ? 0 : copysign(1.0, b);
1958 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1961 double builtin_drem(double a, double b)
1967 /* conversion operations ******************************************************/
1970 s8 builtin_i2l(s4 i)
1982 s4 builtin_l2i(s8 l)
1993 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1994 float builtin_i2f(s4 a)
1996 float f = (float) a;
1999 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2002 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2003 double builtin_i2d(s4 a)
2005 double d = (double) a;
2008 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2011 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2012 float builtin_l2f(s8 a)
2015 float f = (float) a;
2021 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2024 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2025 double builtin_l2d(s8 a)
2028 double d = (double) a;
2034 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2037 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2038 s4 builtin_f2i(float a)
2042 i = builtin_d2i((double) a);
2053 if (a < (-2147483648))
2054 return (-2147483648);
2057 f = copysignf((float) 1.0, a);
2060 return (-2147483648); */
2062 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2065 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2066 s8 builtin_f2l(float a)
2070 l = builtin_d2l((double) a);
2077 if (a > 9223372036854775807L)
2078 return 9223372036854775807L;
2079 if (a < (-9223372036854775808L))
2080 return (-9223372036854775808L);
2085 f = copysignf((float) 1.0, a);
2087 return 9223372036854775807L;
2088 return (-9223372036854775808L); */
2090 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2093 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2094 s4 builtin_d2i(double a)
2099 if (a >= 2147483647)
2101 if (a <= (-2147483647-1))
2102 return (-2147483647-1);
2107 d = copysign(1.0, a);
2110 return (-2147483647-1);
2112 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2115 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2116 s8 builtin_d2l(double a)
2121 if (a >= 9223372036854775807LL)
2122 return 9223372036854775807LL;
2123 if (a <= (-9223372036854775807LL-1))
2124 return (-9223372036854775807LL-1);
2129 d = copysign(1.0, a);
2131 return 9223372036854775807LL;
2132 return (-9223372036854775807LL-1);
2134 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2137 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2138 double builtin_f2d(float a)
2140 if (finitef(a)) return (double) a;
2143 return longBitsToDouble(DBL_NAN);
2145 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2149 float builtin_d2f(double a)
2155 return intBitsToFloat(FLT_NAN);
2157 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2160 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2163 /*============================================================================*/
2164 /* AUTOMATICALLY REPLACED FUNCTIONS */
2165 /*============================================================================*/
2167 /* builtin_arraycopy ***********************************************************
2169 Builtin for java.lang.System.arraycopy.
2171 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2173 *******************************************************************************/
2175 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2176 java_handle_t *dest, s4 destStart, s4 len)
2178 arraydescriptor *sdesc;
2179 arraydescriptor *ddesc;
2182 if ((src == NULL) || (dest == NULL)) {
2183 exceptions_throw_nullpointerexception();
2187 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2188 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2190 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2191 exceptions_throw_arraystoreexception();
2195 // Check if offsets and length are positive.
2196 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2197 exceptions_throw_arrayindexoutofboundsexception();
2201 // Check if ranges are valid.
2202 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2203 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2204 exceptions_throw_arrayindexoutofboundsexception();
2213 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2214 /* We copy primitive values or references of exactly the same type */
2216 s4 dataoffset = sdesc->dataoffset;
2217 s4 componentsize = sdesc->componentsize;
2219 LLNI_CRITICAL_START;
2221 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2222 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2223 u1, (size_t) len * componentsize);
2228 /* We copy references of different type */
2230 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2231 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2233 if (destStart <= srcStart) {
2234 for (i = 0; i < len; i++) {
2237 o = array_objectarray_element_get(oas, srcStart + i);
2239 if (!builtin_canstore(oad, o))
2242 array_objectarray_element_set(oad, destStart + i, o);
2246 /* XXX this does not completely obey the specification!
2247 If an exception is thrown only the elements above the
2248 current index have been copied. The specification
2249 requires that only the elements *below* the current
2250 index have been copied before the throw. */
2252 for (i = len - 1; i >= 0; i--) {
2255 o = array_objectarray_element_get(oas, srcStart + i);
2257 if (!builtin_canstore(oad, o))
2260 array_objectarray_element_set(oad, destStart + i, o);
2267 /* builtin_nanotime ************************************************************
2269 Return the current time in nanoseconds.
2271 *******************************************************************************/
2273 s8 builtin_nanotime(void)
2278 if (gettimeofday(&tv, NULL) == -1)
2279 vm_abort("gettimeofday failed: %s", strerror(errno));
2281 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2283 return usecs * 1000;
2287 /* builtin_currenttimemillis ***************************************************
2289 Return the current time in milliseconds.
2291 *******************************************************************************/
2293 s8 builtin_currenttimemillis(void)
2297 msecs = builtin_nanotime() / 1000 / 1000;
2303 /* builtin_clone ***************************************************************
2305 Function for cloning objects or arrays.
2307 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2309 *******************************************************************************/
2311 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2313 arraydescriptor *ad;
2316 java_handle_t *co; /* cloned object header */
2318 /* get the array descriptor */
2320 ad = LLNI_vftbl_direct(o)->arraydesc;
2322 /* we are cloning an array */
2325 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2327 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2332 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2333 /* XXX this is only a dirty hack to make Boehm work with handles */
2335 co = LLNI_WRAP((java_object_t *) co);
2338 LLNI_CRITICAL_START;
2340 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2342 #if defined(ENABLE_GC_CACAO)
2343 heap_init_objectheader(LLNI_DIRECT(co), size);
2346 #if defined(ENABLE_THREADS)
2347 lock_init_object_lock(LLNI_DIRECT(co));
2355 /* we are cloning a non-array */
2357 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2358 exceptions_throw_clonenotsupportedexception();
2362 /* get the class of the object */
2364 LLNI_class_get(o, c);
2366 /* create new object */
2368 co = builtin_new(c);
2373 LLNI_CRITICAL_START;
2375 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2377 #if defined(ENABLE_GC_CACAO)
2378 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2381 #if defined(ENABLE_THREADS)
2382 lock_init_object_lock(LLNI_DIRECT(co));
2391 #if defined(ENABLE_CYCLES_STATS)
2392 void builtin_print_cycles_stats(FILE *file)
2394 fprintf(file,"builtin cylce count statistics:\n");
2396 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2397 CYCLES_STATS_PRINT(builtin_new ,file);
2401 #endif /* defined(ENABLE_CYCLES_STATS) */
2404 #if defined(ENABLE_VMLOG)
2406 #include <vmlog_cacao.c>
2411 * These are local overrides for various environment variables in Emacs.
2412 * Please do not remove this and leave it at the end of the file, where
2413 * Emacs will automagically detect them.
2414 * ---------------------------------------------------------------------
2417 * indent-tabs-mode: t
2421 * vim:noexpandtab:sw=4:ts=4: