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;
113 /* mark start of dump memory area */
117 /* create a new descriptor pool */
119 descpool = descriptor_pool_new(class_java_lang_Object);
121 /* add some entries we need */
123 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
126 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
129 /* first add all descriptors to the pool */
131 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
132 bte->name = utf_new_char(bte->cname);
133 bte->descriptor = utf_new_char(bte->cdescriptor);
135 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
136 /* release dump area */
144 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
145 bte->descriptor = utf_new_char(bte->cdescriptor);
147 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
153 for (bte = builtintable_function; bte->fp != NULL; bte++) {
154 bte->classname = utf_new_char(bte->cclassname);
155 bte->name = utf_new_char(bte->cname);
156 bte->descriptor = utf_new_char(bte->cdescriptor);
158 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
164 /* create the class reference table */
166 (void) descriptor_pool_create_classrefs(descpool, NULL);
168 /* allocate space for the parsed descriptors */
170 descriptor_pool_alloc_parsed_descriptors(descpool);
172 /* Now parse all descriptors. NOTE: builtin-functions are treated
173 like static methods (no `this' pointer). */
175 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
177 descriptor_pool_parse_method_descriptor(descpool,
179 ACC_STATIC | ACC_METHOD_BUILTIN,
182 /* generate a builtin stub if we need one */
184 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
185 m = method_new_builtin(bte);
186 BuiltinStub::generate(m, bte);
190 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
192 descriptor_pool_parse_method_descriptor(descpool,
194 ACC_STATIC | ACC_METHOD_BUILTIN,
197 /* no stubs should be needed for this table */
199 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
202 for (bte = builtintable_function; bte->fp != NULL; bte++) {
204 descriptor_pool_parse_method_descriptor(descpool,
206 ACC_STATIC | ACC_METHOD_BUILTIN,
209 /* generate a builtin stub if we need one */
211 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
212 m = method_new_builtin(bte);
213 BuiltinStub::generate(m, bte);
217 /* release dump area */
225 /* builtintable_comparator *****************************************************
227 qsort comparator for the automatic builtin table.
229 *******************************************************************************/
231 static int builtintable_comparator(const void *a, const void *b)
233 builtintable_entry *bte1;
234 builtintable_entry *bte2;
236 bte1 = (builtintable_entry *) a;
237 bte2 = (builtintable_entry *) b;
239 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
243 /* builtintable_sort_automatic *************************************************
245 Sorts the automatic builtin table.
247 *******************************************************************************/
249 static void builtintable_sort_automatic(void)
253 /* calculate table size statically (`- 1' comment see builtintable.inc) */
255 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
257 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
258 builtintable_comparator);
262 /* builtin_init ****************************************************************
264 Initialize the global table of builtin functions.
266 *******************************************************************************/
268 bool builtin_init(void)
270 TRACESUBSYSTEMINITIALIZATION("builtin_init");
272 /* initialize the builtin tables */
274 if (!builtintable_init())
277 /* sort builtin tables */
279 builtintable_sort_automatic();
285 /* builtintable_get_internal ***************************************************
287 Finds an entry in the builtintable for internal functions and
288 returns the a pointer to the structure.
290 *******************************************************************************/
292 builtintable_entry *builtintable_get_internal(functionptr fp)
294 builtintable_entry *bte;
296 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
305 /* builtintable_get_automatic **************************************************
307 Finds an entry in the builtintable for functions which are replaced
308 automatically and returns the a pointer to the structure.
310 *******************************************************************************/
312 builtintable_entry *builtintable_get_automatic(s4 opcode)
314 builtintable_entry *first;
315 builtintable_entry *last;
316 builtintable_entry *middle;
320 /* calculate table size statically (`- 1' comment see builtintable.inc) */
322 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
324 first = builtintable_automatic;
325 last = builtintable_automatic + entries;
327 while (entries > 0) {
329 middle = first + half;
331 if (middle->opcode < opcode) {
339 return (first != last ? first : NULL);
343 /* builtintable_replace_function ***********************************************
347 *******************************************************************************/
349 #if defined(ENABLE_JIT)
350 bool builtintable_replace_function(void *iptr_)
353 builtintable_entry *bte;
356 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
358 /* get name and descriptor of the function */
361 case ICMD_INVOKESTATIC:
362 /* The instruction MUST be resolved, otherwise we run into
363 lazy loading troubles. Anyway, we should/can only replace
364 very VM-close functions. */
366 if (INSTRUCTION_IS_UNRESOLVED(iptr))
369 mr = iptr->sx.s23.s3.fmiref;
376 /* search the function table */
378 for (bte = builtintable_function; bte->fp != NULL; bte++) {
379 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
380 (mr->name == bte->name) &&
381 (mr->descriptor == bte->descriptor)) {
383 /* set the values in the instruction */
385 iptr->opc = bte->opcode;
386 iptr->sx.s23.s3.bte = bte;
388 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
389 iptr->flags.bits |= INS_FLAG_CHECK;
391 iptr->flags.bits &= ~INS_FLAG_CHECK;
399 #endif /* defined(ENABLE_JIT) */
402 /*============================================================================*/
403 /* INTERNAL BUILTIN FUNCTIONS */
404 /*============================================================================*/
406 /* builtin_instanceof **********************************************************
408 Checks if an object is an instance of some given class (or subclass
409 of that class). If class is an interface, checks if the interface
413 1......o is an instance of class or implements the interface
414 0......otherwise or if o == NULL
416 NOTE: This builtin can be called from NATIVE code only.
418 *******************************************************************************/
420 bool builtin_instanceof(java_handle_t *o, classinfo *c)
427 LLNI_class_get(o, oc);
429 return class_isanysubclass(oc, c);
434 /* builtin_checkcast ***********************************************************
436 The same as builtin_instanceof but with the exception
437 that 1 is returned when (o == NULL).
439 NOTE: This builtin can be called from NATIVE code only.
441 *******************************************************************************/
443 bool builtin_checkcast(java_handle_t *o, classinfo *c)
450 LLNI_class_get(o, oc);
452 if (class_isanysubclass(oc, c))
459 /* builtin_descriptorscompatible ***********************************************
461 Checks if two array type descriptors are assignment compatible.
464 1......target = desc is possible
467 *******************************************************************************/
469 static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
474 if (desc->arraytype != target->arraytype)
477 if (desc->arraytype != ARRAYTYPE_OBJECT)
480 /* {both arrays are arrays of references} */
482 if (desc->dimension == target->dimension) {
483 if (!desc->elementvftbl)
485 /* an array which contains elements of interface types is
486 allowed to be casted to Object (JOWENN)*/
488 if ((desc->elementvftbl->baseval < 0) &&
489 (target->elementvftbl->baseval == 1))
492 return class_isanysubclass(desc->elementvftbl->clazz,
493 target->elementvftbl->clazz);
496 if (desc->dimension < target->dimension)
499 /* {desc has higher dimension than target} */
501 return class_isanysubclass(pseudo_class_Arraystub,
502 target->elementvftbl->clazz);
506 /* builtin_arraycheckcast ******************************************************
508 Checks if an object is really a subtype of the requested array
509 type. The object has to be an array to begin with. For simple
510 arrays (int, short, double, etc.) the types have to match exactly.
511 For arrays of objects, the type of elements in the array has to be
512 a subtype (or the same type) of the requested element type. For
513 arrays of arrays (which in turn can again be arrays of arrays), the
514 types at the lowest level have to satisfy the corresponding sub
517 NOTE: This is a FAST builtin and can be called from JIT code only.
519 *******************************************************************************/
521 bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
523 arraydescriptor *desc;
528 desc = o->vftbl->arraydesc;
533 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
537 /* builtin_fast_arrayinstanceof ************************************************
539 NOTE: This is a FAST builtin and can be called from JIT code only.
541 *******************************************************************************/
543 bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
548 return builtin_fast_arraycheckcast(o, targetclass);
552 /* builtin_arrayinstanceof *****************************************************
554 NOTE: This builtin can be called from NATIVE code only.
556 *******************************************************************************/
558 bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
564 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
572 /* builtin_throw_exception *****************************************************
574 Sets the exception pointer with the thrown exception and prints some
575 debugging information.
577 NOTE: This is a FAST builtin and can be called from JIT code,
578 or from asm_vm_call_method.
580 *******************************************************************************/
582 void *builtin_throw_exception(java_object_t *xptr)
585 /* print exception trace */
587 if (opt_TraceExceptions)
588 trace_exception_builtin(xptr);
589 #endif /* !defined(NDEBUG) */
591 /* actually set the exception */
593 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
595 /* Return a NULL pointer. This is required for vm_call_method to
596 check for an exception. This is for convenience. */
602 /* builtin_retrieve_exception **************************************************
604 Gets and clears the exception pointer of the current thread.
607 the exception object, or NULL if no exception was thrown.
609 NOTE: This is a FAST builtin and can be called from JIT code,
610 or from the signal handlers.
612 *******************************************************************************/
614 java_object_t *builtin_retrieve_exception(void)
619 /* actually get and clear the exception */
621 h = exceptions_get_and_clear_exception();
628 /* builtin_canstore ************************************************************
630 Checks, if an object can be stored in an array.
634 0......otherwise (throws an ArrayStoreException)
636 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
638 *******************************************************************************/
640 bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
646 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
650 /* if not possible, throw an exception */
653 exceptions_throw_arraystoreexception();
659 /* builtin_fast_canstore *******************************************************
661 Checks, if an object can be stored in an array.
665 0......otherwise (no exception thrown!)
667 NOTE: This is a FAST builtin and can be called from JIT code only.
669 *******************************************************************************/
671 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
673 arraydescriptor *desc;
674 arraydescriptor *valuedesc;
675 vftbl_t *componentvftbl;
684 /* The following is guaranteed (by verifier checks):
686 * *) oa->...vftbl->arraydesc != NULL
687 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
688 * *) o->vftbl is not an interface vftbl
691 desc = oa->header.objheader.vftbl->arraydesc;
692 componentvftbl = desc->componentvftbl;
693 valuevftbl = o->vftbl;
694 valuedesc = valuevftbl->arraydesc;
696 if ((desc->dimension - 1) == 0) {
697 /* {oa is a one-dimensional array} */
698 /* {oa is an array of references} */
700 if (valuevftbl == componentvftbl)
703 linker_classrenumber_mutex->lock();
705 baseval = componentvftbl->baseval;
708 /* an array of interface references */
710 result = ((valuevftbl->interfacetablelength > -baseval) &&
711 (valuevftbl->interfacetable[baseval] != NULL));
714 diffval = valuevftbl->baseval - componentvftbl->baseval;
715 result = diffval <= (uint32_t) componentvftbl->diffval;
718 linker_classrenumber_mutex->unlock();
720 else if (valuedesc == NULL) {
721 /* {oa has dimension > 1} */
722 /* {componentvftbl->arraydesc != NULL} */
724 /* check if o is an array */
729 /* {o is an array} */
731 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
740 /* This is an optimized version where a is guaranteed to be one-dimensional */
741 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
743 arraydescriptor *desc;
744 vftbl_t *elementvftbl;
753 /* The following is guaranteed (by verifier checks):
755 * *) a->...vftbl->arraydesc != NULL
756 * *) a->...vftbl->arraydesc->elementvftbl != NULL
757 * *) a->...vftbl->arraydesc->dimension == 1
758 * *) o->vftbl is not an interface vftbl
761 desc = a->header.objheader.vftbl->arraydesc;
762 elementvftbl = desc->elementvftbl;
763 valuevftbl = o->vftbl;
765 /* {a is a one-dimensional array} */
767 if (valuevftbl == elementvftbl)
770 linker_classrenumber_mutex->lock();
772 baseval = elementvftbl->baseval;
775 /* an array of interface references */
776 result = ((valuevftbl->interfacetablelength > -baseval) &&
777 (valuevftbl->interfacetable[baseval] != NULL));
780 diffval = valuevftbl->baseval - elementvftbl->baseval;
781 result = diffval <= (uint32_t) elementvftbl->diffval;
784 linker_classrenumber_mutex->unlock();
790 /* This is an optimized version where a is guaranteed to be a
791 * one-dimensional array of a class type */
792 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
794 vftbl_t *elementvftbl;
802 /* The following is guaranteed (by verifier checks):
804 * *) a->...vftbl->arraydesc != NULL
805 * *) a->...vftbl->arraydesc->elementvftbl != NULL
806 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
807 * *) a->...vftbl->arraydesc->dimension == 1
808 * *) o->vftbl is not an interface vftbl
811 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
812 valuevftbl = o->vftbl;
814 /* {a is a one-dimensional array} */
816 if (valuevftbl == elementvftbl)
819 linker_classrenumber_mutex->lock();
821 diffval = valuevftbl->baseval - elementvftbl->baseval;
822 result = diffval <= (uint32_t) elementvftbl->diffval;
824 linker_classrenumber_mutex->unlock();
830 /* builtin_new *****************************************************************
832 Creates a new instance of class c on the heap.
835 pointer to the object, or NULL if no memory is available
837 NOTE: This builtin can be called from NATIVE code only.
839 *******************************************************************************/
841 java_handle_t *builtin_new(classinfo *c)
844 #if defined(ENABLE_RT_TIMING)
845 struct timespec time_start, time_end;
847 #if defined(ENABLE_CYCLES_STATS)
848 u8 cycles_start, cycles_end;
851 RT_TIMING_GET_TIME(time_start);
852 CYCLES_STATS_GET(cycles_start);
854 /* is the class loaded */
856 assert(c->state & CLASS_LOADED);
858 /* check if we can instantiate this class */
860 if (c->flags & ACC_ABSTRACT) {
861 exceptions_throw_instantiationerror(c);
865 /* is the class linked */
867 if (!(c->state & CLASS_LINKED))
871 if (!(c->state & CLASS_INITIALIZED)) {
874 log_message_class("Initialize class (from builtin_new): ", c);
877 if (!initialize_class(c))
881 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
887 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
888 /* XXX this is only a dirty hack to make Boehm work with handles */
890 o = LLNI_WRAP((java_object_t *) o);
893 LLNI_vftbl_direct(o) = c->vftbl;
895 #if defined(ENABLE_THREADS)
896 lock_init_object_lock(LLNI_DIRECT(o));
899 CYCLES_STATS_GET(cycles_end);
900 RT_TIMING_GET_TIME(time_end);
902 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
903 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
908 #if defined(ENABLE_ESCAPE_REASON)
909 java_handle_t *builtin_escape_reason_new(classinfo *c) {
910 print_escape_reasons();
911 return builtin_java_new(c);
915 #if defined(ENABLE_TLH)
916 java_handle_t *builtin_tlh_new(classinfo *c)
919 # if defined(ENABLE_RT_TIMING)
920 struct timespec time_start, time_end;
922 # if defined(ENABLE_CYCLES_STATS)
923 u8 cycles_start, cycles_end;
926 RT_TIMING_GET_TIME(time_start);
927 CYCLES_STATS_GET(cycles_start);
929 /* is the class loaded */
931 assert(c->state & CLASS_LOADED);
933 /* check if we can instantiate this class */
935 if (c->flags & ACC_ABSTRACT) {
936 exceptions_throw_instantiationerror(c);
940 /* is the class linked */
942 if (!(c->state & CLASS_LINKED))
946 if (!(c->state & CLASS_INITIALIZED)) {
947 # if !defined(NDEBUG)
949 log_message_class("Initialize class (from builtin_new): ", c);
952 if (!initialize_class(c))
957 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
962 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
969 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
970 /* XXX this is only a dirty hack to make Boehm work with handles */
972 o = LLNI_WRAP((java_object_t *) o);
975 LLNI_vftbl_direct(o) = c->vftbl;
977 # if defined(ENABLE_THREADS)
978 lock_init_object_lock(LLNI_DIRECT(o));
981 CYCLES_STATS_GET(cycles_end);
982 RT_TIMING_GET_TIME(time_end);
985 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
986 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
994 /* builtin_java_new ************************************************************
996 NOTE: This is a SLOW builtin and can be called from JIT code only.
998 *******************************************************************************/
1000 java_handle_t *builtin_java_new(java_handle_t *clazz)
1002 return builtin_new(LLNI_classinfo_unwrap(clazz));
1006 /* builtin_fast_new ************************************************************
1008 Creates a new instance of class c on the heap.
1011 pointer to the object, or NULL if no fast return
1012 is possible for any reason.
1014 NOTE: This is a FAST builtin and can be called from JIT code only.
1016 *******************************************************************************/
1018 java_object_t *builtin_fast_new(classinfo *c)
1021 #if defined(ENABLE_RT_TIMING)
1022 struct timespec time_start, time_end;
1024 #if defined(ENABLE_CYCLES_STATS)
1025 u8 cycles_start, cycles_end;
1028 RT_TIMING_GET_TIME(time_start);
1029 CYCLES_STATS_GET(cycles_start);
1031 /* is the class loaded */
1033 assert(c->state & CLASS_LOADED);
1035 /* check if we can instantiate this class */
1037 if (c->flags & ACC_ABSTRACT)
1040 /* is the class linked */
1042 if (!(c->state & CLASS_LINKED))
1045 if (!(c->state & CLASS_INITIALIZED))
1048 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1049 c->finalizer, false);
1054 o->vftbl = c->vftbl;
1056 #if defined(ENABLE_THREADS)
1057 lock_init_object_lock(o);
1060 CYCLES_STATS_GET(cycles_end);
1061 RT_TIMING_GET_TIME(time_end);
1063 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1064 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1070 /* builtin_newarray ************************************************************
1072 Creates an array with the given vftbl on the heap. This function
1073 takes as class argument an array class.
1076 pointer to the array or NULL if no memory is available
1078 NOTE: This builtin can be called from NATIVE code only.
1080 *******************************************************************************/
1082 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1084 arraydescriptor *desc;
1089 #if defined(ENABLE_RT_TIMING)
1090 struct timespec time_start, time_end;
1093 RT_TIMING_GET_TIME(time_start);
1095 desc = arrayclass->vftbl->arraydesc;
1096 dataoffset = desc->dataoffset;
1097 componentsize = desc->componentsize;
1100 exceptions_throw_negativearraysizeexception();
1104 actualsize = dataoffset + size * componentsize;
1106 /* check for overflow */
1108 if (((u4) actualsize) < ((u4) size)) {
1109 exceptions_throw_outofmemoryerror();
1113 a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1118 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1119 /* XXX this is only a dirty hack to make Boehm work with handles */
1121 a = LLNI_WRAP((java_object_t *) a);
1124 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1126 #if defined(ENABLE_THREADS)
1127 lock_init_object_lock(LLNI_DIRECT(a));
1130 LLNI_array_size(a) = size;
1132 RT_TIMING_GET_TIME(time_end);
1133 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1139 /* builtin_java_newarray *******************************************************
1141 NOTE: This is a SLOW builtin and can be called from JIT code only.
1143 *******************************************************************************/
1145 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1147 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1151 /* builtin_anewarray ***********************************************************
1153 Creates an array of references to the given class type on the heap.
1156 pointer to the array or NULL if no memory is
1159 NOTE: This builtin can be called from NATIVE code only.
1161 *******************************************************************************/
1163 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1165 classinfo *arrayclass;
1167 /* is class loaded */
1169 assert(componentclass->state & CLASS_LOADED);
1171 /* is class linked */
1173 if (!(componentclass->state & CLASS_LINKED))
1174 if (!link_class(componentclass))
1177 arrayclass = class_array_of(componentclass, true);
1182 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1186 /* builtin_newarray_type ****************************************************
1188 Creates an array of [type]s on the heap.
1191 pointer to the array or NULL if no memory is available
1193 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1195 *******************************************************************************/
1197 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1198 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1200 return (java_handle_##type##array_t *) \
1201 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1204 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1205 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1206 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1207 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1208 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1209 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1210 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1211 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1214 /* builtin_multianewarray_intern ***********************************************
1216 Creates a multi-dimensional array on the heap. The dimensions are
1217 passed in an array of longs.
1220 n.............number of dimensions to create
1221 arrayclass....the array class
1222 dims..........array containing the size of each dimension to create
1225 pointer to the array or NULL if no memory is available
1227 ******************************************************************************/
1229 static java_handle_t *builtin_multianewarray_intern(int n,
1230 classinfo *arrayclass,
1235 classinfo *componentclass;
1238 /* create this dimension */
1240 size = (s4) dims[0];
1241 a = builtin_newarray(size, arrayclass);
1246 /* if this is the last dimension return */
1251 /* get the class of the components to create */
1253 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1255 /* The verifier guarantees that the dimension count is in the range. */
1257 /* create the component arrays */
1259 for (i = 0; i < size; i++) {
1261 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1262 /* we save an s4 to a s8 slot, 8-byte aligned */
1264 builtin_multianewarray_intern(n, componentclass, dims + 2);
1266 builtin_multianewarray_intern(n, componentclass, dims + 1);
1272 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1279 /* builtin_multianewarray ******************************************************
1281 Wrapper for builtin_multianewarray_intern which checks all
1282 dimensions before we start allocating.
1284 NOTE: This is a SLOW builtin and can be called from JIT code only.
1286 ******************************************************************************/
1288 java_handle_objectarray_t *builtin_multianewarray(int n,
1289 java_handle_t *arrayclazz,
1296 /* check all dimensions before doing anything */
1298 for (i = 0; i < n; i++) {
1299 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1300 /* we save an s4 to a s8 slot, 8-byte aligned */
1301 size = (s4) dims[i * 2];
1303 size = (s4) dims[i];
1307 exceptions_throw_negativearraysizeexception();
1312 c = LLNI_classinfo_unwrap(arrayclazz);
1314 /* now call the real function */
1316 return (java_handle_objectarray_t *)
1317 builtin_multianewarray_intern(n, c, dims);
1321 /* builtin_verbosecall_enter ***************************************************
1323 Print method call with arguments for -verbose:call.
1325 XXX: Remove mew once all archs use the new tracer!
1327 *******************************************************************************/
1329 #if !defined(NDEBUG)
1330 #ifdef TRACE_ARGS_NUM
1331 void builtin_verbosecall_enter(s8 a0, s8 a1,
1332 # if TRACE_ARGS_NUM >= 4
1335 # if TRACE_ARGS_NUM >= 6
1338 # if TRACE_ARGS_NUM == 8
1343 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1346 #endif /* !defined(NDEBUG) */
1349 /* builtin_verbosecall_exit ****************************************************
1351 Print method exit for -verbose:call.
1353 XXX: Remove mew once all archs use the new tracer!
1355 *******************************************************************************/
1357 #if !defined(NDEBUG)
1358 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1360 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1362 #endif /* !defined(NDEBUG) */
1365 /*============================================================================*/
1366 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1367 /*============================================================================*/
1369 /*********** Functions for integer divisions *****************************
1371 On some systems (eg. DEC ALPHA), integer division is not supported by the
1372 CPU. These helper functions implement the missing functionality.
1374 ******************************************************************************/
1376 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1377 s4 builtin_idiv(s4 a, s4 b)
1386 s4 builtin_irem(s4 a, s4 b)
1394 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1397 /* functions for long arithmetics **********************************************
1399 On systems where 64 bit Integers are not supported by the CPU,
1400 these functions are needed.
1402 ******************************************************************************/
1404 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1405 s8 builtin_ladd(s8 a, s8 b)
1418 s8 builtin_lsub(s8 a, s8 b)
1431 s8 builtin_lneg(s8 a)
1443 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1446 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1447 s8 builtin_lmul(s8 a, s8 b)
1459 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1462 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1463 s8 builtin_ldiv(s8 a, s8 b)
1476 s8 builtin_lrem(s8 a, s8 b)
1488 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1491 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1492 s8 builtin_lshl(s8 a, s4 b)
1505 s8 builtin_lshr(s8 a, s4 b)
1518 s8 builtin_lushr(s8 a, s4 b)
1523 c = ((u8) a) >> (b & 63);
1530 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1533 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1534 s8 builtin_land(s8 a, s8 b)
1547 s8 builtin_lor(s8 a, s8 b)
1560 s8 builtin_lxor(s8 a, s8 b)
1572 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1575 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1576 s4 builtin_lcmp(s8 a, s8 b)
1590 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1593 /* functions for unsupported floating instructions ****************************/
1595 /* used to convert FLT_xxx defines into float values */
1597 static inline float intBitsToFloat(s4 i)
1606 /* used to convert DBL_xxx defines into double values */
1608 static inline float longBitsToDouble(s8 l)
1618 float builtin_fadd(float a, float b)
1620 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1621 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1632 if (copysignf(1.0, a) == copysignf(1.0, b))
1635 return intBitsToFloat(FLT_NAN);
1641 float builtin_fsub(float a, float b)
1643 return builtin_fadd(a, builtin_fneg(b));
1647 float builtin_fmul(float a, float b)
1649 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1650 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1652 if (finitef(b)) return a * b;
1654 if (a == 0) return intBitsToFloat(FLT_NAN);
1655 else return copysignf(b, copysignf(1.0, b)*a);
1660 if (b == 0) return intBitsToFloat(FLT_NAN);
1661 else return copysignf(a, copysignf(1.0, a)*b);
1664 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1670 /* builtin_ddiv ****************************************************************
1672 Implementation as described in VM Spec.
1674 *******************************************************************************/
1676 float builtin_fdiv(float a, float b)
1680 /* If neither value1' nor value2' is NaN, the sign of the result */
1681 /* is positive if both values have the same sign, negative if the */
1682 /* values have different signs. */
1688 /* If either value1' or value2' is NaN, the result is NaN. */
1690 return intBitsToFloat(FLT_NAN);
1693 /* Division of a finite value by an infinity results in a */
1694 /* signed zero, with the sign-producing rule just given. */
1696 /* is sign equal? */
1698 if (copysignf(1.0, a) == copysignf(1.0, b))
1707 /* If either value1' or value2' is NaN, the result is NaN. */
1709 return intBitsToFloat(FLT_NAN);
1711 } else if (finitef(b)) {
1712 /* Division of an infinity by a finite value results in a signed */
1713 /* infinity, with the sign-producing rule just given. */
1715 /* is sign equal? */
1717 if (copysignf(1.0, a) == copysignf(1.0, b))
1718 return intBitsToFloat(FLT_POSINF);
1720 return intBitsToFloat(FLT_NEGINF);
1723 /* Division of an infinity by an infinity results in NaN. */
1725 return intBitsToFloat(FLT_NAN);
1731 float builtin_fneg(float a)
1733 if (isnanf(a)) return a;
1735 if (finitef(a)) return -a;
1736 else return copysignf(a, -copysignf(1.0, a));
1739 #endif /* !SUPPORT_FLOAT */
1742 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1743 s4 builtin_fcmpl(float a, float b)
1751 if (!finitef(a) || !finitef(b)) {
1752 a = finitef(a) ? 0 : copysignf(1.0, a);
1753 b = finitef(b) ? 0 : copysignf(1.0, b);
1766 s4 builtin_fcmpg(float a, float b)
1768 if (isnanf(a)) return 1;
1769 if (isnanf(b)) return 1;
1770 if (!finitef(a) || !finitef(b)) {
1771 a = finitef(a) ? 0 : copysignf(1.0, a);
1772 b = finitef(b) ? 0 : copysignf(1.0, b);
1774 if (a > b) return 1;
1775 if (a == b) return 0;
1778 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1781 float builtin_frem(float a, float b)
1787 /* functions for unsupported double instructions ******************************/
1790 double builtin_dadd(double a, double b)
1792 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1793 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1795 if (finite(b)) return a + b;
1799 if (finite(b)) return a;
1801 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1802 else return longBitsToDouble(DBL_NAN);
1808 double builtin_dsub(double a, double b)
1810 return builtin_dadd(a, builtin_dneg(b));
1814 double builtin_dmul(double a, double b)
1816 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1817 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1819 if (finite(b)) return a * b;
1821 if (a == 0) return longBitsToDouble(DBL_NAN);
1822 else return copysign(b, copysign(1.0, b) * a);
1827 if (b == 0) return longBitsToDouble(DBL_NAN);
1828 else return copysign(a, copysign(1.0, a) * b);
1831 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1837 /* builtin_ddiv ****************************************************************
1839 Implementation as described in VM Spec.
1841 *******************************************************************************/
1843 double builtin_ddiv(double a, double b)
1847 /* If neither value1' nor value2' is NaN, the sign of the result */
1848 /* is positive if both values have the same sign, negative if the */
1849 /* values have different signs. */
1855 /* If either value1' or value2' is NaN, the result is NaN. */
1857 return longBitsToDouble(DBL_NAN);
1860 /* Division of a finite value by an infinity results in a */
1861 /* signed zero, with the sign-producing rule just given. */
1863 /* is sign equal? */
1865 if (copysign(1.0, a) == copysign(1.0, b))
1874 /* If either value1' or value2' is NaN, the result is NaN. */
1876 return longBitsToDouble(DBL_NAN);
1878 } else if (finite(b)) {
1879 /* Division of an infinity by a finite value results in a signed */
1880 /* infinity, with the sign-producing rule just given. */
1882 /* is sign equal? */
1884 if (copysign(1.0, a) == copysign(1.0, b))
1885 return longBitsToDouble(DBL_POSINF);
1887 return longBitsToDouble(DBL_NEGINF);
1890 /* Division of an infinity by an infinity results in NaN. */
1892 return longBitsToDouble(DBL_NAN);
1898 /* builtin_dneg ****************************************************************
1900 Implemented as described in VM Spec.
1902 *******************************************************************************/
1904 double builtin_dneg(double a)
1907 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1914 /* If the operand is a zero, the result is the zero of opposite */
1920 /* If the operand is an infinity, the result is the infinity of */
1921 /* opposite sign. */
1923 return copysign(a, -copysign(1.0, a));
1927 #endif /* !SUPPORT_DOUBLE */
1930 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1931 s4 builtin_dcmpl(double a, double b)
1939 if (!finite(a) || !finite(b)) {
1940 a = finite(a) ? 0 : copysign(1.0, a);
1941 b = finite(b) ? 0 : copysign(1.0, b);
1954 s4 builtin_dcmpg(double a, double b)
1962 if (!finite(a) || !finite(b)) {
1963 a = finite(a) ? 0 : copysign(1.0, a);
1964 b = finite(b) ? 0 : copysign(1.0, b);
1975 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1978 double builtin_drem(double a, double b)
1984 /* conversion operations ******************************************************/
1987 s8 builtin_i2l(s4 i)
1999 s4 builtin_l2i(s8 l)
2010 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2011 float builtin_i2f(s4 a)
2013 float f = (float) a;
2016 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2019 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2020 double builtin_i2d(s4 a)
2022 double d = (double) a;
2025 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2028 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2029 float builtin_l2f(s8 a)
2032 float f = (float) a;
2038 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2041 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2042 double builtin_l2d(s8 a)
2045 double d = (double) a;
2051 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2054 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2055 s4 builtin_f2i(float a)
2059 i = builtin_d2i((double) a);
2070 if (a < (-2147483648))
2071 return (-2147483648);
2074 f = copysignf((float) 1.0, a);
2077 return (-2147483648); */
2079 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2082 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2083 s8 builtin_f2l(float a)
2087 l = builtin_d2l((double) a);
2094 if (a > 9223372036854775807L)
2095 return 9223372036854775807L;
2096 if (a < (-9223372036854775808L))
2097 return (-9223372036854775808L);
2102 f = copysignf((float) 1.0, a);
2104 return 9223372036854775807L;
2105 return (-9223372036854775808L); */
2107 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2110 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2111 s4 builtin_d2i(double a)
2116 if (a >= 2147483647)
2118 if (a <= (-2147483647-1))
2119 return (-2147483647-1);
2124 d = copysign(1.0, a);
2127 return (-2147483647-1);
2129 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2132 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2133 s8 builtin_d2l(double a)
2138 if (a >= 9223372036854775807LL)
2139 return 9223372036854775807LL;
2140 if (a <= (-9223372036854775807LL-1))
2141 return (-9223372036854775807LL-1);
2146 d = copysign(1.0, a);
2148 return 9223372036854775807LL;
2149 return (-9223372036854775807LL-1);
2151 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2154 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2155 double builtin_f2d(float a)
2157 if (finitef(a)) return (double) a;
2160 return longBitsToDouble(DBL_NAN);
2162 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2166 float builtin_d2f(double a)
2172 return intBitsToFloat(FLT_NAN);
2174 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2177 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2180 /*============================================================================*/
2181 /* AUTOMATICALLY REPLACED FUNCTIONS */
2182 /*============================================================================*/
2184 /* builtin_arraycopy ***********************************************************
2186 Builtin for java.lang.System.arraycopy.
2188 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2190 *******************************************************************************/
2192 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2193 java_handle_t *dest, s4 destStart, s4 len)
2195 arraydescriptor *sdesc;
2196 arraydescriptor *ddesc;
2199 if ((src == NULL) || (dest == NULL)) {
2200 exceptions_throw_nullpointerexception();
2204 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2205 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2207 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2208 exceptions_throw_arraystoreexception();
2212 // Check if offsets and length are positive.
2213 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2214 exceptions_throw_arrayindexoutofboundsexception();
2218 // Check if ranges are valid.
2219 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2220 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2221 exceptions_throw_arrayindexoutofboundsexception();
2230 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2231 /* We copy primitive values or references of exactly the same type */
2233 s4 dataoffset = sdesc->dataoffset;
2234 s4 componentsize = sdesc->componentsize;
2236 LLNI_CRITICAL_START;
2238 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2239 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2240 u1, (size_t) len * componentsize);
2245 /* We copy references of different type */
2247 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2248 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2250 if (destStart <= srcStart) {
2251 for (i = 0; i < len; i++) {
2254 o = array_objectarray_element_get(oas, srcStart + i);
2256 if (!builtin_canstore(oad, o))
2259 array_objectarray_element_set(oad, destStart + i, o);
2263 /* XXX this does not completely obey the specification!
2264 If an exception is thrown only the elements above the
2265 current index have been copied. The specification
2266 requires that only the elements *below* the current
2267 index have been copied before the throw. */
2269 for (i = len - 1; i >= 0; i--) {
2272 o = array_objectarray_element_get(oas, srcStart + i);
2274 if (!builtin_canstore(oad, o))
2277 array_objectarray_element_set(oad, destStart + i, o);
2284 /* builtin_nanotime ************************************************************
2286 Return the current time in nanoseconds.
2288 *******************************************************************************/
2290 s8 builtin_nanotime(void)
2295 if (gettimeofday(&tv, NULL) == -1)
2296 vm_abort("gettimeofday failed: %s", strerror(errno));
2298 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2300 return usecs * 1000;
2304 /* builtin_currenttimemillis ***************************************************
2306 Return the current time in milliseconds.
2308 *******************************************************************************/
2310 s8 builtin_currenttimemillis(void)
2314 msecs = builtin_nanotime() / 1000 / 1000;
2320 /* builtin_clone ***************************************************************
2322 Function for cloning objects or arrays.
2324 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2326 *******************************************************************************/
2328 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2330 arraydescriptor *ad;
2333 java_handle_t *co; /* cloned object header */
2335 /* get the array descriptor */
2337 ad = LLNI_vftbl_direct(o)->arraydesc;
2339 /* we are cloning an array */
2342 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2344 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2349 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2350 /* XXX this is only a dirty hack to make Boehm work with handles */
2352 co = LLNI_WRAP((java_object_t *) co);
2355 LLNI_CRITICAL_START;
2357 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2359 #if defined(ENABLE_GC_CACAO)
2360 heap_init_objectheader(LLNI_DIRECT(co), size);
2363 #if defined(ENABLE_THREADS)
2364 lock_init_object_lock(LLNI_DIRECT(co));
2372 /* we are cloning a non-array */
2374 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2375 exceptions_throw_clonenotsupportedexception();
2379 /* get the class of the object */
2381 LLNI_class_get(o, c);
2383 /* create new object */
2385 co = builtin_new(c);
2390 LLNI_CRITICAL_START;
2392 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2394 #if defined(ENABLE_GC_CACAO)
2395 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2398 #if defined(ENABLE_THREADS)
2399 lock_init_object_lock(LLNI_DIRECT(co));
2408 #if defined(ENABLE_CYCLES_STATS)
2409 void builtin_print_cycles_stats(FILE *file)
2411 fprintf(file,"builtin cylce count statistics:\n");
2413 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2414 CYCLES_STATS_PRINT(builtin_new ,file);
2418 #endif /* defined(ENABLE_CYCLES_STATS) */
2421 #if defined(ENABLE_VMLOG)
2423 #include <vmlog_cacao.c>
2428 * These are local overrides for various environment variables in Emacs.
2429 * Please do not remove this and leave it at the end of the file, where
2430 * Emacs will automagically detect them.
2431 * ---------------------------------------------------------------------
2434 * indent-tabs-mode: t
2438 * vim:noexpandtab:sw=4:ts=4: