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/jni.h"
54 #include "native/llni.h"
56 #include "threads/lock-common.h"
57 #include "threads/thread.hpp"
59 #include "toolbox/logging.h"
60 #include "toolbox/util.h"
63 #include "vm/builtin.h"
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.h"
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/trace.hpp"
80 #if defined(ENABLE_VMLOG)
81 #include <vmlog_cacao.h>
85 /* include builtin tables *****************************************************/
87 #include "vm/builtintable.inc"
90 CYCLES_STATS_DECLARE(builtin_new ,100,5)
91 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
94 /*============================================================================*/
95 /* BUILTIN TABLE MANAGEMENT FUNCTIONS */
96 /*============================================================================*/
98 /* builtintable_init ***********************************************************
100 Parse the descriptors of builtin functions and create the parsed
103 *******************************************************************************/
105 static bool builtintable_init(void)
107 descriptor_pool *descpool;
108 builtintable_entry *bte;
112 /* mark start of dump memory area */
116 /* create a new descriptor pool */
118 descpool = descriptor_pool_new(class_java_lang_Object);
120 /* add some entries we need */
122 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
125 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
128 /* first add all descriptors to the pool */
130 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
131 bte->name = utf_new_char(bte->cname);
132 bte->descriptor = utf_new_char(bte->cdescriptor);
134 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
135 /* release dump area */
143 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
144 bte->descriptor = utf_new_char(bte->cdescriptor);
146 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
152 for (bte = builtintable_function; bte->fp != NULL; bte++) {
153 bte->classname = utf_new_char(bte->cclassname);
154 bte->name = utf_new_char(bte->cname);
155 bte->descriptor = utf_new_char(bte->cdescriptor);
157 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
163 /* create the class reference table */
165 (void) descriptor_pool_create_classrefs(descpool, NULL);
167 /* allocate space for the parsed descriptors */
169 descriptor_pool_alloc_parsed_descriptors(descpool);
171 /* Now parse all descriptors. NOTE: builtin-functions are treated
172 like static methods (no `this' pointer). */
174 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
176 descriptor_pool_parse_method_descriptor(descpool,
178 ACC_STATIC | ACC_METHOD_BUILTIN,
181 /* generate a builtin stub if we need one */
183 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
184 m = method_new_builtin(bte);
185 codegen_generate_stub_builtin(m, bte);
189 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
191 descriptor_pool_parse_method_descriptor(descpool,
193 ACC_STATIC | ACC_METHOD_BUILTIN,
196 /* no stubs should be needed for this table */
198 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
201 for (bte = builtintable_function; bte->fp != NULL; bte++) {
203 descriptor_pool_parse_method_descriptor(descpool,
205 ACC_STATIC | ACC_METHOD_BUILTIN,
208 /* generate a builtin stub if we need one */
210 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
211 m = method_new_builtin(bte);
212 codegen_generate_stub_builtin(m, bte);
216 /* release dump area */
224 /* builtintable_comparator *****************************************************
226 qsort comparator for the automatic builtin table.
228 *******************************************************************************/
230 static int builtintable_comparator(const void *a, const void *b)
232 builtintable_entry *bte1;
233 builtintable_entry *bte2;
235 bte1 = (builtintable_entry *) a;
236 bte2 = (builtintable_entry *) b;
238 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
242 /* builtintable_sort_automatic *************************************************
244 Sorts the automatic builtin table.
246 *******************************************************************************/
248 static void builtintable_sort_automatic(void)
252 /* calculate table size statically (`- 1' comment see builtintable.inc) */
254 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
256 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
257 builtintable_comparator);
261 /* builtin_init ****************************************************************
263 Initialize the global table of builtin functions.
265 *******************************************************************************/
267 bool builtin_init(void)
269 TRACESUBSYSTEMINITIALIZATION("builtin_init");
271 /* initialize the builtin tables */
273 if (!builtintable_init())
276 /* sort builtin tables */
278 builtintable_sort_automatic();
284 /* builtintable_get_internal ***************************************************
286 Finds an entry in the builtintable for internal functions and
287 returns the a pointer to the structure.
289 *******************************************************************************/
291 builtintable_entry *builtintable_get_internal(functionptr fp)
293 builtintable_entry *bte;
295 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
304 /* builtintable_get_automatic **************************************************
306 Finds an entry in the builtintable for functions which are replaced
307 automatically and returns the a pointer to the structure.
309 *******************************************************************************/
311 builtintable_entry *builtintable_get_automatic(s4 opcode)
313 builtintable_entry *first;
314 builtintable_entry *last;
315 builtintable_entry *middle;
319 /* calculate table size statically (`- 1' comment see builtintable.inc) */
321 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
323 first = builtintable_automatic;
324 last = builtintable_automatic + entries;
326 while (entries > 0) {
328 middle = first + half;
330 if (middle->opcode < opcode) {
338 return (first != last ? first : NULL);
342 /* builtintable_replace_function ***********************************************
346 *******************************************************************************/
348 #if defined(ENABLE_JIT)
349 bool builtintable_replace_function(void *iptr_)
352 builtintable_entry *bte;
355 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
357 /* get name and descriptor of the function */
360 case ICMD_INVOKESTATIC:
361 /* The instruction MUST be resolved, otherwise we run into
362 lazy loading troubles. Anyway, we should/can only replace
363 very VM-close functions. */
365 if (INSTRUCTION_IS_UNRESOLVED(iptr))
368 mr = iptr->sx.s23.s3.fmiref;
375 /* search the function table */
377 for (bte = builtintable_function; bte->fp != NULL; bte++) {
378 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
379 (mr->name == bte->name) &&
380 (mr->descriptor == bte->descriptor)) {
382 /* set the values in the instruction */
384 iptr->opc = bte->opcode;
385 iptr->sx.s23.s3.bte = bte;
387 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
388 iptr->flags.bits |= INS_FLAG_CHECK;
390 iptr->flags.bits &= ~INS_FLAG_CHECK;
398 #endif /* defined(ENABLE_JIT) */
401 /*============================================================================*/
402 /* INTERNAL BUILTIN FUNCTIONS */
403 /*============================================================================*/
405 /* builtin_instanceof **********************************************************
407 Checks if an object is an instance of some given class (or subclass
408 of that class). If class is an interface, checks if the interface
412 1......o is an instance of class or implements the interface
413 0......otherwise or if o == NULL
415 NOTE: This builtin can be called from NATIVE code only.
417 *******************************************************************************/
419 bool builtin_instanceof(java_handle_t *o, classinfo *c)
426 LLNI_class_get(o, oc);
428 return class_isanysubclass(oc, c);
433 /* builtin_checkcast ***********************************************************
435 The same as builtin_instanceof but with the exception
436 that 1 is returned when (o == NULL).
438 NOTE: This builtin can be called from NATIVE code only.
440 *******************************************************************************/
442 bool builtin_checkcast(java_handle_t *o, classinfo *c)
449 LLNI_class_get(o, oc);
451 if (class_isanysubclass(oc, c))
458 /* builtin_descriptorscompatible ***********************************************
460 Checks if two array type descriptors are assignment compatible.
463 1......target = desc is possible
466 *******************************************************************************/
468 static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
473 if (desc->arraytype != target->arraytype)
476 if (desc->arraytype != ARRAYTYPE_OBJECT)
479 /* {both arrays are arrays of references} */
481 if (desc->dimension == target->dimension) {
482 if (!desc->elementvftbl)
484 /* an array which contains elements of interface types is
485 allowed to be casted to Object (JOWENN)*/
487 if ((desc->elementvftbl->baseval < 0) &&
488 (target->elementvftbl->baseval == 1))
491 return class_isanysubclass(desc->elementvftbl->clazz,
492 target->elementvftbl->clazz);
495 if (desc->dimension < target->dimension)
498 /* {desc has higher dimension than target} */
500 return class_isanysubclass(pseudo_class_Arraystub,
501 target->elementvftbl->clazz);
505 /* builtin_arraycheckcast ******************************************************
507 Checks if an object is really a subtype of the requested array
508 type. The object has to be an array to begin with. For simple
509 arrays (int, short, double, etc.) the types have to match exactly.
510 For arrays of objects, the type of elements in the array has to be
511 a subtype (or the same type) of the requested element type. For
512 arrays of arrays (which in turn can again be arrays of arrays), the
513 types at the lowest level have to satisfy the corresponding sub
516 NOTE: This is a FAST builtin and can be called from JIT code only.
518 *******************************************************************************/
520 bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
522 arraydescriptor *desc;
527 desc = o->vftbl->arraydesc;
532 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
536 /* builtin_fast_arrayinstanceof ************************************************
538 NOTE: This is a FAST builtin and can be called from JIT code only.
540 *******************************************************************************/
542 bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
547 return builtin_fast_arraycheckcast(o, targetclass);
551 /* builtin_arrayinstanceof *****************************************************
553 NOTE: This builtin can be called from NATIVE code only.
555 *******************************************************************************/
557 bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
563 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
571 /* builtin_throw_exception *****************************************************
573 Sets the exception pointer with the thrown exception and prints some
574 debugging information.
576 NOTE: This is a FAST builtin and can be called from JIT code,
577 or from asm_vm_call_method.
579 *******************************************************************************/
581 void *builtin_throw_exception(java_object_t *xptr)
584 /* print exception trace */
586 if (opt_TraceExceptions)
587 trace_exception_builtin(xptr);
588 #endif /* !defined(NDEBUG) */
590 /* actually set the exception */
592 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
594 /* Return a NULL pointer. This is required for vm_call_method to
595 check for an exception. This is for convenience. */
601 /* builtin_retrieve_exception **************************************************
603 Gets and clears the exception pointer of the current thread.
606 the exception object, or NULL if no exception was thrown.
608 NOTE: This is a FAST builtin and can be called from JIT code,
609 or from the signal handlers.
611 *******************************************************************************/
613 java_object_t *builtin_retrieve_exception(void)
618 /* actually get and clear the exception */
620 h = exceptions_get_and_clear_exception();
627 /* builtin_canstore ************************************************************
629 Checks, if an object can be stored in an array.
633 0......otherwise (throws an ArrayStoreException)
635 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
637 *******************************************************************************/
639 bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
645 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
649 /* if not possible, throw an exception */
652 exceptions_throw_arraystoreexception();
658 /* builtin_fast_canstore *******************************************************
660 Checks, if an object can be stored in an array.
664 0......otherwise (no exception thrown!)
666 NOTE: This is a FAST builtin and can be called from JIT code only.
668 *******************************************************************************/
670 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
672 arraydescriptor *desc;
673 arraydescriptor *valuedesc;
674 vftbl_t *componentvftbl;
683 /* The following is guaranteed (by verifier checks):
685 * *) oa->...vftbl->arraydesc != NULL
686 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
687 * *) o->vftbl is not an interface vftbl
690 desc = oa->header.objheader.vftbl->arraydesc;
691 componentvftbl = desc->componentvftbl;
692 valuevftbl = o->vftbl;
693 valuedesc = valuevftbl->arraydesc;
695 if ((desc->dimension - 1) == 0) {
696 /* {oa is a one-dimensional array} */
697 /* {oa is an array of references} */
699 if (valuevftbl == componentvftbl)
702 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
704 baseval = componentvftbl->baseval;
707 /* an array of interface references */
709 result = ((valuevftbl->interfacetablelength > -baseval) &&
710 (valuevftbl->interfacetable[baseval] != NULL));
713 diffval = valuevftbl->baseval - componentvftbl->baseval;
714 result = diffval <= (uint32_t) componentvftbl->diffval;
717 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
719 else if (valuedesc == NULL) {
720 /* {oa has dimension > 1} */
721 /* {componentvftbl->arraydesc != NULL} */
723 /* check if o is an array */
728 /* {o is an array} */
730 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
739 /* This is an optimized version where a is guaranteed to be one-dimensional */
740 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
742 arraydescriptor *desc;
743 vftbl_t *elementvftbl;
752 /* The following is guaranteed (by verifier checks):
754 * *) a->...vftbl->arraydesc != NULL
755 * *) a->...vftbl->arraydesc->elementvftbl != NULL
756 * *) a->...vftbl->arraydesc->dimension == 1
757 * *) o->vftbl is not an interface vftbl
760 desc = a->header.objheader.vftbl->arraydesc;
761 elementvftbl = desc->elementvftbl;
762 valuevftbl = o->vftbl;
764 /* {a is a one-dimensional array} */
766 if (valuevftbl == elementvftbl)
769 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
771 baseval = elementvftbl->baseval;
774 /* an array of interface references */
775 result = ((valuevftbl->interfacetablelength > -baseval) &&
776 (valuevftbl->interfacetable[baseval] != NULL));
779 diffval = valuevftbl->baseval - elementvftbl->baseval;
780 result = diffval <= (uint32_t) elementvftbl->diffval;
783 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
789 /* This is an optimized version where a is guaranteed to be a
790 * one-dimensional array of a class type */
791 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
793 vftbl_t *elementvftbl;
801 /* The following is guaranteed (by verifier checks):
803 * *) a->...vftbl->arraydesc != NULL
804 * *) a->...vftbl->arraydesc->elementvftbl != NULL
805 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
806 * *) a->...vftbl->arraydesc->dimension == 1
807 * *) o->vftbl is not an interface vftbl
810 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
811 valuevftbl = o->vftbl;
813 /* {a is a one-dimensional array} */
815 if (valuevftbl == elementvftbl)
818 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
820 diffval = valuevftbl->baseval - elementvftbl->baseval;
821 result = diffval <= (uint32_t) elementvftbl->diffval;
823 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
829 /* builtin_new *****************************************************************
831 Creates a new instance of class c on the heap.
834 pointer to the object, or NULL if no memory is available
836 NOTE: This builtin can be called from NATIVE code only.
838 *******************************************************************************/
840 java_handle_t *builtin_new(classinfo *c)
843 #if defined(ENABLE_RT_TIMING)
844 struct timespec time_start, time_end;
846 #if defined(ENABLE_CYCLES_STATS)
847 u8 cycles_start, cycles_end;
850 RT_TIMING_GET_TIME(time_start);
851 CYCLES_STATS_GET(cycles_start);
853 /* is the class loaded */
855 assert(c->state & CLASS_LOADED);
857 /* check if we can instantiate this class */
859 if (c->flags & ACC_ABSTRACT) {
860 exceptions_throw_instantiationerror(c);
864 /* is the class linked */
866 if (!(c->state & CLASS_LINKED))
870 if (!(c->state & CLASS_INITIALIZED)) {
873 log_message_class("Initialize class (from builtin_new): ", c);
876 if (!initialize_class(c))
880 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
886 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
887 /* XXX this is only a dirty hack to make Boehm work with handles */
889 o = LLNI_WRAP((java_object_t *) o);
892 LLNI_vftbl_direct(o) = c->vftbl;
894 #if defined(ENABLE_THREADS)
895 lock_init_object_lock(LLNI_DIRECT(o));
898 CYCLES_STATS_GET(cycles_end);
899 RT_TIMING_GET_TIME(time_end);
901 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
902 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
907 #if defined(ENABLE_ESCAPE_REASON)
908 java_handle_t *builtin_escape_reason_new(classinfo *c) {
909 print_escape_reasons();
910 return builtin_java_new(c);
914 #if defined(ENABLE_TLH)
915 java_handle_t *builtin_tlh_new(classinfo *c)
918 # if defined(ENABLE_RT_TIMING)
919 struct timespec time_start, time_end;
921 # if defined(ENABLE_CYCLES_STATS)
922 u8 cycles_start, cycles_end;
925 RT_TIMING_GET_TIME(time_start);
926 CYCLES_STATS_GET(cycles_start);
928 /* is the class loaded */
930 assert(c->state & CLASS_LOADED);
932 /* check if we can instantiate this class */
934 if (c->flags & ACC_ABSTRACT) {
935 exceptions_throw_instantiationerror(c);
939 /* is the class linked */
941 if (!(c->state & CLASS_LINKED))
945 if (!(c->state & CLASS_INITIALIZED)) {
946 # if !defined(NDEBUG)
948 log_message_class("Initialize class (from builtin_new): ", c);
951 if (!initialize_class(c))
956 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
961 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
968 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
969 /* XXX this is only a dirty hack to make Boehm work with handles */
971 o = LLNI_WRAP((java_object_t *) o);
974 LLNI_vftbl_direct(o) = c->vftbl;
976 # if defined(ENABLE_THREADS)
977 lock_init_object_lock(LLNI_DIRECT(o));
980 CYCLES_STATS_GET(cycles_end);
981 RT_TIMING_GET_TIME(time_end);
984 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
985 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
993 /* builtin_java_new ************************************************************
995 NOTE: This is a SLOW builtin and can be called from JIT code only.
997 *******************************************************************************/
999 java_handle_t *builtin_java_new(java_handle_t *clazz)
1001 return builtin_new(LLNI_classinfo_unwrap(clazz));
1005 /* builtin_fast_new ************************************************************
1007 Creates a new instance of class c on the heap.
1010 pointer to the object, or NULL if no fast return
1011 is possible for any reason.
1013 NOTE: This is a FAST builtin and can be called from JIT code only.
1015 *******************************************************************************/
1017 java_object_t *builtin_fast_new(classinfo *c)
1020 #if defined(ENABLE_RT_TIMING)
1021 struct timespec time_start, time_end;
1023 #if defined(ENABLE_CYCLES_STATS)
1024 u8 cycles_start, cycles_end;
1027 RT_TIMING_GET_TIME(time_start);
1028 CYCLES_STATS_GET(cycles_start);
1030 /* is the class loaded */
1032 assert(c->state & CLASS_LOADED);
1034 /* check if we can instantiate this class */
1036 if (c->flags & ACC_ABSTRACT)
1039 /* is the class linked */
1041 if (!(c->state & CLASS_LINKED))
1044 if (!(c->state & CLASS_INITIALIZED))
1047 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1048 c->finalizer, false);
1053 o->vftbl = c->vftbl;
1055 #if defined(ENABLE_THREADS)
1056 lock_init_object_lock(o);
1059 CYCLES_STATS_GET(cycles_end);
1060 RT_TIMING_GET_TIME(time_end);
1062 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1063 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1069 /* builtin_newarray ************************************************************
1071 Creates an array with the given vftbl on the heap. This function
1072 takes as class argument an array class.
1075 pointer to the array or NULL if no memory is available
1077 NOTE: This builtin can be called from NATIVE code only.
1079 *******************************************************************************/
1081 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
1083 arraydescriptor *desc;
1088 #if defined(ENABLE_RT_TIMING)
1089 struct timespec time_start, time_end;
1092 RT_TIMING_GET_TIME(time_start);
1094 desc = arrayclass->vftbl->arraydesc;
1095 dataoffset = desc->dataoffset;
1096 componentsize = desc->componentsize;
1099 exceptions_throw_negativearraysizeexception();
1103 actualsize = dataoffset + size * componentsize;
1105 /* check for overflow */
1107 if (((u4) actualsize) < ((u4) size)) {
1108 exceptions_throw_outofmemoryerror();
1112 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1117 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1118 /* XXX this is only a dirty hack to make Boehm work with handles */
1120 a = LLNI_WRAP((java_object_t *) a);
1123 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1125 #if defined(ENABLE_THREADS)
1126 lock_init_object_lock(LLNI_DIRECT(a));
1129 LLNI_array_size(a) = size;
1131 RT_TIMING_GET_TIME(time_end);
1132 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1138 /* builtin_java_newarray *******************************************************
1140 NOTE: This is a SLOW builtin and can be called from JIT code only.
1142 *******************************************************************************/
1144 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1146 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1150 /* builtin_anewarray ***********************************************************
1152 Creates an array of references to the given class type on the heap.
1155 pointer to the array or NULL if no memory is
1158 NOTE: This builtin can be called from NATIVE code only.
1160 *******************************************************************************/
1162 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1164 classinfo *arrayclass;
1166 /* is class loaded */
1168 assert(componentclass->state & CLASS_LOADED);
1170 /* is class linked */
1172 if (!(componentclass->state & CLASS_LINKED))
1173 if (!link_class(componentclass))
1176 arrayclass = class_array_of(componentclass, true);
1181 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1185 /* builtin_newarray_type ****************************************************
1187 Creates an array of [type]s on the heap.
1190 pointer to the array or NULL if no memory is available
1192 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1194 *******************************************************************************/
1196 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1197 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1199 return (java_handle_##type##array_t *) \
1200 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1203 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1204 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1205 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1206 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1207 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1208 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1209 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1210 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1213 /* builtin_multianewarray_intern ***********************************************
1215 Creates a multi-dimensional array on the heap. The dimensions are
1216 passed in an array of longs.
1219 n.............number of dimensions to create
1220 arrayclass....the array class
1221 dims..........array containing the size of each dimension to create
1224 pointer to the array or NULL if no memory is available
1226 ******************************************************************************/
1228 static java_handle_t *builtin_multianewarray_intern(int n,
1229 classinfo *arrayclass,
1234 classinfo *componentclass;
1237 /* create this dimension */
1239 size = (s4) dims[0];
1240 a = builtin_newarray(size, arrayclass);
1245 /* if this is the last dimension return */
1250 /* get the class of the components to create */
1252 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1254 /* The verifier guarantees that the dimension count is in the range. */
1256 /* create the component arrays */
1258 for (i = 0; i < size; i++) {
1260 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1261 /* we save an s4 to a s8 slot, 8-byte aligned */
1263 builtin_multianewarray_intern(n, componentclass, dims + 2);
1265 builtin_multianewarray_intern(n, componentclass, dims + 1);
1271 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1278 /* builtin_multianewarray ******************************************************
1280 Wrapper for builtin_multianewarray_intern which checks all
1281 dimensions before we start allocating.
1283 NOTE: This is a SLOW builtin and can be called from JIT code only.
1285 ******************************************************************************/
1287 java_handle_objectarray_t *builtin_multianewarray(int n,
1288 java_handle_t *arrayclazz,
1295 /* check all dimensions before doing anything */
1297 for (i = 0; i < n; i++) {
1298 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1299 /* we save an s4 to a s8 slot, 8-byte aligned */
1300 size = (s4) dims[i * 2];
1302 size = (s4) dims[i];
1306 exceptions_throw_negativearraysizeexception();
1311 c = LLNI_classinfo_unwrap(arrayclazz);
1313 /* now call the real function */
1315 return (java_handle_objectarray_t *)
1316 builtin_multianewarray_intern(n, c, dims);
1320 /* builtin_verbosecall_enter ***************************************************
1322 Print method call with arguments for -verbose:call.
1324 XXX: Remove mew once all archs use the new tracer!
1326 *******************************************************************************/
1328 #if !defined(NDEBUG)
1329 #ifdef TRACE_ARGS_NUM
1330 void builtin_verbosecall_enter(s8 a0, s8 a1,
1331 # if TRACE_ARGS_NUM >= 4
1334 # if TRACE_ARGS_NUM >= 6
1337 # if TRACE_ARGS_NUM == 8
1342 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1345 #endif /* !defined(NDEBUG) */
1348 /* builtin_verbosecall_exit ****************************************************
1350 Print method exit for -verbose:call.
1352 XXX: Remove mew once all archs use the new tracer!
1354 *******************************************************************************/
1356 #if !defined(NDEBUG)
1357 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1359 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1361 #endif /* !defined(NDEBUG) */
1364 /*============================================================================*/
1365 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1366 /*============================================================================*/
1368 /*********** Functions for integer divisions *****************************
1370 On some systems (eg. DEC ALPHA), integer division is not supported by the
1371 CPU. These helper functions implement the missing functionality.
1373 ******************************************************************************/
1375 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1376 s4 builtin_idiv(s4 a, s4 b)
1385 s4 builtin_irem(s4 a, s4 b)
1393 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1396 /* functions for long arithmetics **********************************************
1398 On systems where 64 bit Integers are not supported by the CPU,
1399 these functions are needed.
1401 ******************************************************************************/
1403 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1404 s8 builtin_ladd(s8 a, s8 b)
1417 s8 builtin_lsub(s8 a, s8 b)
1430 s8 builtin_lneg(s8 a)
1442 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1445 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1446 s8 builtin_lmul(s8 a, s8 b)
1458 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1461 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1462 s8 builtin_ldiv(s8 a, s8 b)
1475 s8 builtin_lrem(s8 a, s8 b)
1487 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1490 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1491 s8 builtin_lshl(s8 a, s4 b)
1504 s8 builtin_lshr(s8 a, s4 b)
1517 s8 builtin_lushr(s8 a, s4 b)
1522 c = ((u8) a) >> (b & 63);
1529 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1532 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1533 s8 builtin_land(s8 a, s8 b)
1546 s8 builtin_lor(s8 a, s8 b)
1559 s8 builtin_lxor(s8 a, s8 b)
1571 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1574 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1575 s4 builtin_lcmp(s8 a, s8 b)
1589 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1592 /* functions for unsupported floating instructions ****************************/
1594 /* used to convert FLT_xxx defines into float values */
1596 static inline float intBitsToFloat(s4 i)
1605 /* used to convert DBL_xxx defines into double values */
1607 static inline float longBitsToDouble(s8 l)
1617 float builtin_fadd(float a, float b)
1619 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1620 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1631 if (copysignf(1.0, a) == copysignf(1.0, b))
1634 return intBitsToFloat(FLT_NAN);
1640 float builtin_fsub(float a, float b)
1642 return builtin_fadd(a, builtin_fneg(b));
1646 float builtin_fmul(float a, float b)
1648 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1649 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1651 if (finitef(b)) return a * b;
1653 if (a == 0) return intBitsToFloat(FLT_NAN);
1654 else return copysignf(b, copysignf(1.0, b)*a);
1659 if (b == 0) return intBitsToFloat(FLT_NAN);
1660 else return copysignf(a, copysignf(1.0, a)*b);
1663 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1669 /* builtin_ddiv ****************************************************************
1671 Implementation as described in VM Spec.
1673 *******************************************************************************/
1675 float builtin_fdiv(float a, float b)
1679 /* If neither value1' nor value2' is NaN, the sign of the result */
1680 /* is positive if both values have the same sign, negative if the */
1681 /* values have different signs. */
1687 /* If either value1' or value2' is NaN, the result is NaN. */
1689 return intBitsToFloat(FLT_NAN);
1692 /* Division of a finite value by an infinity results in a */
1693 /* signed zero, with the sign-producing rule just given. */
1695 /* is sign equal? */
1697 if (copysignf(1.0, a) == copysignf(1.0, b))
1706 /* If either value1' or value2' is NaN, the result is NaN. */
1708 return intBitsToFloat(FLT_NAN);
1710 } else if (finitef(b)) {
1711 /* Division of an infinity by a finite value results in a signed */
1712 /* infinity, with the sign-producing rule just given. */
1714 /* is sign equal? */
1716 if (copysignf(1.0, a) == copysignf(1.0, b))
1717 return intBitsToFloat(FLT_POSINF);
1719 return intBitsToFloat(FLT_NEGINF);
1722 /* Division of an infinity by an infinity results in NaN. */
1724 return intBitsToFloat(FLT_NAN);
1730 float builtin_fneg(float a)
1732 if (isnanf(a)) return a;
1734 if (finitef(a)) return -a;
1735 else return copysignf(a, -copysignf(1.0, a));
1738 #endif /* !SUPPORT_FLOAT */
1741 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1742 s4 builtin_fcmpl(float a, float b)
1750 if (!finitef(a) || !finitef(b)) {
1751 a = finitef(a) ? 0 : copysignf(1.0, a);
1752 b = finitef(b) ? 0 : copysignf(1.0, b);
1765 s4 builtin_fcmpg(float a, float b)
1767 if (isnanf(a)) return 1;
1768 if (isnanf(b)) return 1;
1769 if (!finitef(a) || !finitef(b)) {
1770 a = finitef(a) ? 0 : copysignf(1.0, a);
1771 b = finitef(b) ? 0 : copysignf(1.0, b);
1773 if (a > b) return 1;
1774 if (a == b) return 0;
1777 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1780 float builtin_frem(float a, float b)
1786 /* functions for unsupported double instructions ******************************/
1789 double builtin_dadd(double a, double b)
1791 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1792 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1794 if (finite(b)) return a + b;
1798 if (finite(b)) return a;
1800 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1801 else return longBitsToDouble(DBL_NAN);
1807 double builtin_dsub(double a, double b)
1809 return builtin_dadd(a, builtin_dneg(b));
1813 double builtin_dmul(double a, double b)
1815 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1816 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1818 if (finite(b)) return a * b;
1820 if (a == 0) return longBitsToDouble(DBL_NAN);
1821 else return copysign(b, copysign(1.0, b) * a);
1826 if (b == 0) return longBitsToDouble(DBL_NAN);
1827 else return copysign(a, copysign(1.0, a) * b);
1830 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1836 /* builtin_ddiv ****************************************************************
1838 Implementation as described in VM Spec.
1840 *******************************************************************************/
1842 double builtin_ddiv(double a, double b)
1846 /* If neither value1' nor value2' is NaN, the sign of the result */
1847 /* is positive if both values have the same sign, negative if the */
1848 /* values have different signs. */
1854 /* If either value1' or value2' is NaN, the result is NaN. */
1856 return longBitsToDouble(DBL_NAN);
1859 /* Division of a finite value by an infinity results in a */
1860 /* signed zero, with the sign-producing rule just given. */
1862 /* is sign equal? */
1864 if (copysign(1.0, a) == copysign(1.0, b))
1873 /* If either value1' or value2' is NaN, the result is NaN. */
1875 return longBitsToDouble(DBL_NAN);
1877 } else if (finite(b)) {
1878 /* Division of an infinity by a finite value results in a signed */
1879 /* infinity, with the sign-producing rule just given. */
1881 /* is sign equal? */
1883 if (copysign(1.0, a) == copysign(1.0, b))
1884 return longBitsToDouble(DBL_POSINF);
1886 return longBitsToDouble(DBL_NEGINF);
1889 /* Division of an infinity by an infinity results in NaN. */
1891 return longBitsToDouble(DBL_NAN);
1897 /* builtin_dneg ****************************************************************
1899 Implemented as described in VM Spec.
1901 *******************************************************************************/
1903 double builtin_dneg(double a)
1906 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1913 /* If the operand is a zero, the result is the zero of opposite */
1919 /* If the operand is an infinity, the result is the infinity of */
1920 /* opposite sign. */
1922 return copysign(a, -copysign(1.0, a));
1926 #endif /* !SUPPORT_DOUBLE */
1929 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1930 s4 builtin_dcmpl(double a, double b)
1938 if (!finite(a) || !finite(b)) {
1939 a = finite(a) ? 0 : copysign(1.0, a);
1940 b = finite(b) ? 0 : copysign(1.0, b);
1953 s4 builtin_dcmpg(double a, double b)
1961 if (!finite(a) || !finite(b)) {
1962 a = finite(a) ? 0 : copysign(1.0, a);
1963 b = finite(b) ? 0 : copysign(1.0, b);
1974 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1977 double builtin_drem(double a, double b)
1983 /* conversion operations ******************************************************/
1986 s8 builtin_i2l(s4 i)
1998 s4 builtin_l2i(s8 l)
2009 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2010 float builtin_i2f(s4 a)
2012 float f = (float) a;
2015 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2018 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2019 double builtin_i2d(s4 a)
2021 double d = (double) a;
2024 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2027 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2028 float builtin_l2f(s8 a)
2031 float f = (float) a;
2037 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2040 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2041 double builtin_l2d(s8 a)
2044 double d = (double) a;
2050 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2053 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2054 s4 builtin_f2i(float a)
2058 i = builtin_d2i((double) a);
2069 if (a < (-2147483648))
2070 return (-2147483648);
2073 f = copysignf((float) 1.0, a);
2076 return (-2147483648); */
2078 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2081 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2082 s8 builtin_f2l(float a)
2086 l = builtin_d2l((double) a);
2093 if (a > 9223372036854775807L)
2094 return 9223372036854775807L;
2095 if (a < (-9223372036854775808L))
2096 return (-9223372036854775808L);
2101 f = copysignf((float) 1.0, a);
2103 return 9223372036854775807L;
2104 return (-9223372036854775808L); */
2106 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2109 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2110 s4 builtin_d2i(double a)
2115 if (a >= 2147483647)
2117 if (a <= (-2147483647-1))
2118 return (-2147483647-1);
2123 d = copysign(1.0, a);
2126 return (-2147483647-1);
2128 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2131 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2132 s8 builtin_d2l(double a)
2137 if (a >= 9223372036854775807LL)
2138 return 9223372036854775807LL;
2139 if (a <= (-9223372036854775807LL-1))
2140 return (-9223372036854775807LL-1);
2145 d = copysign(1.0, a);
2147 return 9223372036854775807LL;
2148 return (-9223372036854775807LL-1);
2150 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2153 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2154 double builtin_f2d(float a)
2156 if (finitef(a)) return (double) a;
2159 return longBitsToDouble(DBL_NAN);
2161 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2165 float builtin_d2f(double a)
2171 return intBitsToFloat(FLT_NAN);
2173 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2176 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2179 /*============================================================================*/
2180 /* AUTOMATICALLY REPLACED FUNCTIONS */
2181 /*============================================================================*/
2183 /* builtin_arraycopy ***********************************************************
2185 Builtin for java.lang.System.arraycopy.
2187 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2189 *******************************************************************************/
2191 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2192 java_handle_t *dest, s4 destStart, s4 len)
2194 arraydescriptor *sdesc;
2195 arraydescriptor *ddesc;
2198 if ((src == NULL) || (dest == NULL)) {
2199 exceptions_throw_nullpointerexception();
2203 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2204 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2206 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2207 exceptions_throw_arraystoreexception();
2211 // Check if offsets and length are positive.
2212 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2213 exceptions_throw_arrayindexoutofboundsexception();
2217 // Check if ranges are valid.
2218 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
2219 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
2220 exceptions_throw_arrayindexoutofboundsexception();
2229 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2230 /* We copy primitive values or references of exactly the same type */
2232 s4 dataoffset = sdesc->dataoffset;
2233 s4 componentsize = sdesc->componentsize;
2235 LLNI_CRITICAL_START;
2237 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2238 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2239 u1, (size_t) len * componentsize);
2244 /* We copy references of different type */
2246 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2247 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2249 if (destStart <= srcStart) {
2250 for (i = 0; i < len; i++) {
2253 o = array_objectarray_element_get(oas, srcStart + i);
2255 if (!builtin_canstore(oad, o))
2258 array_objectarray_element_set(oad, destStart + i, o);
2262 /* XXX this does not completely obey the specification!
2263 If an exception is thrown only the elements above the
2264 current index have been copied. The specification
2265 requires that only the elements *below* the current
2266 index have been copied before the throw. */
2268 for (i = len - 1; i >= 0; i--) {
2271 o = array_objectarray_element_get(oas, srcStart + i);
2273 if (!builtin_canstore(oad, o))
2276 array_objectarray_element_set(oad, destStart + i, o);
2283 /* builtin_nanotime ************************************************************
2285 Return the current time in nanoseconds.
2287 *******************************************************************************/
2289 s8 builtin_nanotime(void)
2294 if (gettimeofday(&tv, NULL) == -1)
2295 vm_abort("gettimeofday failed: %s", strerror(errno));
2297 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2299 return usecs * 1000;
2303 /* builtin_currenttimemillis ***************************************************
2305 Return the current time in milliseconds.
2307 *******************************************************************************/
2309 s8 builtin_currenttimemillis(void)
2313 msecs = builtin_nanotime() / 1000 / 1000;
2319 /* builtin_clone ***************************************************************
2321 Function for cloning objects or arrays.
2323 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2325 *******************************************************************************/
2327 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2329 arraydescriptor *ad;
2332 java_handle_t *co; /* cloned object header */
2334 /* get the array descriptor */
2336 ad = LLNI_vftbl_direct(o)->arraydesc;
2338 /* we are cloning an array */
2341 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2343 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2348 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2349 /* XXX this is only a dirty hack to make Boehm work with handles */
2351 co = LLNI_WRAP((java_object_t *) co);
2354 LLNI_CRITICAL_START;
2356 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2358 #if defined(ENABLE_GC_CACAO)
2359 heap_init_objectheader(LLNI_DIRECT(co), size);
2362 #if defined(ENABLE_THREADS)
2363 lock_init_object_lock(LLNI_DIRECT(co));
2371 /* we are cloning a non-array */
2373 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2374 exceptions_throw_clonenotsupportedexception();
2378 /* get the class of the object */
2380 LLNI_class_get(o, c);
2382 /* create new object */
2384 co = builtin_new(c);
2389 LLNI_CRITICAL_START;
2391 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2393 #if defined(ENABLE_GC_CACAO)
2394 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2397 #if defined(ENABLE_THREADS)
2398 lock_init_object_lock(LLNI_DIRECT(co));
2407 #if defined(ENABLE_CYCLES_STATS)
2408 void builtin_print_cycles_stats(FILE *file)
2410 fprintf(file,"builtin cylce count statistics:\n");
2412 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2413 CYCLES_STATS_PRINT(builtin_new ,file);
2417 #endif /* defined(ENABLE_CYCLES_STATS) */
2420 #if defined(ENABLE_VMLOG)
2422 #include <vmlog_cacao.c>
2427 * These are local overrides for various environment variables in Emacs.
2428 * Please do not remove this and leave it at the end of the file, where
2429 * Emacs will automagically detect them.
2430 * ---------------------------------------------------------------------
2433 * indent-tabs-mode: t
2437 * vim:noexpandtab:sw=4:ts=4: