1 /* src/vm/builtin.c - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contains C functions for JavaVM Instructions that cannot be
26 translated to machine language directly. Consequently, the
27 generated machine code for these instructions contains function
28 calls instead of machine instructions, using the C calling
47 #include "fdlibm/fdlibm.h"
48 #if defined(__CYGWIN__) && defined(Bias)
52 #include "mm/gc-common.h"
53 #include "mm/memory.h"
55 #include "native/jni.h"
56 #include "native/llni.h"
58 #include "threads/lock-common.h"
59 #include "threads/threads-common.h"
61 #include "toolbox/logging.h"
62 #include "toolbox/util.h"
65 #include "vm/builtin.h"
66 #include "vm/cycles-stats.h"
67 #include "vm/exceptions.h"
68 #include "vm/global.h"
69 #include "vm/initialize.h"
70 #include "vm/primitive.h"
71 #include "vm/stringlocal.h"
73 #include "vm/jit/asmpart.h"
74 #include "vm/jit/trace.h"
76 #include "vmcore/class.h"
77 #include "vmcore/linker.h"
78 #include "vmcore/loader.h"
79 #include "vmcore/options.h"
80 #include "vmcore/rt-timing.h"
82 #if defined(ENABLE_VMLOG)
83 #include <vmlog_cacao.h>
86 #if defined(ENABLE_DEBUG_FILTER)
87 # include "vm/jit/show.h"
90 /* include builtin tables *****************************************************/
92 #include "vm/builtintable.inc"
95 CYCLES_STATS_DECLARE(builtin_new ,100,5)
96 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
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;
109 builtintable_entry *bte;
111 /* mark start of dump memory area */
113 dumpsize = dump_size();
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 /* create a utf8 string from descriptor */
132 bte->descriptor = utf_new_char(bte->cdescriptor);
134 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
135 /* release dump area */
137 dump_release(dumpsize);
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)) {
147 dump_release(dumpsize);
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)) {
158 dump_release(dumpsize);
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 codegen_generate_stub_builtin(bte);
187 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
189 descriptor_pool_parse_method_descriptor(descpool,
191 ACC_STATIC | ACC_METHOD_BUILTIN,
194 /* no stubs should be needed for this table */
196 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
199 for (bte = builtintable_function; bte->fp != NULL; bte++) {
201 descriptor_pool_parse_method_descriptor(descpool,
203 ACC_STATIC | ACC_METHOD_BUILTIN,
206 /* generate a builtin stub if we need one */
208 if (bte->flags & BUILTINTABLE_FLAG_STUB)
209 codegen_generate_stub_builtin(bte);
212 /* release dump area */
214 dump_release(dumpsize);
220 /* builtintable_comparator *****************************************************
222 qsort comparator for the automatic builtin table.
224 *******************************************************************************/
226 static int builtintable_comparator(const void *a, const void *b)
228 builtintable_entry *bte1;
229 builtintable_entry *bte2;
231 bte1 = (builtintable_entry *) a;
232 bte2 = (builtintable_entry *) b;
234 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
238 /* builtintable_sort_automatic *************************************************
240 Sorts the automatic builtin table.
242 *******************************************************************************/
244 static void builtintable_sort_automatic(void)
248 /* calculate table size statically (`- 1' comment see builtintable.inc) */
250 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
252 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
253 builtintable_comparator);
257 /* builtin_init ****************************************************************
259 Initialize the global table of builtin functions.
261 *******************************************************************************/
263 bool builtin_init(void)
265 /* initialize the builtin tables */
267 if (!builtintable_init())
270 /* sort builtin tables */
272 builtintable_sort_automatic();
278 /* builtintable_get_internal ***************************************************
280 Finds an entry in the builtintable for internal functions and
281 returns the a pointer to the structure.
283 *******************************************************************************/
285 builtintable_entry *builtintable_get_internal(functionptr fp)
287 builtintable_entry *bte;
289 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
298 /* builtintable_get_automatic **************************************************
300 Finds an entry in the builtintable for functions which are replaced
301 automatically and returns the a pointer to the structure.
303 *******************************************************************************/
305 builtintable_entry *builtintable_get_automatic(s4 opcode)
307 builtintable_entry *first;
308 builtintable_entry *last;
309 builtintable_entry *middle;
313 /* calculate table size statically (`- 1' comment see builtintable.inc) */
315 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
317 first = builtintable_automatic;
318 last = builtintable_automatic + entries;
320 while (entries > 0) {
322 middle = first + half;
324 if (middle->opcode < opcode) {
332 return (first != last ? first : NULL);
336 /* builtintable_replace_function ***********************************************
340 *******************************************************************************/
342 #if defined(ENABLE_JIT)
343 bool builtintable_replace_function(void *iptr_)
346 builtintable_entry *bte;
349 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
351 /* get name and descriptor of the function */
354 case ICMD_INVOKESTATIC:
355 /* The instruction MUST be resolved, otherwise we run into
356 lazy loading troubles. Anyway, we should/can only replace
357 very VM-close functions. */
359 if (INSTRUCTION_IS_UNRESOLVED(iptr))
362 mr = iptr->sx.s23.s3.fmiref;
369 /* search the function table */
371 for (bte = builtintable_function; bte->fp != NULL; bte++) {
372 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
373 (mr->name == bte->name) &&
374 (mr->descriptor == bte->descriptor)) {
376 /* set the values in the instruction */
378 iptr->opc = bte->opcode;
379 iptr->sx.s23.s3.bte = bte;
381 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
382 iptr->flags.bits |= INS_FLAG_CHECK;
384 iptr->flags.bits &= ~INS_FLAG_CHECK;
392 #endif /* defined(ENABLE_JIT) */
395 /*****************************************************************************
397 *****************************************************************************/
399 /* builtin_instanceof **********************************************************
401 Checks if an object is an instance of some given class (or subclass
402 of that class). If class is an interface, checks if the interface
405 Return value: 1 ... o is an instance of class or implements the interface
406 0 ... otherwise or if o == NULL
408 *******************************************************************************/
410 s4 builtin_instanceof(java_handle_t *o, classinfo *class)
417 LLNI_class_get(o, c);
419 return class_isanysubclass(c, class);
424 /* builtin_checkcast ***********************************************************
426 The same as builtin_instanceof except that 1 is returned when o ==
429 *******************************************************************************/
431 s4 builtin_checkcast(java_handle_t *o, classinfo *class)
438 LLNI_class_get(o, c);
440 if (class_isanysubclass(c, class))
447 /* builtin_descriptorscompatible ***********************************************
449 Checks if two array type descriptors are assignment compatible
451 Return value: 1 ... target = desc is possible
454 *******************************************************************************/
456 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
457 arraydescriptor *target)
462 if (desc->arraytype != target->arraytype)
465 if (desc->arraytype != ARRAYTYPE_OBJECT)
468 /* {both arrays are arrays of references} */
470 if (desc->dimension == target->dimension) {
471 /* an array which contains elements of interface types is
472 allowed to be casted to Object (JOWENN)*/
474 if ((desc->elementvftbl->baseval < 0) &&
475 (target->elementvftbl->baseval == 1))
478 return class_isanysubclass(desc->elementvftbl->class,
479 target->elementvftbl->class);
482 if (desc->dimension < target->dimension)
485 /* {desc has higher dimension than target} */
487 return class_isanysubclass(pseudo_class_Arraystub,
488 target->elementvftbl->class);
492 /* builtin_arraycheckcast ******************************************************
494 Checks if an object is really a subtype of the requested array
495 type. The object has to be an array to begin with. For simple
496 arrays (int, short, double, etc.) the types have to match exactly.
497 For arrays of objects, the type of elements in the array has to be
498 a subtype (or the same type) of the requested element type. For
499 arrays of arrays (which in turn can again be arrays of arrays), the
500 types at the lowest level have to satisfy the corresponding sub
503 *******************************************************************************/
505 s4 builtin_arraycheckcast(java_handle_t *o, classinfo *targetclass)
507 arraydescriptor *desc;
512 desc = LLNI_vftbl_direct(o)->arraydesc;
517 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
521 s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass)
526 return builtin_arraycheckcast(o, targetclass);
530 /* builtin_throw_exception *****************************************************
532 Sets the exceptionptr with the thrown exception and prints some
533 debugging information. Called from asm_vm_call_method.
535 *******************************************************************************/
537 void *builtin_throw_exception(java_object_t *xptr)
540 /* print exception trace */
542 if (opt_TraceExceptions)
543 trace_exception_builtin(xptr);
544 #endif /* !defined(NDEBUG) */
546 /* actually set the exception */
548 exceptions_set_exception(xptr);
550 /* Return a NULL pointer. This is required for vm_call_method to
551 check for an exception. This is for convenience. */
557 /* builtin_canstore ************************************************************
559 Checks, if an object can be stored in an array.
561 Return value: 1 ... possible
562 0 ... otherwise (throws an ArrayStoreException)
564 *******************************************************************************/
566 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
572 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
576 /* if not possible, throw an exception */
579 exceptions_throw_arraystoreexception();
585 s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
587 arraydescriptor *desc;
588 arraydescriptor *valuedesc;
589 vftbl_t *componentvftbl;
598 /* The following is guaranteed (by verifier checks):
600 * *) oa->...vftbl->arraydesc != NULL
601 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
602 * *) o->vftbl is not an interface vftbl
605 desc = oa->header.objheader.vftbl->arraydesc;
606 componentvftbl = desc->componentvftbl;
607 valuevftbl = o->vftbl;
608 valuedesc = valuevftbl->arraydesc;
610 if ((desc->dimension - 1) == 0) {
611 /* {oa is a one-dimensional array} */
612 /* {oa is an array of references} */
614 if (valuevftbl == componentvftbl)
617 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
619 baseval = componentvftbl->baseval;
622 /* an array of interface references */
624 result = ((valuevftbl->interfacetablelength > -baseval) &&
625 (valuevftbl->interfacetable[baseval] != NULL));
628 diffval = valuevftbl->baseval - componentvftbl->baseval;
629 result = diffval <= (uint32_t) componentvftbl->diffval;
632 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
634 else if (valuedesc == NULL) {
635 /* {oa has dimension > 1} */
636 /* {componentvftbl->arraydesc != NULL} */
638 /* check if o is an array */
643 /* {o is an array} */
645 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
654 /* This is an optimized version where a is guaranteed to be one-dimensional */
655 s4 builtin_canstore_onedim (java_objectarray_t *a, java_object_t *o)
657 arraydescriptor *desc;
658 vftbl_t *elementvftbl;
667 /* The following is guaranteed (by verifier checks):
669 * *) a->...vftbl->arraydesc != NULL
670 * *) a->...vftbl->arraydesc->elementvftbl != NULL
671 * *) a->...vftbl->arraydesc->dimension == 1
672 * *) o->vftbl is not an interface vftbl
675 desc = a->header.objheader.vftbl->arraydesc;
676 elementvftbl = desc->elementvftbl;
677 valuevftbl = o->vftbl;
679 /* {a is a one-dimensional array} */
681 if (valuevftbl == elementvftbl)
684 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
686 baseval = elementvftbl->baseval;
689 /* an array of interface references */
690 result = ((valuevftbl->interfacetablelength > -baseval) &&
691 (valuevftbl->interfacetable[baseval] != NULL));
694 diffval = valuevftbl->baseval - elementvftbl->baseval;
695 result = diffval <= (uint32_t) elementvftbl->diffval;
698 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
704 /* This is an optimized version where a is guaranteed to be a
705 * one-dimensional array of a class type */
706 s4 builtin_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
708 vftbl_t *elementvftbl;
716 /* The following is guaranteed (by verifier checks):
718 * *) a->...vftbl->arraydesc != NULL
719 * *) a->...vftbl->arraydesc->elementvftbl != NULL
720 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
721 * *) a->...vftbl->arraydesc->dimension == 1
722 * *) o->vftbl is not an interface vftbl
725 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
726 valuevftbl = o->vftbl;
728 /* {a is a one-dimensional array} */
730 if (valuevftbl == elementvftbl)
733 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
735 diffval = valuevftbl->baseval - elementvftbl->baseval;
736 result = diffval <= (uint32_t) elementvftbl->diffval;
738 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
744 /* builtin_new *****************************************************************
746 Creates a new instance of class c on the heap.
748 Return value: pointer to the object or NULL if no memory is
751 *******************************************************************************/
753 java_handle_t *builtin_new(classinfo *c)
756 #if defined(ENABLE_RT_TIMING)
757 struct timespec time_start, time_end;
759 #if defined(ENABLE_CYCLES_STATS)
760 u8 cycles_start, cycles_end;
763 RT_TIMING_GET_TIME(time_start);
764 CYCLES_STATS_GET(cycles_start);
766 /* is the class loaded */
768 assert(c->state & CLASS_LOADED);
770 /* check if we can instantiate this class */
772 if (c->flags & ACC_ABSTRACT) {
773 exceptions_throw_instantiationerror(c);
777 /* is the class linked */
779 if (!(c->state & CLASS_LINKED))
783 if (!(c->state & CLASS_INITIALIZED)) {
786 log_message_class("Initialize class (from builtin_new): ", c);
789 if (!initialize_class(c))
793 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
801 #if defined(ENABLE_THREADS)
802 lock_init_object_lock(o);
805 CYCLES_STATS_GET(cycles_end);
806 RT_TIMING_GET_TIME(time_end);
808 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
809 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
815 /* builtin_fast_new ************************************************************
817 Creates a new instance of class c on the heap.
819 Return value: pointer to the object or NULL if no fast return
820 is possible for any reason.
822 *******************************************************************************/
824 java_object_t *builtin_fast_new(classinfo *c)
827 #if defined(ENABLE_RT_TIMING)
828 struct timespec time_start, time_end;
830 #if defined(ENABLE_CYCLES_STATS)
831 u8 cycles_start, cycles_end;
834 RT_TIMING_GET_TIME(time_start);
835 CYCLES_STATS_GET(cycles_start);
837 /* is the class loaded */
839 assert(c->state & CLASS_LOADED);
841 /* check if we can instantiate this class */
843 if (c->flags & ACC_ABSTRACT)
846 /* is the class linked */
848 if (!(c->state & CLASS_LINKED))
851 if (!(c->state & CLASS_INITIALIZED))
854 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
855 c->finalizer, false);
862 #if defined(ENABLE_THREADS)
863 lock_init_object_lock(o);
866 CYCLES_STATS_GET(cycles_end);
867 RT_TIMING_GET_TIME(time_end);
869 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
870 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
876 /* builtin_newarray ************************************************************
878 Creates an array with the given vftbl on the heap. This function
879 takes as class argument an array class.
881 Return value: pointer to the array or NULL if no memory is available
883 *******************************************************************************/
885 java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
887 arraydescriptor *desc;
892 #if defined(ENABLE_RT_TIMING)
893 struct timespec time_start, time_end;
896 RT_TIMING_GET_TIME(time_start);
898 desc = arrayclass->vftbl->arraydesc;
899 dataoffset = desc->dataoffset;
900 componentsize = desc->componentsize;
903 exceptions_throw_negativearraysizeexception();
907 actualsize = dataoffset + size * componentsize;
909 /* check for overflow */
911 if (((u4) actualsize) < ((u4) size)) {
912 exceptions_throw_outofmemoryerror();
916 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
921 a->objheader.vftbl = arrayclass->vftbl;
923 #if defined(ENABLE_THREADS)
924 lock_init_object_lock(&a->objheader);
927 LLNI_array_size(a) = size;
929 RT_TIMING_GET_TIME(time_end);
930 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
936 /* builtin_anewarray ***********************************************************
938 Creates an array of references to the given class type on the heap.
940 Return value: pointer to the array or NULL if no memory is
943 *******************************************************************************/
945 java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
947 classinfo *arrayclass;
949 /* is class loaded */
951 assert(componentclass->state & CLASS_LOADED);
953 /* is class linked */
955 if (!(componentclass->state & CLASS_LINKED))
956 if (!link_class(componentclass))
959 arrayclass = class_array_of(componentclass, true);
964 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
968 /* builtin_newarray_boolean ****************************************************
970 Creates an array of bytes on the heap. The array is designated as
971 an array of booleans (important for casts)
973 Return value: pointer to the array or NULL if no memory is
976 *******************************************************************************/
978 java_handle_booleanarray_t *builtin_newarray_boolean(s4 size)
980 return (java_handle_booleanarray_t *)
981 builtin_newarray(size,
982 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
986 /* builtin_newarray_byte *******************************************************
988 Creates an array of 8 bit Integers on the heap.
990 Return value: pointer to the array or NULL if no memory is
993 *******************************************************************************/
995 java_handle_bytearray_t *builtin_newarray_byte(s4 size)
997 return (java_handle_bytearray_t *)
998 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
1002 /* builtin_newarray_char *******************************************************
1004 Creates an array of characters on the heap.
1006 Return value: pointer to the array or NULL if no memory is
1009 *******************************************************************************/
1011 java_handle_chararray_t *builtin_newarray_char(s4 size)
1013 return (java_handle_chararray_t *)
1014 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1018 /* builtin_newarray_short ******************************************************
1020 Creates an array of 16 bit Integers on the heap.
1022 Return value: pointer to the array or NULL if no memory is
1025 *******************************************************************************/
1027 java_handle_shortarray_t *builtin_newarray_short(s4 size)
1029 return (java_handle_shortarray_t *)
1030 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1034 /* builtin_newarray_int ********************************************************
1036 Creates an array of 32 bit Integers on the heap.
1038 Return value: pointer to the array or NULL if no memory is
1041 *******************************************************************************/
1043 java_handle_intarray_t *builtin_newarray_int(s4 size)
1045 return (java_handle_intarray_t *)
1046 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1050 /* builtin_newarray_long *******************************************************
1052 Creates an array of 64 bit Integers on the heap.
1054 Return value: pointer to the array or NULL if no memory is
1057 *******************************************************************************/
1059 java_handle_longarray_t *builtin_newarray_long(s4 size)
1061 return (java_handle_longarray_t *)
1062 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1066 /* builtin_newarray_float ******************************************************
1068 Creates an array of 32 bit IEEE floats on the heap.
1070 Return value: pointer to the array or NULL if no memory is
1073 *******************************************************************************/
1075 java_handle_floatarray_t *builtin_newarray_float(s4 size)
1077 return (java_handle_floatarray_t *)
1078 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1082 /* builtin_newarray_double *****************************************************
1084 Creates an array of 64 bit IEEE floats on the heap.
1086 Return value: pointer to the array or NULL if no memory is
1089 *******************************************************************************/
1091 java_handle_doublearray_t *builtin_newarray_double(s4 size)
1093 return (java_handle_doublearray_t *)
1094 builtin_newarray(size,
1095 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1099 /* builtin_multianewarray_intern ***********************************************
1101 Creates a multi-dimensional array on the heap. The dimensions are
1102 passed in an array of longs.
1105 n.............number of dimensions to create
1106 arrayclass....the array class
1107 dims..........array containing the size of each dimension to create
1109 Return value: pointer to the array or NULL if no memory is
1112 ******************************************************************************/
1114 static java_handle_t *builtin_multianewarray_intern(int n,
1115 classinfo *arrayclass,
1120 classinfo *componentclass;
1123 /* create this dimension */
1125 size = (s4) dims[0];
1126 a = builtin_newarray(size, arrayclass);
1131 /* if this is the last dimension return */
1136 /* get the class of the components to create */
1138 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1140 /* The verifier guarantees that the dimension count is in the range. */
1142 /* create the component arrays */
1144 for (i = 0; i < size; i++) {
1146 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1147 /* we save an s4 to a s8 slot, 8-byte aligned */
1149 builtin_multianewarray_intern(n, componentclass, dims + 2);
1151 builtin_multianewarray_intern(n, componentclass, dims + 1);
1157 LLNI_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1164 /* builtin_multianewarray ******************************************************
1166 Wrapper for builtin_multianewarray_intern which checks all
1167 dimensions before we start allocating.
1169 ******************************************************************************/
1171 java_handle_objectarray_t *builtin_multianewarray(int n, classinfo *arrayclass,
1177 /* check all dimensions before doing anything */
1179 for (i = 0; i < n; i++) {
1180 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1181 /* we save an s4 to a s8 slot, 8-byte aligned */
1182 size = (s4) dims[i * 2];
1184 size = (s4) dims[i];
1188 exceptions_throw_negativearraysizeexception();
1193 /* now call the real function */
1195 return (java_handle_objectarray_t *)
1196 builtin_multianewarray_intern(n, arrayclass, dims);
1200 /*****************************************************************************
1203 Various functions for printing a message at method entry or exit (for
1206 *****************************************************************************/
1208 /* builtin_print_argument ******************************************************
1210 Prints arguments and return values for the call trace.
1212 *******************************************************************************/
1214 #if !defined(NDEBUG)
1215 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1216 typedesc *paramtype, s8 value)
1224 switch (paramtype->type) {
1227 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1232 #if SIZEOF_VOID_P == 4
1233 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1235 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1240 #if defined(__S390__)
1242 /* The below won't work on S390 */
1246 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1251 #if SIZEOF_VOID_P == 4
1252 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1254 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1259 #if SIZEOF_VOID_P == 4
1260 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1262 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1265 /* cast to java.lang.Object */
1267 o = (java_object_t *) (ptrint) value;
1269 /* check return argument for java.lang.Class or java.lang.String */
1272 if (o->vftbl->class == class_java_lang_String) {
1273 /* get java.lang.String object and the length of the
1276 u = javastring_toutf(o, false);
1278 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1280 /* realloc memory for string length */
1282 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1285 /* convert to utf8 string and strcat it to the logtext */
1287 strcat(logtext, " (String = \"");
1288 utf_cat(logtext, u);
1289 strcat(logtext, "\")");
1292 if (o->vftbl->class == class_java_lang_Class) {
1293 /* if the object returned is a java.lang.Class
1294 cast it to classinfo structure and get the name
1297 c = (classinfo *) o;
1302 /* if the object returned is not a java.lang.String or
1303 a java.lang.Class just print the name of the class */
1305 u = o->vftbl->class->name;
1308 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1310 /* realloc memory for string length */
1312 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1315 /* strcat to the logtext */
1317 strcat(logtext, " (Class = \"");
1318 utf_cat_classname(logtext, u);
1319 strcat(logtext, "\")");
1326 #endif /* !defined(NDEBUG) */
1328 /* builtin_verbosecall_enter ***************************************************
1330 Print method call with arguments for -verbose:call.
1332 *******************************************************************************/
1334 #if !defined(NDEBUG)
1336 #ifdef TRACE_ARGS_NUM
1337 void builtin_verbosecall_enter(s8 a0, s8 a1,
1338 # if TRACE_ARGS_NUM >= 4
1341 # if TRACE_ARGS_NUM >= 6
1344 # if TRACE_ARGS_NUM == 8
1358 #if defined(ENABLE_DEBUG_FILTER)
1359 if (! show_filters_test_verbosecall_enter(m)) return;
1362 #if defined(ENABLE_VMLOG)
1363 vmlog_cacao_enter_method(m);
1369 methodindent = TRACEJAVACALLINDENT;
1371 /* calculate message length */
1374 strlen("4294967295 ") +
1375 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1377 strlen("called: ") +
1378 utf_bytes(m->class->name) +
1380 utf_bytes(m->name) +
1381 utf_bytes(m->descriptor);
1383 /* Actually it's not possible to have all flags printed, but:
1388 strlen(" PRIVATE") +
1389 strlen(" PROTECTED") +
1392 strlen(" SYNCHRONIZED") +
1393 strlen(" VOLATILE") +
1394 strlen(" TRANSIENT") +
1396 strlen(" INTERFACE") +
1397 strlen(" ABSTRACT");
1399 /* add maximal argument length */
1403 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1404 strlen("...(255)") +
1407 /* allocate memory */
1409 dumpsize = dump_size();
1411 logtext = DMNEW(char, logtextlen);
1413 callcount = ++TRACEJAVACALLCOUNT;
1415 sprintf(logtext, "%10d ", callcount);
1416 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1418 pos = strlen(logtext);
1420 for (i = 0; i < methodindent; i++)
1421 logtext[pos++] = '\t';
1423 strcpy(logtext + pos, "called: ");
1425 utf_cat_classname(logtext, m->class->name);
1426 strcat(logtext, ".");
1427 utf_cat(logtext, m->name);
1428 utf_cat(logtext, m->descriptor);
1430 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1431 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1432 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1433 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1434 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1435 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1436 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1437 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1438 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1439 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1440 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1442 strcat(logtext, "(");
1444 if (md->paramcount >= 1) {
1445 logtext = builtin_print_argument(logtext, &logtextlen,
1446 &md->paramtypes[0], a0);
1449 if (md->paramcount >= 2) {
1450 strcat(logtext, ", ");
1452 logtext = builtin_print_argument(logtext, &logtextlen,
1453 &md->paramtypes[1], a1);
1456 #if TRACE_ARGS_NUM >= 4
1457 if (md->paramcount >= 3) {
1458 strcat(logtext, ", ");
1460 logtext = builtin_print_argument(logtext, &logtextlen,
1461 &md->paramtypes[2], a2);
1464 if (md->paramcount >= 4) {
1465 strcat(logtext, ", ");
1467 logtext = builtin_print_argument(logtext, &logtextlen,
1468 &md->paramtypes[3], a3);
1472 #if TRACE_ARGS_NUM >= 6
1473 if (md->paramcount >= 5) {
1474 strcat(logtext, ", ");
1476 logtext = builtin_print_argument(logtext, &logtextlen,
1477 &md->paramtypes[4], a4);
1480 if (md->paramcount >= 6) {
1481 strcat(logtext, ", ");
1483 logtext = builtin_print_argument(logtext, &logtextlen,
1484 &md->paramtypes[5], a5);
1488 #if TRACE_ARGS_NUM == 8
1489 if (md->paramcount >= 7) {
1490 strcat(logtext, ", ");
1492 logtext = builtin_print_argument(logtext, &logtextlen,
1493 &md->paramtypes[6], a6);
1496 if (md->paramcount >= 8) {
1497 strcat(logtext, ", ");
1499 logtext = builtin_print_argument(logtext, &logtextlen,
1500 &md->paramtypes[7], a7);
1504 if (md->paramcount > 8) {
1505 sprintf(logtext + strlen(logtext), ", ...(%d)",
1506 md->paramcount - TRACE_ARGS_NUM);
1509 strcat(logtext, ")");
1513 /* release memory */
1515 dump_release(dumpsize);
1517 TRACEJAVACALLINDENT++;
1521 #endif /* !defined(NDEBUG) */
1524 /* builtin_verbosecall_exit ****************************************************
1526 Print method exit for -verbose:call.
1528 *******************************************************************************/
1530 #if !defined(NDEBUG)
1531 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1542 #if defined(ENABLE_DEBUG_FILTER)
1543 if (! show_filters_test_verbosecall_exit(m)) return;
1546 #if defined(ENABLE_VMLOG)
1547 vmlog_cacao_leave_method(m);
1553 /* outdent the log message */
1555 if (TRACEJAVACALLINDENT)
1556 TRACEJAVACALLINDENT--;
1558 log_text("WARNING: unmatched methodindent--");
1560 methodindent = TRACEJAVACALLINDENT;
1562 /* calculate message length */
1565 strlen("4294967295 ") +
1566 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1568 strlen("finished: ") +
1569 utf_bytes(m->class->name) +
1571 utf_bytes(m->name) +
1572 utf_bytes(m->descriptor) +
1573 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1575 /* add maximal argument length */
1577 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1579 /* allocate memory */
1581 dumpsize = dump_size();
1583 logtext = DMNEW(char, logtextlen);
1585 /* generate the message */
1587 sprintf(logtext, " ");
1588 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1590 pos = strlen(logtext);
1592 for (i = 0; i < methodindent; i++)
1593 logtext[pos++] = '\t';
1595 strcpy(logtext + pos, "finished: ");
1596 utf_cat_classname(logtext, m->class->name);
1597 strcat(logtext, ".");
1598 utf_cat(logtext, m->name);
1599 utf_cat(logtext, m->descriptor);
1601 if (!IS_VOID_TYPE(md->returntype.type)) {
1602 strcat(logtext, "->");
1604 switch (md->returntype.type) {
1621 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1626 /* release memory */
1628 dump_release(dumpsize);
1631 #endif /* !defined(NDEBUG) */
1634 #if defined(ENABLE_CYCLES_STATS)
1635 void builtin_print_cycles_stats(FILE *file)
1637 fprintf(file,"builtin cylce count statistics:\n");
1639 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1640 CYCLES_STATS_PRINT(builtin_new ,file);
1644 #endif /* defined(ENABLE_CYCLES_STATS) */
1647 /*****************************************************************************
1648 MISCELLANEOUS HELPER FUNCTIONS
1649 *****************************************************************************/
1653 /*********** Functions for integer divisions *****************************
1655 On some systems (eg. DEC ALPHA), integer division is not supported by the
1656 CPU. These helper functions implement the missing functionality.
1658 ******************************************************************************/
1660 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1661 s4 builtin_idiv(s4 a, s4 b)
1670 s4 builtin_irem(s4 a, s4 b)
1678 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1681 /* functions for long arithmetics **********************************************
1683 On systems where 64 bit Integers are not supported by the CPU,
1684 these functions are needed.
1686 ******************************************************************************/
1688 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1689 s8 builtin_ladd(s8 a, s8 b)
1702 s8 builtin_lsub(s8 a, s8 b)
1715 s8 builtin_lneg(s8 a)
1727 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1730 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1731 s8 builtin_lmul(s8 a, s8 b)
1743 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1746 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1747 s8 builtin_ldiv(s8 a, s8 b)
1760 s8 builtin_lrem(s8 a, s8 b)
1772 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1775 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1776 s8 builtin_lshl(s8 a, s4 b)
1789 s8 builtin_lshr(s8 a, s4 b)
1802 s8 builtin_lushr(s8 a, s4 b)
1807 c = ((u8) a) >> (b & 63);
1814 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1817 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1818 s8 builtin_land(s8 a, s8 b)
1831 s8 builtin_lor(s8 a, s8 b)
1844 s8 builtin_lxor(s8 a, s8 b)
1856 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1859 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1860 s4 builtin_lcmp(s8 a, s8 b)
1874 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1877 /* functions for unsupported floating instructions ****************************/
1879 /* used to convert FLT_xxx defines into float values */
1881 static inline float intBitsToFloat(s4 i)
1890 /* used to convert DBL_xxx defines into double values */
1892 static inline float longBitsToDouble(s8 l)
1902 float builtin_fadd(float a, float b)
1904 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1905 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1916 if (copysignf(1.0, a) == copysignf(1.0, b))
1919 return intBitsToFloat(FLT_NAN);
1925 float builtin_fsub(float a, float b)
1927 return builtin_fadd(a, builtin_fneg(b));
1931 float builtin_fmul(float a, float b)
1933 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1934 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1936 if (finitef(b)) return a * b;
1938 if (a == 0) return intBitsToFloat(FLT_NAN);
1939 else return copysignf(b, copysignf(1.0, b)*a);
1944 if (b == 0) return intBitsToFloat(FLT_NAN);
1945 else return copysignf(a, copysignf(1.0, a)*b);
1948 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1954 /* builtin_ddiv ****************************************************************
1956 Implementation as described in VM Spec.
1958 *******************************************************************************/
1960 float builtin_fdiv(float a, float b)
1964 /* If neither value1' nor value2' is NaN, the sign of the result */
1965 /* is positive if both values have the same sign, negative if the */
1966 /* values have different signs. */
1972 /* If either value1' or value2' is NaN, the result is NaN. */
1974 return intBitsToFloat(FLT_NAN);
1977 /* Division of a finite value by an infinity results in a */
1978 /* signed zero, with the sign-producing rule just given. */
1980 /* is sign equal? */
1982 if (copysignf(1.0, a) == copysignf(1.0, b))
1991 /* If either value1' or value2' is NaN, the result is NaN. */
1993 return intBitsToFloat(FLT_NAN);
1995 } else if (finitef(b)) {
1996 /* Division of an infinity by a finite value results in a signed */
1997 /* infinity, with the sign-producing rule just given. */
1999 /* is sign equal? */
2001 if (copysignf(1.0, a) == copysignf(1.0, b))
2002 return intBitsToFloat(FLT_POSINF);
2004 return intBitsToFloat(FLT_NEGINF);
2007 /* Division of an infinity by an infinity results in NaN. */
2009 return intBitsToFloat(FLT_NAN);
2015 float builtin_fneg(float a)
2017 if (isnanf(a)) return a;
2019 if (finitef(a)) return -a;
2020 else return copysignf(a, -copysignf(1.0, a));
2023 #endif /* !SUPPORT_FLOAT */
2026 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2027 s4 builtin_fcmpl(float a, float b)
2035 if (!finitef(a) || !finitef(b)) {
2036 a = finitef(a) ? 0 : copysignf(1.0, a);
2037 b = finitef(b) ? 0 : copysignf(1.0, b);
2050 s4 builtin_fcmpg(float a, float b)
2052 if (isnanf(a)) return 1;
2053 if (isnanf(b)) return 1;
2054 if (!finitef(a) || !finitef(b)) {
2055 a = finitef(a) ? 0 : copysignf(1.0, a);
2056 b = finitef(b) ? 0 : copysignf(1.0, b);
2058 if (a > b) return 1;
2059 if (a == b) return 0;
2062 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2065 float builtin_frem(float a, float b)
2071 /* functions for unsupported double instructions ******************************/
2074 double builtin_dadd(double a, double b)
2076 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2077 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2079 if (finite(b)) return a + b;
2083 if (finite(b)) return a;
2085 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2086 else return longBitsToDouble(DBL_NAN);
2092 double builtin_dsub(double a, double b)
2094 return builtin_dadd(a, builtin_dneg(b));
2098 double builtin_dmul(double a, double b)
2100 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2101 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2103 if (finite(b)) return a * b;
2105 if (a == 0) return longBitsToDouble(DBL_NAN);
2106 else return copysign(b, copysign(1.0, b) * a);
2111 if (b == 0) return longBitsToDouble(DBL_NAN);
2112 else return copysign(a, copysign(1.0, a) * b);
2115 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2121 /* builtin_ddiv ****************************************************************
2123 Implementation as described in VM Spec.
2125 *******************************************************************************/
2127 double builtin_ddiv(double a, double b)
2131 /* If neither value1' nor value2' is NaN, the sign of the result */
2132 /* is positive if both values have the same sign, negative if the */
2133 /* values have different signs. */
2139 /* If either value1' or value2' is NaN, the result is NaN. */
2141 return longBitsToDouble(DBL_NAN);
2144 /* Division of a finite value by an infinity results in a */
2145 /* signed zero, with the sign-producing rule just given. */
2147 /* is sign equal? */
2149 if (copysign(1.0, a) == copysign(1.0, b))
2158 /* If either value1' or value2' is NaN, the result is NaN. */
2160 return longBitsToDouble(DBL_NAN);
2162 } else if (finite(b)) {
2163 /* Division of an infinity by a finite value results in a signed */
2164 /* infinity, with the sign-producing rule just given. */
2166 /* is sign equal? */
2168 if (copysign(1.0, a) == copysign(1.0, b))
2169 return longBitsToDouble(DBL_POSINF);
2171 return longBitsToDouble(DBL_NEGINF);
2174 /* Division of an infinity by an infinity results in NaN. */
2176 return longBitsToDouble(DBL_NAN);
2182 /* builtin_dneg ****************************************************************
2184 Implemented as described in VM Spec.
2186 *******************************************************************************/
2188 double builtin_dneg(double a)
2191 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2198 /* If the operand is a zero, the result is the zero of opposite */
2204 /* If the operand is an infinity, the result is the infinity of */
2205 /* opposite sign. */
2207 return copysign(a, -copysign(1.0, a));
2211 #endif /* !SUPPORT_DOUBLE */
2214 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2215 s4 builtin_dcmpl(double a, double b)
2223 if (!finite(a) || !finite(b)) {
2224 a = finite(a) ? 0 : copysign(1.0, a);
2225 b = finite(b) ? 0 : copysign(1.0, b);
2238 s4 builtin_dcmpg(double a, double b)
2246 if (!finite(a) || !finite(b)) {
2247 a = finite(a) ? 0 : copysign(1.0, a);
2248 b = finite(b) ? 0 : copysign(1.0, b);
2259 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2262 double builtin_drem(double a, double b)
2268 /* conversion operations ******************************************************/
2271 s8 builtin_i2l(s4 i)
2283 s4 builtin_l2i(s8 l)
2294 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2295 float builtin_i2f(s4 a)
2297 float f = (float) a;
2300 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2303 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2304 double builtin_i2d(s4 a)
2306 double d = (double) a;
2309 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2312 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2313 float builtin_l2f(s8 a)
2316 float f = (float) a;
2322 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2325 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2326 double builtin_l2d(s8 a)
2329 double d = (double) a;
2335 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2338 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2339 s4 builtin_f2i(float a)
2343 i = builtin_d2i((double) a);
2354 if (a < (-2147483648))
2355 return (-2147483648);
2358 f = copysignf((float) 1.0, a);
2361 return (-2147483648); */
2363 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2366 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2367 s8 builtin_f2l(float a)
2371 l = builtin_d2l((double) a);
2378 if (a > 9223372036854775807L)
2379 return 9223372036854775807L;
2380 if (a < (-9223372036854775808L))
2381 return (-9223372036854775808L);
2386 f = copysignf((float) 1.0, a);
2388 return 9223372036854775807L;
2389 return (-9223372036854775808L); */
2391 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2394 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2395 s4 builtin_d2i(double a)
2400 if (a >= 2147483647)
2402 if (a <= (-2147483647-1))
2403 return (-2147483647-1);
2408 d = copysign(1.0, a);
2411 return (-2147483647-1);
2413 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2416 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2417 s8 builtin_d2l(double a)
2422 if (a >= 9223372036854775807LL)
2423 return 9223372036854775807LL;
2424 if (a <= (-9223372036854775807LL-1))
2425 return (-9223372036854775807LL-1);
2430 d = copysign(1.0, a);
2432 return 9223372036854775807LL;
2433 return (-9223372036854775807LL-1);
2435 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2438 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2439 double builtin_f2d(float a)
2441 if (finitef(a)) return (double) a;
2444 return longBitsToDouble(DBL_NAN);
2446 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2450 float builtin_d2f(double a)
2456 return intBitsToFloat(FLT_NAN);
2458 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2461 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2464 /* builtin_arraycopy ***********************************************************
2466 Builtin for java.lang.System.arraycopy.
2468 ATTENTION: This builtin function returns a boolean value to signal
2469 the ICMD_BUILTIN if there was an exception.
2471 *******************************************************************************/
2473 bool builtin_arraycopy(java_handle_t *src, s4 srcStart,
2474 java_handle_t *dest, s4 destStart, s4 len)
2476 arraydescriptor *sdesc;
2477 arraydescriptor *ddesc;
2480 if ((src == NULL) || (dest == NULL)) {
2481 exceptions_throw_nullpointerexception();
2485 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2486 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2488 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2489 exceptions_throw_arraystoreexception();
2493 /* we try to throw exception with the same message as SUN does */
2495 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2496 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2497 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2498 exceptions_throw_arrayindexoutofboundsexception();
2502 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2503 /* We copy primitive values or references of exactly the same type */
2505 s4 dataoffset = sdesc->dataoffset;
2506 s4 componentsize = sdesc->componentsize;
2508 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2509 ((u1 *) src) + dataoffset + componentsize * srcStart,
2510 (size_t) len * componentsize);
2513 /* We copy references of different type */
2515 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2516 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2518 if (destStart <= srcStart) {
2519 for (i = 0; i < len; i++) {
2522 LLNI_objectarray_element_get(oas, srcStart + i, o);
2524 if (!builtin_canstore(oad, o))
2527 LLNI_objectarray_element_set(oad, destStart + i, o);
2531 /* XXX this does not completely obey the specification!
2532 If an exception is thrown only the elements above the
2533 current index have been copied. The specification
2534 requires that only the elements *below* the current
2535 index have been copied before the throw. */
2537 for (i = len - 1; i >= 0; i--) {
2540 LLNI_objectarray_element_get(oas, srcStart + i, o);
2542 if (!builtin_canstore(oad, o))
2545 LLNI_objectarray_element_set(oad, destStart + i, o);
2554 /* builtin_nanotime ************************************************************
2556 Return the current time in nanoseconds.
2558 *******************************************************************************/
2560 s8 builtin_nanotime(void)
2565 if (gettimeofday(&tv, NULL) == -1)
2566 vm_abort("gettimeofday failed: %s", strerror(errno));
2568 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2570 return usecs * 1000;
2574 /* builtin_currenttimemillis ***************************************************
2576 Return the current time in milliseconds.
2578 *******************************************************************************/
2580 s8 builtin_currenttimemillis(void)
2584 msecs = builtin_nanotime() / 1000 / 1000;
2590 /* builtin_clone ***************************************************************
2592 Function for cloning objects or arrays.
2594 *******************************************************************************/
2596 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2598 arraydescriptor *ad;
2602 java_handle_t *co; /* cloned object header */
2604 /* get the array descriptor */
2606 ad = LLNI_vftbl_direct(o)->arraydesc;
2608 /* we are cloning an array */
2611 ah = (java_handle_t *) o;
2613 size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah);
2615 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2620 MCOPY(co, o, u1, size);
2622 #if defined(ENABLE_GC_CACAO)
2623 heap_init_objectheader(co, size);
2626 #if defined(ENABLE_THREADS)
2627 lock_init_object_lock(co);
2633 /* we are cloning a non-array */
2635 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2636 exceptions_throw_clonenotsupportedexception();
2640 /* get the class of the object */
2642 LLNI_class_get(o, c);
2644 /* create new object */
2646 co = builtin_new(c);
2651 MCOPY(co, o, u1, c->instancesize);
2653 #if defined(ENABLE_GC_CACAO)
2654 heap_init_objectheader(co, c->instancesize);
2657 #if defined(ENABLE_THREADS)
2658 lock_init_object_lock(co);
2664 #if defined(ENABLE_VMLOG)
2666 #include <vmlog_cacao.c>
2671 * These are local overrides for various environment variables in Emacs.
2672 * Please do not remove this and leave it at the end of the file, where
2673 * Emacs will automagically detect them.
2674 * ---------------------------------------------------------------------
2677 * indent-tabs-mode: t
2681 * vim:noexpandtab:sw=4:ts=4: