1 /* src/vm/builtin.c - 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/thread.hpp"
58 #include "toolbox/logging.h"
59 #include "toolbox/util.h"
62 #include "vm/builtin.h"
64 #include "vm/cycles-stats.h"
65 #include "vm/exceptions.hpp"
66 #include "vm/global.h"
67 #include "vm/globals.hpp"
68 #include "vm/initialize.h"
69 #include "vm/linker.h"
70 #include "vm/loader.h"
71 #include "vm/options.h"
72 #include "vm/primitive.hpp"
73 #include "vm/rt-timing.h"
74 #include "vm/string.hpp"
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/trace.hpp"
79 #if defined(ENABLE_VMLOG)
80 #include <vmlog_cacao.h>
84 /* include builtin tables *****************************************************/
86 #include "vm/builtintable.inc"
89 CYCLES_STATS_DECLARE(builtin_new ,100,5)
90 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
93 /*============================================================================*/
94 /* BUILTIN TABLE MANAGEMENT FUNCTIONS */
95 /*============================================================================*/
97 /* builtintable_init ***********************************************************
99 Parse the descriptors of builtin functions and create the parsed
102 *******************************************************************************/
104 static bool builtintable_init(void)
106 descriptor_pool *descpool;
107 builtintable_entry *bte;
111 /* mark start of 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)) {
134 /* release dump area */
142 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
143 bte->descriptor = utf_new_char(bte->cdescriptor);
145 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
151 for (bte = builtintable_function; bte->fp != NULL; bte++) {
152 bte->classname = utf_new_char(bte->cclassname);
153 bte->name = utf_new_char(bte->cname);
154 bte->descriptor = utf_new_char(bte->cdescriptor);
156 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
162 /* create the class reference table */
164 (void) descriptor_pool_create_classrefs(descpool, NULL);
166 /* allocate space for the parsed descriptors */
168 descriptor_pool_alloc_parsed_descriptors(descpool);
170 /* Now parse all descriptors. NOTE: builtin-functions are treated
171 like static methods (no `this' pointer). */
173 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
175 descriptor_pool_parse_method_descriptor(descpool,
177 ACC_STATIC | ACC_METHOD_BUILTIN,
180 /* generate a builtin stub if we need one */
182 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
183 m = method_new_builtin(bte);
184 codegen_generate_stub_builtin(m, bte);
188 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
190 descriptor_pool_parse_method_descriptor(descpool,
192 ACC_STATIC | ACC_METHOD_BUILTIN,
195 /* no stubs should be needed for this table */
197 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
200 for (bte = builtintable_function; bte->fp != NULL; bte++) {
202 descriptor_pool_parse_method_descriptor(descpool,
204 ACC_STATIC | ACC_METHOD_BUILTIN,
207 /* generate a builtin stub if we need one */
209 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
210 m = method_new_builtin(bte);
211 codegen_generate_stub_builtin(m, bte);
215 /* release dump area */
223 /* builtintable_comparator *****************************************************
225 qsort comparator for the automatic builtin table.
227 *******************************************************************************/
229 static int builtintable_comparator(const void *a, const void *b)
231 builtintable_entry *bte1;
232 builtintable_entry *bte2;
234 bte1 = (builtintable_entry *) a;
235 bte2 = (builtintable_entry *) b;
237 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
241 /* builtintable_sort_automatic *************************************************
243 Sorts the automatic builtin table.
245 *******************************************************************************/
247 static void builtintable_sort_automatic(void)
251 /* calculate table size statically (`- 1' comment see builtintable.inc) */
253 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
255 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
256 builtintable_comparator);
260 /* builtin_init ****************************************************************
262 Initialize the global table of builtin functions.
264 *******************************************************************************/
266 bool builtin_init(void)
268 TRACESUBSYSTEMINITIALIZATION("builtin_init");
270 /* initialize the builtin tables */
272 if (!builtintable_init())
275 /* sort builtin tables */
277 builtintable_sort_automatic();
283 /* builtintable_get_internal ***************************************************
285 Finds an entry in the builtintable for internal functions and
286 returns the a pointer to the structure.
288 *******************************************************************************/
290 builtintable_entry *builtintable_get_internal(functionptr fp)
292 builtintable_entry *bte;
294 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
303 /* builtintable_get_automatic **************************************************
305 Finds an entry in the builtintable for functions which are replaced
306 automatically and returns the a pointer to the structure.
308 *******************************************************************************/
310 builtintable_entry *builtintable_get_automatic(s4 opcode)
312 builtintable_entry *first;
313 builtintable_entry *last;
314 builtintable_entry *middle;
318 /* calculate table size statically (`- 1' comment see builtintable.inc) */
320 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
322 first = builtintable_automatic;
323 last = builtintable_automatic + entries;
325 while (entries > 0) {
327 middle = first + half;
329 if (middle->opcode < opcode) {
337 return (first != last ? first : NULL);
341 /* builtintable_replace_function ***********************************************
345 *******************************************************************************/
347 #if defined(ENABLE_JIT)
348 bool builtintable_replace_function(void *iptr_)
351 builtintable_entry *bte;
354 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
356 /* get name and descriptor of the function */
359 case ICMD_INVOKESTATIC:
360 /* The instruction MUST be resolved, otherwise we run into
361 lazy loading troubles. Anyway, we should/can only replace
362 very VM-close functions. */
364 if (INSTRUCTION_IS_UNRESOLVED(iptr))
367 mr = iptr->sx.s23.s3.fmiref;
374 /* search the function table */
376 for (bte = builtintable_function; bte->fp != NULL; bte++) {
377 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
378 (mr->name == bte->name) &&
379 (mr->descriptor == bte->descriptor)) {
381 /* set the values in the instruction */
383 iptr->opc = bte->opcode;
384 iptr->sx.s23.s3.bte = bte;
386 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
387 iptr->flags.bits |= INS_FLAG_CHECK;
389 iptr->flags.bits &= ~INS_FLAG_CHECK;
397 #endif /* defined(ENABLE_JIT) */
400 /*============================================================================*/
401 /* INTERNAL BUILTIN FUNCTIONS */
402 /*============================================================================*/
404 /* builtin_instanceof **********************************************************
406 Checks if an object is an instance of some given class (or subclass
407 of that class). If class is an interface, checks if the interface
411 1......o is an instance of class or implements the interface
412 0......otherwise or if o == NULL
414 NOTE: This builtin can be called from NATIVE code only.
416 *******************************************************************************/
418 bool builtin_instanceof(java_handle_t *o, classinfo *c)
425 LLNI_class_get(o, oc);
427 return class_isanysubclass(oc, c);
432 /* builtin_checkcast ***********************************************************
434 The same as builtin_instanceof but with the exception
435 that 1 is returned when (o == NULL).
437 NOTE: This builtin can be called from NATIVE code only.
439 *******************************************************************************/
441 bool builtin_checkcast(java_handle_t *o, classinfo *c)
448 LLNI_class_get(o, oc);
450 if (class_isanysubclass(oc, c))
457 /* builtin_descriptorscompatible ***********************************************
459 Checks if two array type descriptors are assignment compatible.
462 1......target = desc is possible
465 *******************************************************************************/
467 static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
472 if (desc->arraytype != target->arraytype)
475 if (desc->arraytype != ARRAYTYPE_OBJECT)
478 /* {both arrays are arrays of references} */
480 if (desc->dimension == target->dimension) {
481 if (!desc->elementvftbl)
483 /* an array which contains elements of interface types is
484 allowed to be casted to Object (JOWENN)*/
486 if ((desc->elementvftbl->baseval < 0) &&
487 (target->elementvftbl->baseval == 1))
490 return class_isanysubclass(desc->elementvftbl->clazz,
491 target->elementvftbl->clazz);
494 if (desc->dimension < target->dimension)
497 /* {desc has higher dimension than target} */
499 return class_isanysubclass(pseudo_class_Arraystub,
500 target->elementvftbl->clazz);
504 /* builtin_arraycheckcast ******************************************************
506 Checks if an object is really a subtype of the requested array
507 type. The object has to be an array to begin with. For simple
508 arrays (int, short, double, etc.) the types have to match exactly.
509 For arrays of objects, the type of elements in the array has to be
510 a subtype (or the same type) of the requested element type. For
511 arrays of arrays (which in turn can again be arrays of arrays), the
512 types at the lowest level have to satisfy the corresponding sub
515 NOTE: This is a FAST builtin and can be called from JIT code only.
517 *******************************************************************************/
519 bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
521 arraydescriptor *desc;
526 desc = o->vftbl->arraydesc;
531 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
535 /* builtin_fast_arrayinstanceof ************************************************
537 NOTE: This is a FAST builtin and can be called from JIT code only.
539 *******************************************************************************/
541 bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
546 return builtin_fast_arraycheckcast(o, targetclass);
550 /* builtin_arrayinstanceof *****************************************************
552 NOTE: This builtin can be called from NATIVE code only.
554 *******************************************************************************/
556 bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
562 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
570 /* builtin_throw_exception *****************************************************
572 Sets the exception pointer with the thrown exception and prints some
573 debugging information.
575 NOTE: This is a FAST builtin and can be called from JIT code,
576 or from asm_vm_call_method.
578 *******************************************************************************/
580 void *builtin_throw_exception(java_object_t *xptr)
583 /* print exception trace */
585 if (opt_TraceExceptions)
586 trace_exception_builtin(xptr);
587 #endif /* !defined(NDEBUG) */
589 /* actually set the exception */
591 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
593 /* Return a NULL pointer. This is required for vm_call_method to
594 check for an exception. This is for convenience. */
600 /* builtin_retrieve_exception **************************************************
602 Gets and clears the exception pointer of the current thread.
605 the exception object, or NULL if no exception was thrown.
607 NOTE: This is a FAST builtin and can be called from JIT code,
608 or from the signal handlers.
610 *******************************************************************************/
612 java_object_t *builtin_retrieve_exception(void)
617 /* actually get and clear the exception */
619 h = exceptions_get_and_clear_exception();
626 /* builtin_canstore ************************************************************
628 Checks, if an object can be stored in an array.
632 0......otherwise (throws an ArrayStoreException)
634 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
636 *******************************************************************************/
638 bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
644 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
648 /* if not possible, throw an exception */
651 exceptions_throw_arraystoreexception();
657 /* builtin_fast_canstore *******************************************************
659 Checks, if an object can be stored in an array.
663 0......otherwise (no exception thrown!)
665 NOTE: This is a FAST builtin and can be called from JIT code only.
667 *******************************************************************************/
669 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
671 arraydescriptor *desc;
672 arraydescriptor *valuedesc;
673 vftbl_t *componentvftbl;
682 /* The following is guaranteed (by verifier checks):
684 * *) oa->...vftbl->arraydesc != NULL
685 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
686 * *) o->vftbl is not an interface vftbl
689 desc = oa->header.objheader.vftbl->arraydesc;
690 componentvftbl = desc->componentvftbl;
691 valuevftbl = o->vftbl;
692 valuedesc = valuevftbl->arraydesc;
694 if ((desc->dimension - 1) == 0) {
695 /* {oa is a one-dimensional array} */
696 /* {oa is an array of references} */
698 if (valuevftbl == componentvftbl)
701 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
703 baseval = componentvftbl->baseval;
706 /* an array of interface references */
708 result = ((valuevftbl->interfacetablelength > -baseval) &&
709 (valuevftbl->interfacetable[baseval] != NULL));
712 diffval = valuevftbl->baseval - componentvftbl->baseval;
713 result = diffval <= (uint32_t) componentvftbl->diffval;
716 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
718 else if (valuedesc == NULL) {
719 /* {oa has dimension > 1} */
720 /* {componentvftbl->arraydesc != NULL} */
722 /* check if o is an array */
727 /* {o is an array} */
729 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
738 /* This is an optimized version where a is guaranteed to be one-dimensional */
739 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
741 arraydescriptor *desc;
742 vftbl_t *elementvftbl;
751 /* The following is guaranteed (by verifier checks):
753 * *) a->...vftbl->arraydesc != NULL
754 * *) a->...vftbl->arraydesc->elementvftbl != NULL
755 * *) a->...vftbl->arraydesc->dimension == 1
756 * *) o->vftbl is not an interface vftbl
759 desc = a->header.objheader.vftbl->arraydesc;
760 elementvftbl = desc->elementvftbl;
761 valuevftbl = o->vftbl;
763 /* {a is a one-dimensional array} */
765 if (valuevftbl == elementvftbl)
768 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
770 baseval = elementvftbl->baseval;
773 /* an array of interface references */
774 result = ((valuevftbl->interfacetablelength > -baseval) &&
775 (valuevftbl->interfacetable[baseval] != NULL));
778 diffval = valuevftbl->baseval - elementvftbl->baseval;
779 result = diffval <= (uint32_t) elementvftbl->diffval;
782 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
788 /* This is an optimized version where a is guaranteed to be a
789 * one-dimensional array of a class type */
790 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
792 vftbl_t *elementvftbl;
800 /* The following is guaranteed (by verifier checks):
802 * *) a->...vftbl->arraydesc != NULL
803 * *) a->...vftbl->arraydesc->elementvftbl != NULL
804 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
805 * *) a->...vftbl->arraydesc->dimension == 1
806 * *) o->vftbl is not an interface vftbl
809 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
810 valuevftbl = o->vftbl;
812 /* {a is a one-dimensional array} */
814 if (valuevftbl == elementvftbl)
817 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
819 diffval = valuevftbl->baseval - elementvftbl->baseval;
820 result = diffval <= (uint32_t) elementvftbl->diffval;
822 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
828 /* builtin_new *****************************************************************
830 Creates a new instance of class c on the heap.
833 pointer to the object, or NULL if no memory is available
835 NOTE: This builtin can be called from NATIVE code only.
837 *******************************************************************************/
839 java_handle_t *builtin_new(classinfo *c)
842 #if defined(ENABLE_RT_TIMING)
843 struct timespec time_start, time_end;
845 #if defined(ENABLE_CYCLES_STATS)
846 u8 cycles_start, cycles_end;
849 RT_TIMING_GET_TIME(time_start);
850 CYCLES_STATS_GET(cycles_start);
852 /* is the class loaded */
854 assert(c->state & CLASS_LOADED);
856 /* check if we can instantiate this class */
858 if (c->flags & ACC_ABSTRACT) {
859 exceptions_throw_instantiationerror(c);
863 /* is the class linked */
865 if (!(c->state & CLASS_LINKED))
869 if (!(c->state & CLASS_INITIALIZED)) {
872 log_message_class("Initialize class (from builtin_new): ", c);
875 if (!initialize_class(c))
879 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
885 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
886 /* XXX this is only a dirty hack to make Boehm work with handles */
888 o = LLNI_WRAP((java_object_t *) o);
891 LLNI_vftbl_direct(o) = c->vftbl;
893 #if defined(ENABLE_THREADS)
894 lock_init_object_lock(LLNI_DIRECT(o));
897 CYCLES_STATS_GET(cycles_end);
898 RT_TIMING_GET_TIME(time_end);
900 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
901 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
906 #if defined(ENABLE_ESCAPE_REASON)
907 java_handle_t *builtin_escape_reason_new(classinfo *c) {
908 print_escape_reasons();
909 return builtin_java_new(c);
913 #if defined(ENABLE_TLH)
914 java_handle_t *builtin_tlh_new(classinfo *c)
917 # if defined(ENABLE_RT_TIMING)
918 struct timespec time_start, time_end;
920 # if defined(ENABLE_CYCLES_STATS)
921 u8 cycles_start, cycles_end;
924 RT_TIMING_GET_TIME(time_start);
925 CYCLES_STATS_GET(cycles_start);
927 /* is the class loaded */
929 assert(c->state & CLASS_LOADED);
931 /* check if we can instantiate this class */
933 if (c->flags & ACC_ABSTRACT) {
934 exceptions_throw_instantiationerror(c);
938 /* is the class linked */
940 if (!(c->state & CLASS_LINKED))
944 if (!(c->state & CLASS_INITIALIZED)) {
945 # if !defined(NDEBUG)
947 log_message_class("Initialize class (from builtin_new): ", c);
950 if (!initialize_class(c))
955 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
960 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
967 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
968 /* XXX this is only a dirty hack to make Boehm work with handles */
970 o = LLNI_WRAP((java_object_t *) o);
973 LLNI_vftbl_direct(o) = c->vftbl;
975 # if defined(ENABLE_THREADS)
976 lock_init_object_lock(LLNI_DIRECT(o));
979 CYCLES_STATS_GET(cycles_end);
980 RT_TIMING_GET_TIME(time_end);
983 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
984 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
992 /* builtin_java_new ************************************************************
994 NOTE: This is a SLOW builtin and can be called from JIT code only.
996 *******************************************************************************/
998 java_handle_t *builtin_java_new(java_handle_t *clazz)
1000 return builtin_new(LLNI_classinfo_unwrap(clazz));
1004 /* builtin_fast_new ************************************************************
1006 Creates a new instance of class c on the heap.
1009 pointer to the object, or NULL if no fast return
1010 is possible for any reason.
1012 NOTE: This is a FAST builtin and can be called from JIT code only.
1014 *******************************************************************************/
1016 java_object_t *builtin_fast_new(classinfo *c)
1019 #if defined(ENABLE_RT_TIMING)
1020 struct timespec time_start, time_end;
1022 #if defined(ENABLE_CYCLES_STATS)
1023 u8 cycles_start, cycles_end;
1026 RT_TIMING_GET_TIME(time_start);
1027 CYCLES_STATS_GET(cycles_start);
1029 /* is the class loaded */
1031 assert(c->state & CLASS_LOADED);
1033 /* check if we can instantiate this class */
1035 if (c->flags & ACC_ABSTRACT)
1038 /* is the class linked */
1040 if (!(c->state & CLASS_LINKED))
1043 if (!(c->state & CLASS_INITIALIZED))
1046 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1047 c->finalizer, false);
1052 o->vftbl = c->vftbl;
1054 #if defined(ENABLE_THREADS)
1055 lock_init_object_lock(o);
1058 CYCLES_STATS_GET(cycles_end);
1059 RT_TIMING_GET_TIME(time_end);
1061 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1062 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1068 /* builtin_newarray ************************************************************
1070 Creates an array with the given vftbl on the heap. This function
1071 takes as class argument an array class.
1074 pointer to the array or NULL if no memory is available
1076 NOTE: This builtin can be called from NATIVE code only.
1078 *******************************************************************************/
1080 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1082 arraydescriptor *desc;
1087 #if defined(ENABLE_RT_TIMING)
1088 struct timespec time_start, time_end;
1091 RT_TIMING_GET_TIME(time_start);
1093 desc = arrayclass->vftbl->arraydesc;
1094 dataoffset = desc->dataoffset;
1095 componentsize = desc->componentsize;
1098 exceptions_throw_negativearraysizeexception();
1102 actualsize = dataoffset + size * componentsize;
1104 /* check for overflow */
1106 if (((u4) actualsize) < ((u4) size)) {
1107 exceptions_throw_outofmemoryerror();
1111 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1116 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1117 /* XXX this is only a dirty hack to make Boehm work with handles */
1119 a = LLNI_WRAP((java_object_t *) a);
1122 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1124 #if defined(ENABLE_THREADS)
1125 lock_init_object_lock(LLNI_DIRECT(a));
1128 LLNI_array_size(a) = size;
1130 RT_TIMING_GET_TIME(time_end);
1131 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1137 /* builtin_java_newarray *******************************************************
1139 NOTE: This is a SLOW builtin and can be called from JIT code only.
1141 *******************************************************************************/
1143 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1145 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1149 /* builtin_anewarray ***********************************************************
1151 Creates an array of references to the given class type on the heap.
1154 pointer to the array or NULL if no memory is
1157 NOTE: This builtin can be called from NATIVE code only.
1159 *******************************************************************************/
1161 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1163 classinfo *arrayclass;
1165 /* is class loaded */
1167 assert(componentclass->state & CLASS_LOADED);
1169 /* is class linked */
1171 if (!(componentclass->state & CLASS_LINKED))
1172 if (!link_class(componentclass))
1175 arrayclass = class_array_of(componentclass, true);
1180 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1184 /* builtin_newarray_type ****************************************************
1186 Creates an array of [type]s on the heap.
1189 pointer to the array or NULL if no memory is available
1191 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1193 *******************************************************************************/
1195 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1196 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1198 return (java_handle_##type##array_t *) \
1199 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1202 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1203 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1204 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1205 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1206 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1207 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1208 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1209 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1212 /* builtin_multianewarray_intern ***********************************************
1214 Creates a multi-dimensional array on the heap. The dimensions are
1215 passed in an array of longs.
1218 n.............number of dimensions to create
1219 arrayclass....the array class
1220 dims..........array containing the size of each dimension to create
1223 pointer to the array or NULL if no memory is available
1225 ******************************************************************************/
1227 static java_handle_t *builtin_multianewarray_intern(int n,
1228 classinfo *arrayclass,
1233 classinfo *componentclass;
1236 /* create this dimension */
1238 size = (s4) dims[0];
1239 a = builtin_newarray(size, arrayclass);
1244 /* if this is the last dimension return */
1249 /* get the class of the components to create */
1251 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1253 /* The verifier guarantees that the dimension count is in the range. */
1255 /* create the component arrays */
1257 for (i = 0; i < size; i++) {
1259 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1260 /* we save an s4 to a s8 slot, 8-byte aligned */
1262 builtin_multianewarray_intern(n, componentclass, dims + 2);
1264 builtin_multianewarray_intern(n, componentclass, dims + 1);
1270 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1277 /* builtin_multianewarray ******************************************************
1279 Wrapper for builtin_multianewarray_intern which checks all
1280 dimensions before we start allocating.
1282 NOTE: This is a SLOW builtin and can be called from JIT code only.
1284 ******************************************************************************/
1286 java_handle_objectarray_t *builtin_multianewarray(int n,
1287 java_handle_t *arrayclazz,
1294 /* check all dimensions before doing anything */
1296 for (i = 0; i < n; i++) {
1297 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1298 /* we save an s4 to a s8 slot, 8-byte aligned */
1299 size = (s4) dims[i * 2];
1301 size = (s4) dims[i];
1305 exceptions_throw_negativearraysizeexception();
1310 c = LLNI_classinfo_unwrap(arrayclazz);
1312 /* now call the real function */
1314 return (java_handle_objectarray_t *)
1315 builtin_multianewarray_intern(n, c, dims);
1319 /* builtin_verbosecall_enter ***************************************************
1321 Print method call with arguments for -verbose:call.
1323 XXX: Remove mew once all archs use the new tracer!
1325 *******************************************************************************/
1327 #if !defined(NDEBUG)
1328 #ifdef TRACE_ARGS_NUM
1329 void builtin_verbosecall_enter(s8 a0, s8 a1,
1330 # if TRACE_ARGS_NUM >= 4
1333 # if TRACE_ARGS_NUM >= 6
1336 # if TRACE_ARGS_NUM == 8
1341 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1344 #endif /* !defined(NDEBUG) */
1347 /* builtin_verbosecall_exit ****************************************************
1349 Print method exit for -verbose:call.
1351 XXX: Remove mew once all archs use the new tracer!
1353 *******************************************************************************/
1355 #if !defined(NDEBUG)
1356 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1358 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1360 #endif /* !defined(NDEBUG) */
1363 /*============================================================================*/
1364 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1365 /*============================================================================*/
1367 /*********** Functions for integer divisions *****************************
1369 On some systems (eg. DEC ALPHA), integer division is not supported by the
1370 CPU. These helper functions implement the missing functionality.
1372 ******************************************************************************/
1374 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1375 s4 builtin_idiv(s4 a, s4 b)
1384 s4 builtin_irem(s4 a, s4 b)
1392 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1395 /* functions for long arithmetics **********************************************
1397 On systems where 64 bit Integers are not supported by the CPU,
1398 these functions are needed.
1400 ******************************************************************************/
1402 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1403 s8 builtin_ladd(s8 a, s8 b)
1416 s8 builtin_lsub(s8 a, s8 b)
1429 s8 builtin_lneg(s8 a)
1441 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1444 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1445 s8 builtin_lmul(s8 a, s8 b)
1457 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1460 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1461 s8 builtin_ldiv(s8 a, s8 b)
1474 s8 builtin_lrem(s8 a, s8 b)
1486 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1489 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1490 s8 builtin_lshl(s8 a, s4 b)
1503 s8 builtin_lshr(s8 a, s4 b)
1516 s8 builtin_lushr(s8 a, s4 b)
1521 c = ((u8) a) >> (b & 63);
1528 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1531 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1532 s8 builtin_land(s8 a, s8 b)
1545 s8 builtin_lor(s8 a, s8 b)
1558 s8 builtin_lxor(s8 a, s8 b)
1570 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1573 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1574 s4 builtin_lcmp(s8 a, s8 b)
1588 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1591 /* functions for unsupported floating instructions ****************************/
1593 /* used to convert FLT_xxx defines into float values */
1595 static inline float intBitsToFloat(s4 i)
1604 /* used to convert DBL_xxx defines into double values */
1606 static inline float longBitsToDouble(s8 l)
1616 float builtin_fadd(float a, float b)
1618 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1619 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1630 if (copysignf(1.0, a) == copysignf(1.0, b))
1633 return intBitsToFloat(FLT_NAN);
1639 float builtin_fsub(float a, float b)
1641 return builtin_fadd(a, builtin_fneg(b));
1645 float builtin_fmul(float a, float b)
1647 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1648 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1650 if (finitef(b)) return a * b;
1652 if (a == 0) return intBitsToFloat(FLT_NAN);
1653 else return copysignf(b, copysignf(1.0, b)*a);
1658 if (b == 0) return intBitsToFloat(FLT_NAN);
1659 else return copysignf(a, copysignf(1.0, a)*b);
1662 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1668 /* builtin_ddiv ****************************************************************
1670 Implementation as described in VM Spec.
1672 *******************************************************************************/
1674 float builtin_fdiv(float a, float b)
1678 /* If neither value1' nor value2' is NaN, the sign of the result */
1679 /* is positive if both values have the same sign, negative if the */
1680 /* values have different signs. */
1686 /* If either value1' or value2' is NaN, the result is NaN. */
1688 return intBitsToFloat(FLT_NAN);
1691 /* Division of a finite value by an infinity results in a */
1692 /* signed zero, with the sign-producing rule just given. */
1694 /* is sign equal? */
1696 if (copysignf(1.0, a) == copysignf(1.0, b))
1705 /* If either value1' or value2' is NaN, the result is NaN. */
1707 return intBitsToFloat(FLT_NAN);
1709 } else if (finitef(b)) {
1710 /* Division of an infinity by a finite value results in a signed */
1711 /* infinity, with the sign-producing rule just given. */
1713 /* is sign equal? */
1715 if (copysignf(1.0, a) == copysignf(1.0, b))
1716 return intBitsToFloat(FLT_POSINF);
1718 return intBitsToFloat(FLT_NEGINF);
1721 /* Division of an infinity by an infinity results in NaN. */
1723 return intBitsToFloat(FLT_NAN);
1729 float builtin_fneg(float a)
1731 if (isnanf(a)) return a;
1733 if (finitef(a)) return -a;
1734 else return copysignf(a, -copysignf(1.0, a));
1737 #endif /* !SUPPORT_FLOAT */
1740 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1741 s4 builtin_fcmpl(float a, float b)
1749 if (!finitef(a) || !finitef(b)) {
1750 a = finitef(a) ? 0 : copysignf(1.0, a);
1751 b = finitef(b) ? 0 : copysignf(1.0, b);
1764 s4 builtin_fcmpg(float a, float b)
1766 if (isnanf(a)) return 1;
1767 if (isnanf(b)) return 1;
1768 if (!finitef(a) || !finitef(b)) {
1769 a = finitef(a) ? 0 : copysignf(1.0, a);
1770 b = finitef(b) ? 0 : copysignf(1.0, b);
1772 if (a > b) return 1;
1773 if (a == b) return 0;
1776 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1779 float builtin_frem(float a, float b)
1785 /* functions for unsupported double instructions ******************************/
1788 double builtin_dadd(double a, double b)
1790 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1791 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1793 if (finite(b)) return a + b;
1797 if (finite(b)) return a;
1799 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1800 else return longBitsToDouble(DBL_NAN);
1806 double builtin_dsub(double a, double b)
1808 return builtin_dadd(a, builtin_dneg(b));
1812 double builtin_dmul(double a, double b)
1814 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1815 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1817 if (finite(b)) return a * b;
1819 if (a == 0) return longBitsToDouble(DBL_NAN);
1820 else return copysign(b, copysign(1.0, b) * a);
1825 if (b == 0) return longBitsToDouble(DBL_NAN);
1826 else return copysign(a, copysign(1.0, a) * b);
1829 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1835 /* builtin_ddiv ****************************************************************
1837 Implementation as described in VM Spec.
1839 *******************************************************************************/
1841 double builtin_ddiv(double a, double b)
1845 /* If neither value1' nor value2' is NaN, the sign of the result */
1846 /* is positive if both values have the same sign, negative if the */
1847 /* values have different signs. */
1853 /* If either value1' or value2' is NaN, the result is NaN. */
1855 return longBitsToDouble(DBL_NAN);
1858 /* Division of a finite value by an infinity results in a */
1859 /* signed zero, with the sign-producing rule just given. */
1861 /* is sign equal? */
1863 if (copysign(1.0, a) == copysign(1.0, b))
1872 /* If either value1' or value2' is NaN, the result is NaN. */
1874 return longBitsToDouble(DBL_NAN);
1876 } else if (finite(b)) {
1877 /* Division of an infinity by a finite value results in a signed */
1878 /* infinity, with the sign-producing rule just given. */
1880 /* is sign equal? */
1882 if (copysign(1.0, a) == copysign(1.0, b))
1883 return longBitsToDouble(DBL_POSINF);
1885 return longBitsToDouble(DBL_NEGINF);
1888 /* Division of an infinity by an infinity results in NaN. */
1890 return longBitsToDouble(DBL_NAN);
1896 /* builtin_dneg ****************************************************************
1898 Implemented as described in VM Spec.
1900 *******************************************************************************/
1902 double builtin_dneg(double a)
1905 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1912 /* If the operand is a zero, the result is the zero of opposite */
1918 /* If the operand is an infinity, the result is the infinity of */
1919 /* opposite sign. */
1921 return copysign(a, -copysign(1.0, a));
1925 #endif /* !SUPPORT_DOUBLE */
1928 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1929 s4 builtin_dcmpl(double a, double b)
1937 if (!finite(a) || !finite(b)) {
1938 a = finite(a) ? 0 : copysign(1.0, a);
1939 b = finite(b) ? 0 : copysign(1.0, b);
1952 s4 builtin_dcmpg(double a, double b)
1960 if (!finite(a) || !finite(b)) {
1961 a = finite(a) ? 0 : copysign(1.0, a);
1962 b = finite(b) ? 0 : copysign(1.0, b);
1973 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1976 double builtin_drem(double a, double b)
1982 /* conversion operations ******************************************************/
1985 s8 builtin_i2l(s4 i)
1997 s4 builtin_l2i(s8 l)
2008 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2009 float builtin_i2f(s4 a)
2011 float f = (float) a;
2014 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2017 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2018 double builtin_i2d(s4 a)
2020 double d = (double) a;
2023 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2026 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2027 float builtin_l2f(s8 a)
2030 float f = (float) a;
2036 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2039 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2040 double builtin_l2d(s8 a)
2043 double d = (double) a;
2049 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2052 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2053 s4 builtin_f2i(float a)
2057 i = builtin_d2i((double) a);
2068 if (a < (-2147483648))
2069 return (-2147483648);
2072 f = copysignf((float) 1.0, a);
2075 return (-2147483648); */
2077 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2080 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2081 s8 builtin_f2l(float a)
2085 l = builtin_d2l((double) a);
2092 if (a > 9223372036854775807L)
2093 return 9223372036854775807L;
2094 if (a < (-9223372036854775808L))
2095 return (-9223372036854775808L);
2100 f = copysignf((float) 1.0, a);
2102 return 9223372036854775807L;
2103 return (-9223372036854775808L); */
2105 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2108 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2109 s4 builtin_d2i(double a)
2114 if (a >= 2147483647)
2116 if (a <= (-2147483647-1))
2117 return (-2147483647-1);
2122 d = copysign(1.0, a);
2125 return (-2147483647-1);
2127 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2130 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2131 s8 builtin_d2l(double a)
2136 if (a >= 9223372036854775807LL)
2137 return 9223372036854775807LL;
2138 if (a <= (-9223372036854775807LL-1))
2139 return (-9223372036854775807LL-1);
2144 d = copysign(1.0, a);
2146 return 9223372036854775807LL;
2147 return (-9223372036854775807LL-1);
2149 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2152 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2153 double builtin_f2d(float a)
2155 if (finitef(a)) return (double) a;
2158 return longBitsToDouble(DBL_NAN);
2160 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2164 float builtin_d2f(double a)
2170 return intBitsToFloat(FLT_NAN);
2172 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2175 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2178 /*============================================================================*/
2179 /* AUTOMATICALLY REPLACED FUNCTIONS */
2180 /*============================================================================*/
2182 /* builtin_arraycopy ***********************************************************
2184 Builtin for java.lang.System.arraycopy.
2186 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2188 *******************************************************************************/
2190 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2191 java_handle_t *dest, s4 destStart, s4 len)
2193 arraydescriptor *sdesc;
2194 arraydescriptor *ddesc;
2197 if ((src == NULL) || (dest == NULL)) {
2198 exceptions_throw_nullpointerexception();
2202 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2203 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2205 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2206 exceptions_throw_arraystoreexception();
2210 // Check if offsets and length are positive.
2211 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2212 exceptions_throw_arrayindexoutofboundsexception();
2216 // Check if ranges are valid.
2217 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2218 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2219 exceptions_throw_arrayindexoutofboundsexception();
2228 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2229 /* We copy primitive values or references of exactly the same type */
2231 s4 dataoffset = sdesc->dataoffset;
2232 s4 componentsize = sdesc->componentsize;
2234 LLNI_CRITICAL_START;
2236 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2237 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2238 u1, (size_t) len * componentsize);
2243 /* We copy references of different type */
2245 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2246 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2248 if (destStart <= srcStart) {
2249 for (i = 0; i < len; i++) {
2252 o = array_objectarray_element_get(oas, srcStart + i);
2254 if (!builtin_canstore(oad, o))
2257 array_objectarray_element_set(oad, destStart + i, o);
2261 /* XXX this does not completely obey the specification!
2262 If an exception is thrown only the elements above the
2263 current index have been copied. The specification
2264 requires that only the elements *below* the current
2265 index have been copied before the throw. */
2267 for (i = len - 1; i >= 0; i--) {
2270 o = array_objectarray_element_get(oas, srcStart + i);
2272 if (!builtin_canstore(oad, o))
2275 array_objectarray_element_set(oad, destStart + i, o);
2282 /* builtin_nanotime ************************************************************
2284 Return the current time in nanoseconds.
2286 *******************************************************************************/
2288 s8 builtin_nanotime(void)
2293 if (gettimeofday(&tv, NULL) == -1)
2294 vm_abort("gettimeofday failed: %s", strerror(errno));
2296 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2298 return usecs * 1000;
2302 /* builtin_currenttimemillis ***************************************************
2304 Return the current time in milliseconds.
2306 *******************************************************************************/
2308 s8 builtin_currenttimemillis(void)
2312 msecs = builtin_nanotime() / 1000 / 1000;
2318 /* builtin_clone ***************************************************************
2320 Function for cloning objects or arrays.
2322 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2324 *******************************************************************************/
2326 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2328 arraydescriptor *ad;
2331 java_handle_t *co; /* cloned object header */
2333 /* get the array descriptor */
2335 ad = LLNI_vftbl_direct(o)->arraydesc;
2337 /* we are cloning an array */
2340 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2342 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2347 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2348 /* XXX this is only a dirty hack to make Boehm work with handles */
2350 co = LLNI_WRAP((java_object_t *) co);
2353 LLNI_CRITICAL_START;
2355 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2357 #if defined(ENABLE_GC_CACAO)
2358 heap_init_objectheader(LLNI_DIRECT(co), size);
2361 #if defined(ENABLE_THREADS)
2362 lock_init_object_lock(LLNI_DIRECT(co));
2370 /* we are cloning a non-array */
2372 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2373 exceptions_throw_clonenotsupportedexception();
2377 /* get the class of the object */
2379 LLNI_class_get(o, c);
2381 /* create new object */
2383 co = builtin_new(c);
2388 LLNI_CRITICAL_START;
2390 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2392 #if defined(ENABLE_GC_CACAO)
2393 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2396 #if defined(ENABLE_THREADS)
2397 lock_init_object_lock(LLNI_DIRECT(co));
2406 #if defined(ENABLE_CYCLES_STATS)
2407 void builtin_print_cycles_stats(FILE *file)
2409 fprintf(file,"builtin cylce count statistics:\n");
2411 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2412 CYCLES_STATS_PRINT(builtin_new ,file);
2416 #endif /* defined(ENABLE_CYCLES_STATS) */
2419 #if defined(ENABLE_VMLOG)
2421 #include <vmlog_cacao.c>
2426 * These are local overrides for various environment variables in Emacs.
2427 * Please do not remove this and leave it at the end of the file, where
2428 * Emacs will automagically detect them.
2429 * ---------------------------------------------------------------------
2432 * indent-tabs-mode: t
2436 * vim:noexpandtab:sw=4:ts=4: