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 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
658 arraydescriptor *desc;
659 arraydescriptor *valuedesc;
660 vftbl_t *componentvftbl;
669 /* The following is guaranteed (by verifier checks):
671 * *) oa->...vftbl->arraydesc != NULL
672 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
673 * *) o->vftbl is not an interface vftbl
676 desc = oa->header.objheader.vftbl->arraydesc;
677 componentvftbl = desc->componentvftbl;
678 valuevftbl = o->vftbl;
679 valuedesc = valuevftbl->arraydesc;
681 if ((desc->dimension - 1) == 0) {
682 /* {oa is a one-dimensional array} */
683 /* {oa is an array of references} */
685 if (valuevftbl == componentvftbl)
688 linker_classrenumber_mutex->lock();
690 baseval = componentvftbl->baseval;
693 /* an array of interface references */
695 result = ((valuevftbl->interfacetablelength > -baseval) &&
696 (valuevftbl->interfacetable[baseval] != NULL));
699 diffval = valuevftbl->baseval - componentvftbl->baseval;
700 result = diffval <= (uint32_t) componentvftbl->diffval;
703 linker_classrenumber_mutex->unlock();
705 else if (valuedesc == NULL) {
706 /* {oa has dimension > 1} */
707 /* {componentvftbl->arraydesc != NULL} */
709 /* check if o is an array */
714 /* {o is an array} */
716 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
725 /* This is an optimized version where a is guaranteed to be one-dimensional */
726 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
728 arraydescriptor *desc;
729 vftbl_t *elementvftbl;
738 /* The following is guaranteed (by verifier checks):
740 * *) a->...vftbl->arraydesc != NULL
741 * *) a->...vftbl->arraydesc->elementvftbl != NULL
742 * *) a->...vftbl->arraydesc->dimension == 1
743 * *) o->vftbl is not an interface vftbl
746 desc = a->header.objheader.vftbl->arraydesc;
747 elementvftbl = desc->elementvftbl;
748 valuevftbl = o->vftbl;
750 /* {a is a one-dimensional array} */
752 if (valuevftbl == elementvftbl)
755 linker_classrenumber_mutex->lock();
757 baseval = elementvftbl->baseval;
760 /* an array of interface references */
761 result = ((valuevftbl->interfacetablelength > -baseval) &&
762 (valuevftbl->interfacetable[baseval] != NULL));
765 diffval = valuevftbl->baseval - elementvftbl->baseval;
766 result = diffval <= (uint32_t) elementvftbl->diffval;
769 linker_classrenumber_mutex->unlock();
775 /* This is an optimized version where a is guaranteed to be a
776 * one-dimensional array of a class type */
777 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
779 vftbl_t *elementvftbl;
787 /* The following is guaranteed (by verifier checks):
789 * *) a->...vftbl->arraydesc != NULL
790 * *) a->...vftbl->arraydesc->elementvftbl != NULL
791 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
792 * *) a->...vftbl->arraydesc->dimension == 1
793 * *) o->vftbl is not an interface vftbl
796 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
797 valuevftbl = o->vftbl;
799 /* {a is a one-dimensional array} */
801 if (valuevftbl == elementvftbl)
804 linker_classrenumber_mutex->lock();
806 diffval = valuevftbl->baseval - elementvftbl->baseval;
807 result = diffval <= (uint32_t) elementvftbl->diffval;
809 linker_classrenumber_mutex->unlock();
815 /* builtin_new *****************************************************************
817 Creates a new instance of class c on the heap.
820 pointer to the object, or NULL if no memory is available
822 NOTE: This builtin can be called from NATIVE code only.
824 *******************************************************************************/
826 java_handle_t *builtin_new(classinfo *c)
829 #if defined(ENABLE_RT_TIMING)
830 struct timespec time_start, time_end;
832 #if defined(ENABLE_CYCLES_STATS)
833 u8 cycles_start, cycles_end;
836 RT_TIMING_GET_TIME(time_start);
837 CYCLES_STATS_GET(cycles_start);
839 /* is the class loaded */
841 assert(c->state & CLASS_LOADED);
843 /* check if we can instantiate this class */
845 if (c->flags & ACC_ABSTRACT) {
846 exceptions_throw_instantiationerror(c);
850 /* is the class linked */
852 if (!(c->state & CLASS_LINKED))
856 if (!(c->state & CLASS_INITIALIZED)) {
859 log_message_class("Initialize class (from builtin_new): ", c);
862 if (!initialize_class(c))
866 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
872 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
873 /* XXX this is only a dirty hack to make Boehm work with handles */
875 o = LLNI_WRAP((java_object_t *) o);
878 LLNI_vftbl_direct(o) = c->vftbl;
880 #if defined(ENABLE_THREADS)
881 lock_init_object_lock(LLNI_DIRECT(o));
884 CYCLES_STATS_GET(cycles_end);
885 RT_TIMING_GET_TIME(time_end);
887 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
888 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
893 #if defined(ENABLE_ESCAPE_REASON)
894 java_handle_t *builtin_escape_reason_new(classinfo *c) {
895 print_escape_reasons();
896 return builtin_java_new(c);
900 #if defined(ENABLE_TLH)
901 java_handle_t *builtin_tlh_new(classinfo *c)
904 # if defined(ENABLE_RT_TIMING)
905 struct timespec time_start, time_end;
907 # if defined(ENABLE_CYCLES_STATS)
908 u8 cycles_start, cycles_end;
911 RT_TIMING_GET_TIME(time_start);
912 CYCLES_STATS_GET(cycles_start);
914 /* is the class loaded */
916 assert(c->state & CLASS_LOADED);
918 /* check if we can instantiate this class */
920 if (c->flags & ACC_ABSTRACT) {
921 exceptions_throw_instantiationerror(c);
925 /* is the class linked */
927 if (!(c->state & CLASS_LINKED))
931 if (!(c->state & CLASS_INITIALIZED)) {
932 # if !defined(NDEBUG)
934 log_message_class("Initialize class (from builtin_new): ", c);
937 if (!initialize_class(c))
942 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
947 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
954 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
955 /* XXX this is only a dirty hack to make Boehm work with handles */
957 o = LLNI_WRAP((java_object_t *) o);
960 LLNI_vftbl_direct(o) = c->vftbl;
962 # if defined(ENABLE_THREADS)
963 lock_init_object_lock(LLNI_DIRECT(o));
966 CYCLES_STATS_GET(cycles_end);
967 RT_TIMING_GET_TIME(time_end);
970 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
971 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
979 /* builtin_java_new ************************************************************
981 NOTE: This is a SLOW builtin and can be called from JIT code only.
983 *******************************************************************************/
985 java_handle_t *builtin_java_new(java_handle_t *clazz)
987 return builtin_new(LLNI_classinfo_unwrap(clazz));
991 /* builtin_fast_new ************************************************************
993 Creates a new instance of class c on the heap.
996 pointer to the object, or NULL if no fast return
997 is possible for any reason.
999 NOTE: This is a FAST builtin and can be called from JIT code only.
1001 *******************************************************************************/
1003 java_object_t *builtin_fast_new(classinfo *c)
1006 #if defined(ENABLE_RT_TIMING)
1007 struct timespec time_start, time_end;
1009 #if defined(ENABLE_CYCLES_STATS)
1010 u8 cycles_start, cycles_end;
1013 RT_TIMING_GET_TIME(time_start);
1014 CYCLES_STATS_GET(cycles_start);
1016 /* is the class loaded */
1018 assert(c->state & CLASS_LOADED);
1020 /* check if we can instantiate this class */
1022 if (c->flags & ACC_ABSTRACT)
1025 /* is the class linked */
1027 if (!(c->state & CLASS_LINKED))
1030 if (!(c->state & CLASS_INITIALIZED))
1033 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1034 c->finalizer, false);
1039 o->vftbl = c->vftbl;
1041 #if defined(ENABLE_THREADS)
1042 lock_init_object_lock(o);
1045 CYCLES_STATS_GET(cycles_end);
1046 RT_TIMING_GET_TIME(time_end);
1048 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1049 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1055 /* builtin_newarray ************************************************************
1057 Creates an array with the given vftbl on the heap. This function
1058 takes as class argument an array class.
1061 pointer to the array or NULL if no memory is available
1063 NOTE: This builtin can be called from NATIVE code only.
1065 *******************************************************************************/
1067 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1069 arraydescriptor *desc;
1074 #if defined(ENABLE_RT_TIMING)
1075 struct timespec time_start, time_end;
1078 RT_TIMING_GET_TIME(time_start);
1080 desc = arrayclass->vftbl->arraydesc;
1081 dataoffset = desc->dataoffset;
1082 componentsize = desc->componentsize;
1085 exceptions_throw_negativearraysizeexception();
1089 actualsize = dataoffset + size * componentsize;
1091 /* check for overflow */
1093 if (((u4) actualsize) < ((u4) size)) {
1094 exceptions_throw_outofmemoryerror();
1098 a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1103 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1104 /* XXX this is only a dirty hack to make Boehm work with handles */
1106 a = LLNI_WRAP((java_object_t *) a);
1109 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1111 #if defined(ENABLE_THREADS)
1112 lock_init_object_lock(LLNI_DIRECT(a));
1115 LLNI_array_size(a) = size;
1117 RT_TIMING_GET_TIME(time_end);
1118 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1124 /* builtin_java_newarray *******************************************************
1126 NOTE: This is a SLOW builtin and can be called from JIT code only.
1128 *******************************************************************************/
1130 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1132 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1136 /* builtin_anewarray ***********************************************************
1138 Creates an array of references to the given class type on the heap.
1141 pointer to the array or NULL if no memory is
1144 NOTE: This builtin can be called from NATIVE code only.
1146 *******************************************************************************/
1148 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1150 classinfo *arrayclass;
1152 /* is class loaded */
1154 assert(componentclass->state & CLASS_LOADED);
1156 /* is class linked */
1158 if (!(componentclass->state & CLASS_LINKED))
1159 if (!link_class(componentclass))
1162 arrayclass = class_array_of(componentclass, true);
1167 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1171 /* builtin_newarray_type ****************************************************
1173 Creates an array of [type]s on the heap.
1176 pointer to the array or NULL if no memory is available
1178 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1180 *******************************************************************************/
1182 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1183 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1185 return (java_handle_##type##array_t *) \
1186 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1189 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1190 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1191 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1192 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1193 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1194 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1195 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1196 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1199 /* builtin_multianewarray_intern ***********************************************
1201 Creates a multi-dimensional array on the heap. The dimensions are
1202 passed in an array of longs.
1205 n.............number of dimensions to create
1206 arrayclass....the array class
1207 dims..........array containing the size of each dimension to create
1210 pointer to the array or NULL if no memory is available
1212 ******************************************************************************/
1214 static java_handle_t *builtin_multianewarray_intern(int n,
1215 classinfo *arrayclass,
1220 classinfo *componentclass;
1223 /* create this dimension */
1225 size = (s4) dims[0];
1226 a = builtin_newarray(size, arrayclass);
1231 /* if this is the last dimension return */
1236 /* get the class of the components to create */
1238 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1240 /* The verifier guarantees that the dimension count is in the range. */
1242 /* create the component arrays */
1244 for (i = 0; i < size; i++) {
1246 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1247 /* we save an s4 to a s8 slot, 8-byte aligned */
1249 builtin_multianewarray_intern(n, componentclass, dims + 2);
1251 builtin_multianewarray_intern(n, componentclass, dims + 1);
1257 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1264 /* builtin_multianewarray ******************************************************
1266 Wrapper for builtin_multianewarray_intern which checks all
1267 dimensions before we start allocating.
1269 NOTE: This is a SLOW builtin and can be called from JIT code only.
1271 ******************************************************************************/
1273 java_handle_objectarray_t *builtin_multianewarray(int n,
1274 java_handle_t *arrayclazz,
1281 /* check all dimensions before doing anything */
1283 for (i = 0; i < n; i++) {
1284 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1285 /* we save an s4 to a s8 slot, 8-byte aligned */
1286 size = (s4) dims[i * 2];
1288 size = (s4) dims[i];
1292 exceptions_throw_negativearraysizeexception();
1297 c = LLNI_classinfo_unwrap(arrayclazz);
1299 /* now call the real function */
1301 return (java_handle_objectarray_t *)
1302 builtin_multianewarray_intern(n, c, dims);
1306 /* builtin_verbosecall_enter ***************************************************
1308 Print method call with arguments for -verbose:call.
1310 XXX: Remove mew once all archs use the new tracer!
1312 *******************************************************************************/
1314 #if !defined(NDEBUG)
1315 #ifdef TRACE_ARGS_NUM
1316 void builtin_verbosecall_enter(s8 a0, s8 a1,
1317 # if TRACE_ARGS_NUM >= 4
1320 # if TRACE_ARGS_NUM >= 6
1323 # if TRACE_ARGS_NUM == 8
1328 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1331 #endif /* !defined(NDEBUG) */
1334 /* builtin_verbosecall_exit ****************************************************
1336 Print method exit for -verbose:call.
1338 XXX: Remove mew once all archs use the new tracer!
1340 *******************************************************************************/
1342 #if !defined(NDEBUG)
1343 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1345 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1347 #endif /* !defined(NDEBUG) */
1350 /*============================================================================*/
1351 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1352 /*============================================================================*/
1354 /*********** Functions for integer divisions *****************************
1356 On some systems (eg. DEC ALPHA), integer division is not supported by the
1357 CPU. These helper functions implement the missing functionality.
1359 ******************************************************************************/
1361 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1362 s4 builtin_idiv(s4 a, s4 b)
1371 s4 builtin_irem(s4 a, s4 b)
1379 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1382 /* functions for long arithmetics **********************************************
1384 On systems where 64 bit Integers are not supported by the CPU,
1385 these functions are needed.
1387 ******************************************************************************/
1389 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1390 s8 builtin_ladd(s8 a, s8 b)
1403 s8 builtin_lsub(s8 a, s8 b)
1416 s8 builtin_lneg(s8 a)
1428 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1431 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1432 s8 builtin_lmul(s8 a, s8 b)
1444 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1447 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1448 s8 builtin_ldiv(s8 a, s8 b)
1461 s8 builtin_lrem(s8 a, s8 b)
1473 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1476 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1477 s8 builtin_lshl(s8 a, s4 b)
1490 s8 builtin_lshr(s8 a, s4 b)
1503 s8 builtin_lushr(s8 a, s4 b)
1508 c = ((u8) a) >> (b & 63);
1515 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1518 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1519 s8 builtin_land(s8 a, s8 b)
1532 s8 builtin_lor(s8 a, s8 b)
1545 s8 builtin_lxor(s8 a, s8 b)
1557 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1560 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1561 s4 builtin_lcmp(s8 a, s8 b)
1575 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1578 /* functions for unsupported floating instructions ****************************/
1580 /* used to convert FLT_xxx defines into float values */
1582 static inline float intBitsToFloat(s4 i)
1591 /* used to convert DBL_xxx defines into double values */
1593 static inline float longBitsToDouble(s8 l)
1603 float builtin_fadd(float a, float b)
1605 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1606 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1617 if (copysignf(1.0, a) == copysignf(1.0, b))
1620 return intBitsToFloat(FLT_NAN);
1626 float builtin_fsub(float a, float b)
1628 return builtin_fadd(a, builtin_fneg(b));
1632 float builtin_fmul(float a, float b)
1634 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1635 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1637 if (finitef(b)) return a * b;
1639 if (a == 0) return intBitsToFloat(FLT_NAN);
1640 else return copysignf(b, copysignf(1.0, b)*a);
1645 if (b == 0) return intBitsToFloat(FLT_NAN);
1646 else return copysignf(a, copysignf(1.0, a)*b);
1649 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1655 /* builtin_ddiv ****************************************************************
1657 Implementation as described in VM Spec.
1659 *******************************************************************************/
1661 float builtin_fdiv(float a, float b)
1665 /* If neither value1' nor value2' is NaN, the sign of the result */
1666 /* is positive if both values have the same sign, negative if the */
1667 /* values have different signs. */
1673 /* If either value1' or value2' is NaN, the result is NaN. */
1675 return intBitsToFloat(FLT_NAN);
1678 /* Division of a finite value by an infinity results in a */
1679 /* signed zero, with the sign-producing rule just given. */
1681 /* is sign equal? */
1683 if (copysignf(1.0, a) == copysignf(1.0, b))
1692 /* If either value1' or value2' is NaN, the result is NaN. */
1694 return intBitsToFloat(FLT_NAN);
1696 } else if (finitef(b)) {
1697 /* Division of an infinity by a finite value results in a signed */
1698 /* infinity, with the sign-producing rule just given. */
1700 /* is sign equal? */
1702 if (copysignf(1.0, a) == copysignf(1.0, b))
1703 return intBitsToFloat(FLT_POSINF);
1705 return intBitsToFloat(FLT_NEGINF);
1708 /* Division of an infinity by an infinity results in NaN. */
1710 return intBitsToFloat(FLT_NAN);
1716 float builtin_fneg(float a)
1718 if (isnanf(a)) return a;
1720 if (finitef(a)) return -a;
1721 else return copysignf(a, -copysignf(1.0, a));
1724 #endif /* !SUPPORT_FLOAT */
1727 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1728 s4 builtin_fcmpl(float a, float b)
1736 if (!finitef(a) || !finitef(b)) {
1737 a = finitef(a) ? 0 : copysignf(1.0, a);
1738 b = finitef(b) ? 0 : copysignf(1.0, b);
1751 s4 builtin_fcmpg(float a, float b)
1753 if (isnanf(a)) return 1;
1754 if (isnanf(b)) return 1;
1755 if (!finitef(a) || !finitef(b)) {
1756 a = finitef(a) ? 0 : copysignf(1.0, a);
1757 b = finitef(b) ? 0 : copysignf(1.0, b);
1759 if (a > b) return 1;
1760 if (a == b) return 0;
1763 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1766 float builtin_frem(float a, float b)
1772 /* functions for unsupported double instructions ******************************/
1775 double builtin_dadd(double a, double b)
1777 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1778 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1780 if (finite(b)) return a + b;
1784 if (finite(b)) return a;
1786 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1787 else return longBitsToDouble(DBL_NAN);
1793 double builtin_dsub(double a, double b)
1795 return builtin_dadd(a, builtin_dneg(b));
1799 double builtin_dmul(double a, double b)
1801 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1802 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1804 if (finite(b)) return a * b;
1806 if (a == 0) return longBitsToDouble(DBL_NAN);
1807 else return copysign(b, copysign(1.0, b) * a);
1812 if (b == 0) return longBitsToDouble(DBL_NAN);
1813 else return copysign(a, copysign(1.0, a) * b);
1816 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1822 /* builtin_ddiv ****************************************************************
1824 Implementation as described in VM Spec.
1826 *******************************************************************************/
1828 double builtin_ddiv(double a, double b)
1832 /* If neither value1' nor value2' is NaN, the sign of the result */
1833 /* is positive if both values have the same sign, negative if the */
1834 /* values have different signs. */
1840 /* If either value1' or value2' is NaN, the result is NaN. */
1842 return longBitsToDouble(DBL_NAN);
1845 /* Division of a finite value by an infinity results in a */
1846 /* signed zero, with the sign-producing rule just given. */
1848 /* is sign equal? */
1850 if (copysign(1.0, a) == copysign(1.0, b))
1859 /* If either value1' or value2' is NaN, the result is NaN. */
1861 return longBitsToDouble(DBL_NAN);
1863 } else if (finite(b)) {
1864 /* Division of an infinity by a finite value results in a signed */
1865 /* infinity, with the sign-producing rule just given. */
1867 /* is sign equal? */
1869 if (copysign(1.0, a) == copysign(1.0, b))
1870 return longBitsToDouble(DBL_POSINF);
1872 return longBitsToDouble(DBL_NEGINF);
1875 /* Division of an infinity by an infinity results in NaN. */
1877 return longBitsToDouble(DBL_NAN);
1883 /* builtin_dneg ****************************************************************
1885 Implemented as described in VM Spec.
1887 *******************************************************************************/
1889 double builtin_dneg(double a)
1892 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1899 /* If the operand is a zero, the result is the zero of opposite */
1905 /* If the operand is an infinity, the result is the infinity of */
1906 /* opposite sign. */
1908 return copysign(a, -copysign(1.0, a));
1912 #endif /* !SUPPORT_DOUBLE */
1915 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1916 s4 builtin_dcmpl(double a, double b)
1924 if (!finite(a) || !finite(b)) {
1925 a = finite(a) ? 0 : copysign(1.0, a);
1926 b = finite(b) ? 0 : copysign(1.0, b);
1939 s4 builtin_dcmpg(double a, double b)
1947 if (!finite(a) || !finite(b)) {
1948 a = finite(a) ? 0 : copysign(1.0, a);
1949 b = finite(b) ? 0 : copysign(1.0, b);
1960 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1963 double builtin_drem(double a, double b)
1969 /* conversion operations ******************************************************/
1972 s8 builtin_i2l(s4 i)
1984 s4 builtin_l2i(s8 l)
1995 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1996 float builtin_i2f(s4 a)
1998 float f = (float) a;
2001 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2004 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2005 double builtin_i2d(s4 a)
2007 double d = (double) a;
2010 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2013 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2014 float builtin_l2f(s8 a)
2017 float f = (float) a;
2023 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2026 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2027 double builtin_l2d(s8 a)
2030 double d = (double) a;
2036 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2039 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2040 s4 builtin_f2i(float a)
2044 i = builtin_d2i((double) a);
2055 if (a < (-2147483648))
2056 return (-2147483648);
2059 f = copysignf((float) 1.0, a);
2062 return (-2147483648); */
2064 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2067 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2068 s8 builtin_f2l(float a)
2072 l = builtin_d2l((double) a);
2079 if (a > 9223372036854775807L)
2080 return 9223372036854775807L;
2081 if (a < (-9223372036854775808L))
2082 return (-9223372036854775808L);
2087 f = copysignf((float) 1.0, a);
2089 return 9223372036854775807L;
2090 return (-9223372036854775808L); */
2092 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2095 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2096 s4 builtin_d2i(double a)
2101 if (a >= 2147483647)
2103 if (a <= (-2147483647-1))
2104 return (-2147483647-1);
2109 d = copysign(1.0, a);
2112 return (-2147483647-1);
2114 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2117 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2118 s8 builtin_d2l(double a)
2123 if (a >= 9223372036854775807LL)
2124 return 9223372036854775807LL;
2125 if (a <= (-9223372036854775807LL-1))
2126 return (-9223372036854775807LL-1);
2131 d = copysign(1.0, a);
2133 return 9223372036854775807LL;
2134 return (-9223372036854775807LL-1);
2136 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2139 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2140 double builtin_f2d(float a)
2142 if (finitef(a)) return (double) a;
2145 return longBitsToDouble(DBL_NAN);
2147 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2151 float builtin_d2f(double a)
2157 return intBitsToFloat(FLT_NAN);
2159 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2162 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2165 /*============================================================================*/
2166 /* AUTOMATICALLY REPLACED FUNCTIONS */
2167 /*============================================================================*/
2169 /* builtin_arraycopy ***********************************************************
2171 Builtin for java.lang.System.arraycopy.
2173 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2175 *******************************************************************************/
2177 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2178 java_handle_t *dest, s4 destStart, s4 len)
2180 arraydescriptor *sdesc;
2181 arraydescriptor *ddesc;
2184 if ((src == NULL) || (dest == NULL)) {
2185 exceptions_throw_nullpointerexception();
2189 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2190 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2192 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2193 exceptions_throw_arraystoreexception();
2197 // Check if offsets and length are positive.
2198 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2199 exceptions_throw_arrayindexoutofboundsexception();
2203 // Check if ranges are valid.
2204 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2205 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2206 exceptions_throw_arrayindexoutofboundsexception();
2215 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2216 /* We copy primitive values or references of exactly the same type */
2218 s4 dataoffset = sdesc->dataoffset;
2219 s4 componentsize = sdesc->componentsize;
2221 LLNI_CRITICAL_START;
2223 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2224 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2225 u1, (size_t) len * componentsize);
2230 /* We copy references of different type */
2232 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2233 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2235 if (destStart <= srcStart) {
2236 for (i = 0; i < len; i++) {
2239 o = array_objectarray_element_get(oas, srcStart + i);
2241 if (!builtin_canstore(oad, o))
2244 array_objectarray_element_set(oad, destStart + i, o);
2248 /* XXX this does not completely obey the specification!
2249 If an exception is thrown only the elements above the
2250 current index have been copied. The specification
2251 requires that only the elements *below* the current
2252 index have been copied before the throw. */
2254 for (i = len - 1; i >= 0; i--) {
2257 o = array_objectarray_element_get(oas, srcStart + i);
2259 if (!builtin_canstore(oad, o))
2262 array_objectarray_element_set(oad, destStart + i, o);
2269 /* builtin_nanotime ************************************************************
2271 Return the current time in nanoseconds.
2273 *******************************************************************************/
2275 s8 builtin_nanotime(void)
2280 if (gettimeofday(&tv, NULL) == -1)
2281 vm_abort("gettimeofday failed: %s", strerror(errno));
2283 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2285 return usecs * 1000;
2289 /* builtin_currenttimemillis ***************************************************
2291 Return the current time in milliseconds.
2293 *******************************************************************************/
2295 s8 builtin_currenttimemillis(void)
2299 msecs = builtin_nanotime() / 1000 / 1000;
2305 /* builtin_clone ***************************************************************
2307 Function for cloning objects or arrays.
2309 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2311 *******************************************************************************/
2313 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2315 arraydescriptor *ad;
2318 java_handle_t *co; /* cloned object header */
2320 /* get the array descriptor */
2322 ad = LLNI_vftbl_direct(o)->arraydesc;
2324 /* we are cloning an array */
2327 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2329 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2334 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2335 /* XXX this is only a dirty hack to make Boehm work with handles */
2337 co = LLNI_WRAP((java_object_t *) co);
2340 LLNI_CRITICAL_START;
2342 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2344 #if defined(ENABLE_GC_CACAO)
2345 heap_init_objectheader(LLNI_DIRECT(co), size);
2348 #if defined(ENABLE_THREADS)
2349 lock_init_object_lock(LLNI_DIRECT(co));
2357 /* we are cloning a non-array */
2359 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2360 exceptions_throw_clonenotsupportedexception();
2364 /* get the class of the object */
2366 LLNI_class_get(o, c);
2368 /* create new object */
2370 co = builtin_new(c);
2375 LLNI_CRITICAL_START;
2377 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2379 #if defined(ENABLE_GC_CACAO)
2380 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2383 #if defined(ENABLE_THREADS)
2384 lock_init_object_lock(LLNI_DIRECT(co));
2393 #if defined(ENABLE_CYCLES_STATS)
2394 void builtin_print_cycles_stats(FILE *file)
2396 fprintf(file,"builtin cylce count statistics:\n");
2398 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2399 CYCLES_STATS_PRINT(builtin_new ,file);
2403 #endif /* defined(ENABLE_CYCLES_STATS) */
2406 #if defined(ENABLE_VMLOG)
2408 #include <vmlog_cacao.c>
2413 * These are local overrides for various environment variables in Emacs.
2414 * Please do not remove this and leave it at the end of the file, where
2415 * Emacs will automagically detect them.
2416 * ---------------------------------------------------------------------
2419 * indent-tabs-mode: t
2423 * vim:noexpandtab:sw=4:ts=4: