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;
112 /* mark start of dump memory area */
114 dumpsize = dump_size();
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 */
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 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 */
218 dump_release(dumpsize);
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 /* initialize the builtin tables */
271 if (!builtintable_init())
274 /* sort builtin tables */
276 builtintable_sort_automatic();
282 /* builtintable_get_internal ***************************************************
284 Finds an entry in the builtintable for internal functions and
285 returns the a pointer to the structure.
287 *******************************************************************************/
289 builtintable_entry *builtintable_get_internal(functionptr fp)
291 builtintable_entry *bte;
293 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
302 /* builtintable_get_automatic **************************************************
304 Finds an entry in the builtintable for functions which are replaced
305 automatically and returns the a pointer to the structure.
307 *******************************************************************************/
309 builtintable_entry *builtintable_get_automatic(s4 opcode)
311 builtintable_entry *first;
312 builtintable_entry *last;
313 builtintable_entry *middle;
317 /* calculate table size statically (`- 1' comment see builtintable.inc) */
319 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
321 first = builtintable_automatic;
322 last = builtintable_automatic + entries;
324 while (entries > 0) {
326 middle = first + half;
328 if (middle->opcode < opcode) {
336 return (first != last ? first : NULL);
340 /* builtintable_replace_function ***********************************************
344 *******************************************************************************/
346 #if defined(ENABLE_JIT)
347 bool builtintable_replace_function(void *iptr_)
350 builtintable_entry *bte;
353 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
355 /* get name and descriptor of the function */
358 case ICMD_INVOKESTATIC:
359 /* The instruction MUST be resolved, otherwise we run into
360 lazy loading troubles. Anyway, we should/can only replace
361 very VM-close functions. */
363 if (INSTRUCTION_IS_UNRESOLVED(iptr))
366 mr = iptr->sx.s23.s3.fmiref;
373 /* search the function table */
375 for (bte = builtintable_function; bte->fp != NULL; bte++) {
376 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
377 (mr->name == bte->name) &&
378 (mr->descriptor == bte->descriptor)) {
380 /* set the values in the instruction */
382 iptr->opc = bte->opcode;
383 iptr->sx.s23.s3.bte = bte;
385 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
386 iptr->flags.bits |= INS_FLAG_CHECK;
388 iptr->flags.bits &= ~INS_FLAG_CHECK;
396 #endif /* defined(ENABLE_JIT) */
399 /*****************************************************************************
401 *****************************************************************************/
403 /* builtin_instanceof **********************************************************
405 Checks if an object is an instance of some given class (or subclass
406 of that class). If class is an interface, checks if the interface
409 Return value: 1 ... o is an instance of class or implements the interface
410 0 ... otherwise or if o == NULL
412 *******************************************************************************/
414 s4 builtin_instanceof(java_handle_t *o, classinfo *class)
421 LLNI_class_get(o, c);
423 return class_isanysubclass(c, class);
428 /* builtin_checkcast ***********************************************************
430 The same as builtin_instanceof except that 1 is returned when o ==
433 *******************************************************************************/
435 s4 builtin_checkcast(java_handle_t *o, classinfo *class)
442 LLNI_class_get(o, c);
444 if (class_isanysubclass(c, class))
451 /* builtin_descriptorscompatible ***********************************************
453 Checks if two array type descriptors are assignment compatible
455 Return value: 1 ... target = desc is possible
458 *******************************************************************************/
460 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
461 arraydescriptor *target)
466 if (desc->arraytype != target->arraytype)
469 if (desc->arraytype != ARRAYTYPE_OBJECT)
472 /* {both arrays are arrays of references} */
474 if (desc->dimension == target->dimension) {
475 /* an array which contains elements of interface types is
476 allowed to be casted to Object (JOWENN)*/
478 if ((desc->elementvftbl->baseval < 0) &&
479 (target->elementvftbl->baseval == 1))
482 return class_isanysubclass(desc->elementvftbl->class,
483 target->elementvftbl->class);
486 if (desc->dimension < target->dimension)
489 /* {desc has higher dimension than target} */
491 return class_isanysubclass(pseudo_class_Arraystub,
492 target->elementvftbl->class);
496 /* builtin_arraycheckcast ******************************************************
498 Checks if an object is really a subtype of the requested array
499 type. The object has to be an array to begin with. For simple
500 arrays (int, short, double, etc.) the types have to match exactly.
501 For arrays of objects, the type of elements in the array has to be
502 a subtype (or the same type) of the requested element type. For
503 arrays of arrays (which in turn can again be arrays of arrays), the
504 types at the lowest level have to satisfy the corresponding sub
507 *******************************************************************************/
509 s4 builtin_arraycheckcast(java_handle_t *o, classinfo *targetclass)
511 arraydescriptor *desc;
516 desc = LLNI_vftbl_direct(o)->arraydesc;
521 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
525 s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass)
530 return builtin_arraycheckcast(o, targetclass);
534 /* builtin_throw_exception *****************************************************
536 Sets the exceptionptr with the thrown exception and prints some
537 debugging information. Called from asm_vm_call_method.
539 *******************************************************************************/
541 void *builtin_throw_exception(java_object_t *xptr)
544 /* print exception trace */
546 if (opt_TraceExceptions)
547 trace_exception_builtin(xptr);
548 #endif /* !defined(NDEBUG) */
550 /* actually set the exception */
552 exceptions_set_exception(xptr);
554 /* Return a NULL pointer. This is required for vm_call_method to
555 check for an exception. This is for convenience. */
561 /* builtin_canstore ************************************************************
563 Checks, if an object can be stored in an array.
565 Return value: 1 ... possible
566 0 ... otherwise (throws an ArrayStoreException)
568 *******************************************************************************/
570 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
576 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
580 /* if not possible, throw an exception */
583 exceptions_throw_arraystoreexception();
589 s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
591 arraydescriptor *desc;
592 arraydescriptor *valuedesc;
593 vftbl_t *componentvftbl;
602 /* The following is guaranteed (by verifier checks):
604 * *) oa->...vftbl->arraydesc != NULL
605 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
606 * *) o->vftbl is not an interface vftbl
609 desc = oa->header.objheader.vftbl->arraydesc;
610 componentvftbl = desc->componentvftbl;
611 valuevftbl = o->vftbl;
612 valuedesc = valuevftbl->arraydesc;
614 if ((desc->dimension - 1) == 0) {
615 /* {oa is a one-dimensional array} */
616 /* {oa is an array of references} */
618 if (valuevftbl == componentvftbl)
621 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
623 baseval = componentvftbl->baseval;
626 /* an array of interface references */
628 result = ((valuevftbl->interfacetablelength > -baseval) &&
629 (valuevftbl->interfacetable[baseval] != NULL));
632 diffval = valuevftbl->baseval - componentvftbl->baseval;
633 result = diffval <= (uint32_t) componentvftbl->diffval;
636 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
638 else if (valuedesc == NULL) {
639 /* {oa has dimension > 1} */
640 /* {componentvftbl->arraydesc != NULL} */
642 /* check if o is an array */
647 /* {o is an array} */
649 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
658 /* This is an optimized version where a is guaranteed to be one-dimensional */
659 s4 builtin_canstore_onedim (java_objectarray_t *a, java_object_t *o)
661 arraydescriptor *desc;
662 vftbl_t *elementvftbl;
671 /* The following is guaranteed (by verifier checks):
673 * *) a->...vftbl->arraydesc != NULL
674 * *) a->...vftbl->arraydesc->elementvftbl != NULL
675 * *) a->...vftbl->arraydesc->dimension == 1
676 * *) o->vftbl is not an interface vftbl
679 desc = a->header.objheader.vftbl->arraydesc;
680 elementvftbl = desc->elementvftbl;
681 valuevftbl = o->vftbl;
683 /* {a is a one-dimensional array} */
685 if (valuevftbl == elementvftbl)
688 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
690 baseval = elementvftbl->baseval;
693 /* an array of interface references */
694 result = ((valuevftbl->interfacetablelength > -baseval) &&
695 (valuevftbl->interfacetable[baseval] != NULL));
698 diffval = valuevftbl->baseval - elementvftbl->baseval;
699 result = diffval <= (uint32_t) elementvftbl->diffval;
702 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
708 /* This is an optimized version where a is guaranteed to be a
709 * one-dimensional array of a class type */
710 s4 builtin_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
712 vftbl_t *elementvftbl;
720 /* The following is guaranteed (by verifier checks):
722 * *) a->...vftbl->arraydesc != NULL
723 * *) a->...vftbl->arraydesc->elementvftbl != NULL
724 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
725 * *) a->...vftbl->arraydesc->dimension == 1
726 * *) o->vftbl is not an interface vftbl
729 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
730 valuevftbl = o->vftbl;
732 /* {a is a one-dimensional array} */
734 if (valuevftbl == elementvftbl)
737 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
739 diffval = valuevftbl->baseval - elementvftbl->baseval;
740 result = diffval <= (uint32_t) elementvftbl->diffval;
742 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
748 /* builtin_new *****************************************************************
750 Creates a new instance of class c on the heap.
752 Return value: pointer to the object or NULL if no memory is
755 *******************************************************************************/
757 java_handle_t *builtin_new(classinfo *c)
760 #if defined(ENABLE_RT_TIMING)
761 struct timespec time_start, time_end;
763 #if defined(ENABLE_CYCLES_STATS)
764 u8 cycles_start, cycles_end;
767 RT_TIMING_GET_TIME(time_start);
768 CYCLES_STATS_GET(cycles_start);
770 /* is the class loaded */
772 assert(c->state & CLASS_LOADED);
774 /* check if we can instantiate this class */
776 if (c->flags & ACC_ABSTRACT) {
777 exceptions_throw_instantiationerror(c);
781 /* is the class linked */
783 if (!(c->state & CLASS_LINKED))
787 if (!(c->state & CLASS_INITIALIZED)) {
790 log_message_class("Initialize class (from builtin_new): ", c);
793 if (!initialize_class(c))
797 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
805 #if defined(ENABLE_THREADS)
806 lock_init_object_lock(o);
809 CYCLES_STATS_GET(cycles_end);
810 RT_TIMING_GET_TIME(time_end);
812 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
813 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
819 /* builtin_fast_new ************************************************************
821 Creates a new instance of class c on the heap.
823 Return value: pointer to the object or NULL if no fast return
824 is possible for any reason.
826 *******************************************************************************/
828 java_object_t *builtin_fast_new(classinfo *c)
831 #if defined(ENABLE_RT_TIMING)
832 struct timespec time_start, time_end;
834 #if defined(ENABLE_CYCLES_STATS)
835 u8 cycles_start, cycles_end;
838 RT_TIMING_GET_TIME(time_start);
839 CYCLES_STATS_GET(cycles_start);
841 /* is the class loaded */
843 assert(c->state & CLASS_LOADED);
845 /* check if we can instantiate this class */
847 if (c->flags & ACC_ABSTRACT)
850 /* is the class linked */
852 if (!(c->state & CLASS_LINKED))
855 if (!(c->state & CLASS_INITIALIZED))
858 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
859 c->finalizer, false);
866 #if defined(ENABLE_THREADS)
867 lock_init_object_lock(o);
870 CYCLES_STATS_GET(cycles_end);
871 RT_TIMING_GET_TIME(time_end);
873 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
874 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
880 /* builtin_newarray ************************************************************
882 Creates an array with the given vftbl on the heap. This function
883 takes as class argument an array class.
885 Return value: pointer to the array or NULL if no memory is available
887 *******************************************************************************/
889 java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
891 arraydescriptor *desc;
896 #if defined(ENABLE_RT_TIMING)
897 struct timespec time_start, time_end;
900 RT_TIMING_GET_TIME(time_start);
902 desc = arrayclass->vftbl->arraydesc;
903 dataoffset = desc->dataoffset;
904 componentsize = desc->componentsize;
907 exceptions_throw_negativearraysizeexception();
911 actualsize = dataoffset + size * componentsize;
913 /* check for overflow */
915 if (((u4) actualsize) < ((u4) size)) {
916 exceptions_throw_outofmemoryerror();
920 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
925 a->objheader.vftbl = arrayclass->vftbl;
927 #if defined(ENABLE_THREADS)
928 lock_init_object_lock(&a->objheader);
931 LLNI_array_size(a) = size;
933 RT_TIMING_GET_TIME(time_end);
934 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
940 /* builtin_anewarray ***********************************************************
942 Creates an array of references to the given class type on the heap.
944 Return value: pointer to the array or NULL if no memory is
947 *******************************************************************************/
949 java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
951 classinfo *arrayclass;
953 /* is class loaded */
955 assert(componentclass->state & CLASS_LOADED);
957 /* is class linked */
959 if (!(componentclass->state & CLASS_LINKED))
960 if (!link_class(componentclass))
963 arrayclass = class_array_of(componentclass, true);
968 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
972 /* builtin_newarray_boolean ****************************************************
974 Creates an array of bytes on the heap. The array is designated as
975 an array of booleans (important for casts)
977 Return value: pointer to the array or NULL if no memory is
980 *******************************************************************************/
982 java_handle_booleanarray_t *builtin_newarray_boolean(s4 size)
984 return (java_handle_booleanarray_t *)
985 builtin_newarray(size,
986 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
990 /* builtin_newarray_byte *******************************************************
992 Creates an array of 8 bit Integers on the heap.
994 Return value: pointer to the array or NULL if no memory is
997 *******************************************************************************/
999 java_handle_bytearray_t *builtin_newarray_byte(s4 size)
1001 return (java_handle_bytearray_t *)
1002 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
1006 /* builtin_newarray_char *******************************************************
1008 Creates an array of characters on the heap.
1010 Return value: pointer to the array or NULL if no memory is
1013 *******************************************************************************/
1015 java_handle_chararray_t *builtin_newarray_char(s4 size)
1017 return (java_handle_chararray_t *)
1018 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1022 /* builtin_newarray_short ******************************************************
1024 Creates an array of 16 bit Integers on the heap.
1026 Return value: pointer to the array or NULL if no memory is
1029 *******************************************************************************/
1031 java_handle_shortarray_t *builtin_newarray_short(s4 size)
1033 return (java_handle_shortarray_t *)
1034 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1038 /* builtin_newarray_int ********************************************************
1040 Creates an array of 32 bit Integers on the heap.
1042 Return value: pointer to the array or NULL if no memory is
1045 *******************************************************************************/
1047 java_handle_intarray_t *builtin_newarray_int(s4 size)
1049 return (java_handle_intarray_t *)
1050 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1054 /* builtin_newarray_long *******************************************************
1056 Creates an array of 64 bit Integers on the heap.
1058 Return value: pointer to the array or NULL if no memory is
1061 *******************************************************************************/
1063 java_handle_longarray_t *builtin_newarray_long(s4 size)
1065 return (java_handle_longarray_t *)
1066 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1070 /* builtin_newarray_float ******************************************************
1072 Creates an array of 32 bit IEEE floats on the heap.
1074 Return value: pointer to the array or NULL if no memory is
1077 *******************************************************************************/
1079 java_handle_floatarray_t *builtin_newarray_float(s4 size)
1081 return (java_handle_floatarray_t *)
1082 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1086 /* builtin_newarray_double *****************************************************
1088 Creates an array of 64 bit IEEE floats on the heap.
1090 Return value: pointer to the array or NULL if no memory is
1093 *******************************************************************************/
1095 java_handle_doublearray_t *builtin_newarray_double(s4 size)
1097 return (java_handle_doublearray_t *)
1098 builtin_newarray(size,
1099 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1103 /* builtin_multianewarray_intern ***********************************************
1105 Creates a multi-dimensional array on the heap. The dimensions are
1106 passed in an array of longs.
1109 n.............number of dimensions to create
1110 arrayclass....the array class
1111 dims..........array containing the size of each dimension to create
1113 Return value: pointer to the array or NULL if no memory is
1116 ******************************************************************************/
1118 static java_handle_t *builtin_multianewarray_intern(int n,
1119 classinfo *arrayclass,
1124 classinfo *componentclass;
1127 /* create this dimension */
1129 size = (s4) dims[0];
1130 a = builtin_newarray(size, arrayclass);
1135 /* if this is the last dimension return */
1140 /* get the class of the components to create */
1142 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1144 /* The verifier guarantees that the dimension count is in the range. */
1146 /* create the component arrays */
1148 for (i = 0; i < size; i++) {
1150 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1151 /* we save an s4 to a s8 slot, 8-byte aligned */
1153 builtin_multianewarray_intern(n, componentclass, dims + 2);
1155 builtin_multianewarray_intern(n, componentclass, dims + 1);
1161 LLNI_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1168 /* builtin_multianewarray ******************************************************
1170 Wrapper for builtin_multianewarray_intern which checks all
1171 dimensions before we start allocating.
1173 ******************************************************************************/
1175 java_handle_objectarray_t *builtin_multianewarray(int n, classinfo *arrayclass,
1181 /* check all dimensions before doing anything */
1183 for (i = 0; i < n; i++) {
1184 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1185 /* we save an s4 to a s8 slot, 8-byte aligned */
1186 size = (s4) dims[i * 2];
1188 size = (s4) dims[i];
1192 exceptions_throw_negativearraysizeexception();
1197 /* now call the real function */
1199 return (java_handle_objectarray_t *)
1200 builtin_multianewarray_intern(n, arrayclass, dims);
1204 /*****************************************************************************
1207 Various functions for printing a message at method entry or exit (for
1210 *****************************************************************************/
1212 /* builtin_print_argument ******************************************************
1214 Prints arguments and return values for the call trace.
1216 *******************************************************************************/
1218 #if !defined(NDEBUG)
1219 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1220 typedesc *paramtype, s8 value)
1228 switch (paramtype->type) {
1231 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1236 #if SIZEOF_VOID_P == 4
1237 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1239 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1244 #if defined(__S390__)
1246 /* The below won't work on S390 */
1250 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1255 #if SIZEOF_VOID_P == 4
1256 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1258 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1263 #if SIZEOF_VOID_P == 4
1264 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1266 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1269 /* cast to java.lang.Object */
1271 o = (java_object_t *) (ptrint) value;
1273 /* check return argument for java.lang.Class or java.lang.String */
1276 if (o->vftbl->class == class_java_lang_String) {
1277 /* get java.lang.String object and the length of the
1280 u = javastring_toutf(o, false);
1282 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1284 /* realloc memory for string length */
1286 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1289 /* convert to utf8 string and strcat it to the logtext */
1291 strcat(logtext, " (String = \"");
1292 utf_cat(logtext, u);
1293 strcat(logtext, "\")");
1296 if (o->vftbl->class == class_java_lang_Class) {
1297 /* if the object returned is a java.lang.Class
1298 cast it to classinfo structure and get the name
1301 c = (classinfo *) o;
1306 /* if the object returned is not a java.lang.String or
1307 a java.lang.Class just print the name of the class */
1309 u = o->vftbl->class->name;
1312 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1314 /* realloc memory for string length */
1316 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1319 /* strcat to the logtext */
1321 strcat(logtext, " (Class = \"");
1322 utf_cat_classname(logtext, u);
1323 strcat(logtext, "\")");
1330 #endif /* !defined(NDEBUG) */
1332 /* builtin_verbosecall_enter ***************************************************
1334 Print method call with arguments for -verbose:call.
1336 *******************************************************************************/
1338 #if !defined(NDEBUG)
1340 #ifdef TRACE_ARGS_NUM
1341 void builtin_verbosecall_enter(s8 a0, s8 a1,
1342 # if TRACE_ARGS_NUM >= 4
1345 # if TRACE_ARGS_NUM >= 6
1348 # if TRACE_ARGS_NUM == 8
1362 #if defined(ENABLE_DEBUG_FILTER)
1363 if (! show_filters_test_verbosecall_enter(m)) return;
1366 #if defined(ENABLE_VMLOG)
1367 vmlog_cacao_enter_method(m);
1373 methodindent = TRACEJAVACALLINDENT;
1375 /* calculate message length */
1378 strlen("4294967295 ") +
1379 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1381 strlen("called: ") +
1382 utf_bytes(m->class->name) +
1384 utf_bytes(m->name) +
1385 utf_bytes(m->descriptor);
1387 /* Actually it's not possible to have all flags printed, but:
1392 strlen(" PRIVATE") +
1393 strlen(" PROTECTED") +
1396 strlen(" SYNCHRONIZED") +
1397 strlen(" VOLATILE") +
1398 strlen(" TRANSIENT") +
1400 strlen(" INTERFACE") +
1401 strlen(" ABSTRACT");
1403 /* add maximal argument length */
1407 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1408 strlen("...(255)") +
1411 /* allocate memory */
1413 dumpsize = dump_size();
1415 logtext = DMNEW(char, logtextlen);
1417 callcount = ++TRACEJAVACALLCOUNT;
1419 sprintf(logtext, "%10d ", callcount);
1420 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1422 pos = strlen(logtext);
1424 for (i = 0; i < methodindent; i++)
1425 logtext[pos++] = '\t';
1427 strcpy(logtext + pos, "called: ");
1429 utf_cat_classname(logtext, m->class->name);
1430 strcat(logtext, ".");
1431 utf_cat(logtext, m->name);
1432 utf_cat(logtext, m->descriptor);
1434 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1435 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1436 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1437 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1438 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1439 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1440 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1441 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1442 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1443 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1444 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1446 strcat(logtext, "(");
1448 if (md->paramcount >= 1) {
1449 logtext = builtin_print_argument(logtext, &logtextlen,
1450 &md->paramtypes[0], a0);
1453 if (md->paramcount >= 2) {
1454 strcat(logtext, ", ");
1456 logtext = builtin_print_argument(logtext, &logtextlen,
1457 &md->paramtypes[1], a1);
1460 #if TRACE_ARGS_NUM >= 4
1461 if (md->paramcount >= 3) {
1462 strcat(logtext, ", ");
1464 logtext = builtin_print_argument(logtext, &logtextlen,
1465 &md->paramtypes[2], a2);
1468 if (md->paramcount >= 4) {
1469 strcat(logtext, ", ");
1471 logtext = builtin_print_argument(logtext, &logtextlen,
1472 &md->paramtypes[3], a3);
1476 #if TRACE_ARGS_NUM >= 6
1477 if (md->paramcount >= 5) {
1478 strcat(logtext, ", ");
1480 logtext = builtin_print_argument(logtext, &logtextlen,
1481 &md->paramtypes[4], a4);
1484 if (md->paramcount >= 6) {
1485 strcat(logtext, ", ");
1487 logtext = builtin_print_argument(logtext, &logtextlen,
1488 &md->paramtypes[5], a5);
1492 #if TRACE_ARGS_NUM == 8
1493 if (md->paramcount >= 7) {
1494 strcat(logtext, ", ");
1496 logtext = builtin_print_argument(logtext, &logtextlen,
1497 &md->paramtypes[6], a6);
1500 if (md->paramcount >= 8) {
1501 strcat(logtext, ", ");
1503 logtext = builtin_print_argument(logtext, &logtextlen,
1504 &md->paramtypes[7], a7);
1508 if (md->paramcount > 8) {
1509 sprintf(logtext + strlen(logtext), ", ...(%d)",
1510 md->paramcount - TRACE_ARGS_NUM);
1513 strcat(logtext, ")");
1517 /* release memory */
1519 dump_release(dumpsize);
1521 TRACEJAVACALLINDENT++;
1525 #endif /* !defined(NDEBUG) */
1528 /* builtin_verbosecall_exit ****************************************************
1530 Print method exit for -verbose:call.
1532 *******************************************************************************/
1534 #if !defined(NDEBUG)
1535 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1546 #if defined(ENABLE_DEBUG_FILTER)
1547 if (! show_filters_test_verbosecall_exit(m)) return;
1550 #if defined(ENABLE_VMLOG)
1551 vmlog_cacao_leave_method(m);
1557 /* outdent the log message */
1559 if (TRACEJAVACALLINDENT)
1560 TRACEJAVACALLINDENT--;
1562 log_text("WARNING: unmatched methodindent--");
1564 methodindent = TRACEJAVACALLINDENT;
1566 /* calculate message length */
1569 strlen("4294967295 ") +
1570 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1572 strlen("finished: ") +
1573 utf_bytes(m->class->name) +
1575 utf_bytes(m->name) +
1576 utf_bytes(m->descriptor) +
1577 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1579 /* add maximal argument length */
1581 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1583 /* allocate memory */
1585 dumpsize = dump_size();
1587 logtext = DMNEW(char, logtextlen);
1589 /* generate the message */
1591 sprintf(logtext, " ");
1592 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1594 pos = strlen(logtext);
1596 for (i = 0; i < methodindent; i++)
1597 logtext[pos++] = '\t';
1599 strcpy(logtext + pos, "finished: ");
1600 utf_cat_classname(logtext, m->class->name);
1601 strcat(logtext, ".");
1602 utf_cat(logtext, m->name);
1603 utf_cat(logtext, m->descriptor);
1605 if (!IS_VOID_TYPE(md->returntype.type)) {
1606 strcat(logtext, "->");
1608 switch (md->returntype.type) {
1625 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1630 /* release memory */
1632 dump_release(dumpsize);
1635 #endif /* !defined(NDEBUG) */
1638 #if defined(ENABLE_CYCLES_STATS)
1639 void builtin_print_cycles_stats(FILE *file)
1641 fprintf(file,"builtin cylce count statistics:\n");
1643 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1644 CYCLES_STATS_PRINT(builtin_new ,file);
1648 #endif /* defined(ENABLE_CYCLES_STATS) */
1651 /*****************************************************************************
1652 MISCELLANEOUS HELPER FUNCTIONS
1653 *****************************************************************************/
1657 /*********** Functions for integer divisions *****************************
1659 On some systems (eg. DEC ALPHA), integer division is not supported by the
1660 CPU. These helper functions implement the missing functionality.
1662 ******************************************************************************/
1664 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1665 s4 builtin_idiv(s4 a, s4 b)
1674 s4 builtin_irem(s4 a, s4 b)
1682 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1685 /* functions for long arithmetics **********************************************
1687 On systems where 64 bit Integers are not supported by the CPU,
1688 these functions are needed.
1690 ******************************************************************************/
1692 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1693 s8 builtin_ladd(s8 a, s8 b)
1706 s8 builtin_lsub(s8 a, s8 b)
1719 s8 builtin_lneg(s8 a)
1731 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1734 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1735 s8 builtin_lmul(s8 a, s8 b)
1747 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1750 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1751 s8 builtin_ldiv(s8 a, s8 b)
1764 s8 builtin_lrem(s8 a, s8 b)
1776 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1779 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1780 s8 builtin_lshl(s8 a, s4 b)
1793 s8 builtin_lshr(s8 a, s4 b)
1806 s8 builtin_lushr(s8 a, s4 b)
1811 c = ((u8) a) >> (b & 63);
1818 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1821 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1822 s8 builtin_land(s8 a, s8 b)
1835 s8 builtin_lor(s8 a, s8 b)
1848 s8 builtin_lxor(s8 a, s8 b)
1860 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1863 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1864 s4 builtin_lcmp(s8 a, s8 b)
1878 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1881 /* functions for unsupported floating instructions ****************************/
1883 /* used to convert FLT_xxx defines into float values */
1885 static inline float intBitsToFloat(s4 i)
1894 /* used to convert DBL_xxx defines into double values */
1896 static inline float longBitsToDouble(s8 l)
1906 float builtin_fadd(float a, float b)
1908 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1909 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1920 if (copysignf(1.0, a) == copysignf(1.0, b))
1923 return intBitsToFloat(FLT_NAN);
1929 float builtin_fsub(float a, float b)
1931 return builtin_fadd(a, builtin_fneg(b));
1935 float builtin_fmul(float a, float b)
1937 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1938 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1940 if (finitef(b)) return a * b;
1942 if (a == 0) return intBitsToFloat(FLT_NAN);
1943 else return copysignf(b, copysignf(1.0, b)*a);
1948 if (b == 0) return intBitsToFloat(FLT_NAN);
1949 else return copysignf(a, copysignf(1.0, a)*b);
1952 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1958 /* builtin_ddiv ****************************************************************
1960 Implementation as described in VM Spec.
1962 *******************************************************************************/
1964 float builtin_fdiv(float a, float b)
1968 /* If neither value1' nor value2' is NaN, the sign of the result */
1969 /* is positive if both values have the same sign, negative if the */
1970 /* values have different signs. */
1976 /* If either value1' or value2' is NaN, the result is NaN. */
1978 return intBitsToFloat(FLT_NAN);
1981 /* Division of a finite value by an infinity results in a */
1982 /* signed zero, with the sign-producing rule just given. */
1984 /* is sign equal? */
1986 if (copysignf(1.0, a) == copysignf(1.0, b))
1995 /* If either value1' or value2' is NaN, the result is NaN. */
1997 return intBitsToFloat(FLT_NAN);
1999 } else if (finitef(b)) {
2000 /* Division of an infinity by a finite value results in a signed */
2001 /* infinity, with the sign-producing rule just given. */
2003 /* is sign equal? */
2005 if (copysignf(1.0, a) == copysignf(1.0, b))
2006 return intBitsToFloat(FLT_POSINF);
2008 return intBitsToFloat(FLT_NEGINF);
2011 /* Division of an infinity by an infinity results in NaN. */
2013 return intBitsToFloat(FLT_NAN);
2019 float builtin_fneg(float a)
2021 if (isnanf(a)) return a;
2023 if (finitef(a)) return -a;
2024 else return copysignf(a, -copysignf(1.0, a));
2027 #endif /* !SUPPORT_FLOAT */
2030 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2031 s4 builtin_fcmpl(float a, float b)
2039 if (!finitef(a) || !finitef(b)) {
2040 a = finitef(a) ? 0 : copysignf(1.0, a);
2041 b = finitef(b) ? 0 : copysignf(1.0, b);
2054 s4 builtin_fcmpg(float a, float b)
2056 if (isnanf(a)) return 1;
2057 if (isnanf(b)) return 1;
2058 if (!finitef(a) || !finitef(b)) {
2059 a = finitef(a) ? 0 : copysignf(1.0, a);
2060 b = finitef(b) ? 0 : copysignf(1.0, b);
2062 if (a > b) return 1;
2063 if (a == b) return 0;
2066 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2069 float builtin_frem(float a, float b)
2075 /* functions for unsupported double instructions ******************************/
2078 double builtin_dadd(double a, double b)
2080 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2081 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2083 if (finite(b)) return a + b;
2087 if (finite(b)) return a;
2089 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2090 else return longBitsToDouble(DBL_NAN);
2096 double builtin_dsub(double a, double b)
2098 return builtin_dadd(a, builtin_dneg(b));
2102 double builtin_dmul(double a, double b)
2104 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2105 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2107 if (finite(b)) return a * b;
2109 if (a == 0) return longBitsToDouble(DBL_NAN);
2110 else return copysign(b, copysign(1.0, b) * a);
2115 if (b == 0) return longBitsToDouble(DBL_NAN);
2116 else return copysign(a, copysign(1.0, a) * b);
2119 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2125 /* builtin_ddiv ****************************************************************
2127 Implementation as described in VM Spec.
2129 *******************************************************************************/
2131 double builtin_ddiv(double a, double b)
2135 /* If neither value1' nor value2' is NaN, the sign of the result */
2136 /* is positive if both values have the same sign, negative if the */
2137 /* values have different signs. */
2143 /* If either value1' or value2' is NaN, the result is NaN. */
2145 return longBitsToDouble(DBL_NAN);
2148 /* Division of a finite value by an infinity results in a */
2149 /* signed zero, with the sign-producing rule just given. */
2151 /* is sign equal? */
2153 if (copysign(1.0, a) == copysign(1.0, b))
2162 /* If either value1' or value2' is NaN, the result is NaN. */
2164 return longBitsToDouble(DBL_NAN);
2166 } else if (finite(b)) {
2167 /* Division of an infinity by a finite value results in a signed */
2168 /* infinity, with the sign-producing rule just given. */
2170 /* is sign equal? */
2172 if (copysign(1.0, a) == copysign(1.0, b))
2173 return longBitsToDouble(DBL_POSINF);
2175 return longBitsToDouble(DBL_NEGINF);
2178 /* Division of an infinity by an infinity results in NaN. */
2180 return longBitsToDouble(DBL_NAN);
2186 /* builtin_dneg ****************************************************************
2188 Implemented as described in VM Spec.
2190 *******************************************************************************/
2192 double builtin_dneg(double a)
2195 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2202 /* If the operand is a zero, the result is the zero of opposite */
2208 /* If the operand is an infinity, the result is the infinity of */
2209 /* opposite sign. */
2211 return copysign(a, -copysign(1.0, a));
2215 #endif /* !SUPPORT_DOUBLE */
2218 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2219 s4 builtin_dcmpl(double a, double b)
2227 if (!finite(a) || !finite(b)) {
2228 a = finite(a) ? 0 : copysign(1.0, a);
2229 b = finite(b) ? 0 : copysign(1.0, b);
2242 s4 builtin_dcmpg(double a, double b)
2250 if (!finite(a) || !finite(b)) {
2251 a = finite(a) ? 0 : copysign(1.0, a);
2252 b = finite(b) ? 0 : copysign(1.0, b);
2263 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2266 double builtin_drem(double a, double b)
2272 /* conversion operations ******************************************************/
2275 s8 builtin_i2l(s4 i)
2287 s4 builtin_l2i(s8 l)
2298 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2299 float builtin_i2f(s4 a)
2301 float f = (float) a;
2304 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2307 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2308 double builtin_i2d(s4 a)
2310 double d = (double) a;
2313 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2316 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2317 float builtin_l2f(s8 a)
2320 float f = (float) a;
2326 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2329 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2330 double builtin_l2d(s8 a)
2333 double d = (double) a;
2339 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2342 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2343 s4 builtin_f2i(float a)
2347 i = builtin_d2i((double) a);
2358 if (a < (-2147483648))
2359 return (-2147483648);
2362 f = copysignf((float) 1.0, a);
2365 return (-2147483648); */
2367 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2370 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2371 s8 builtin_f2l(float a)
2375 l = builtin_d2l((double) a);
2382 if (a > 9223372036854775807L)
2383 return 9223372036854775807L;
2384 if (a < (-9223372036854775808L))
2385 return (-9223372036854775808L);
2390 f = copysignf((float) 1.0, a);
2392 return 9223372036854775807L;
2393 return (-9223372036854775808L); */
2395 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2398 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2399 s4 builtin_d2i(double a)
2404 if (a >= 2147483647)
2406 if (a <= (-2147483647-1))
2407 return (-2147483647-1);
2412 d = copysign(1.0, a);
2415 return (-2147483647-1);
2417 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2420 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2421 s8 builtin_d2l(double a)
2426 if (a >= 9223372036854775807LL)
2427 return 9223372036854775807LL;
2428 if (a <= (-9223372036854775807LL-1))
2429 return (-9223372036854775807LL-1);
2434 d = copysign(1.0, a);
2436 return 9223372036854775807LL;
2437 return (-9223372036854775807LL-1);
2439 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2442 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2443 double builtin_f2d(float a)
2445 if (finitef(a)) return (double) a;
2448 return longBitsToDouble(DBL_NAN);
2450 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2454 float builtin_d2f(double a)
2460 return intBitsToFloat(FLT_NAN);
2462 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2465 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2468 /* builtin_arraycopy ***********************************************************
2470 Builtin for java.lang.System.arraycopy.
2472 ATTENTION: This builtin function returns a boolean value to signal
2473 the ICMD_BUILTIN if there was an exception.
2475 *******************************************************************************/
2477 bool builtin_arraycopy(java_handle_t *src, s4 srcStart,
2478 java_handle_t *dest, s4 destStart, s4 len)
2480 arraydescriptor *sdesc;
2481 arraydescriptor *ddesc;
2484 if ((src == NULL) || (dest == NULL)) {
2485 exceptions_throw_nullpointerexception();
2489 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2490 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2492 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2493 exceptions_throw_arraystoreexception();
2497 /* we try to throw exception with the same message as SUN does */
2499 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2500 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2501 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2502 exceptions_throw_arrayindexoutofboundsexception();
2506 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2507 /* We copy primitive values or references of exactly the same type */
2509 s4 dataoffset = sdesc->dataoffset;
2510 s4 componentsize = sdesc->componentsize;
2512 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2513 ((u1 *) src) + dataoffset + componentsize * srcStart,
2514 (size_t) len * componentsize);
2517 /* We copy references of different type */
2519 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2520 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2522 if (destStart <= srcStart) {
2523 for (i = 0; i < len; i++) {
2526 LLNI_objectarray_element_get(oas, srcStart + i, o);
2528 if (!builtin_canstore(oad, o))
2531 LLNI_objectarray_element_set(oad, destStart + i, o);
2535 /* XXX this does not completely obey the specification!
2536 If an exception is thrown only the elements above the
2537 current index have been copied. The specification
2538 requires that only the elements *below* the current
2539 index have been copied before the throw. */
2541 for (i = len - 1; i >= 0; i--) {
2544 LLNI_objectarray_element_get(oas, srcStart + i, o);
2546 if (!builtin_canstore(oad, o))
2549 LLNI_objectarray_element_set(oad, destStart + i, o);
2558 /* builtin_nanotime ************************************************************
2560 Return the current time in nanoseconds.
2562 *******************************************************************************/
2564 s8 builtin_nanotime(void)
2569 if (gettimeofday(&tv, NULL) == -1)
2570 vm_abort("gettimeofday failed: %s", strerror(errno));
2572 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2574 return usecs * 1000;
2578 /* builtin_currenttimemillis ***************************************************
2580 Return the current time in milliseconds.
2582 *******************************************************************************/
2584 s8 builtin_currenttimemillis(void)
2588 msecs = builtin_nanotime() / 1000 / 1000;
2594 /* builtin_clone ***************************************************************
2596 Function for cloning objects or arrays.
2598 *******************************************************************************/
2600 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2602 arraydescriptor *ad;
2606 java_handle_t *co; /* cloned object header */
2608 /* get the array descriptor */
2610 ad = LLNI_vftbl_direct(o)->arraydesc;
2612 /* we are cloning an array */
2615 ah = (java_handle_t *) o;
2617 size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah);
2619 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2624 MCOPY(co, o, u1, size);
2626 #if defined(ENABLE_GC_CACAO)
2627 heap_init_objectheader(co, size);
2630 #if defined(ENABLE_THREADS)
2631 lock_init_object_lock(co);
2637 /* we are cloning a non-array */
2639 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2640 exceptions_throw_clonenotsupportedexception();
2644 /* get the class of the object */
2646 LLNI_class_get(o, c);
2648 /* create new object */
2650 co = builtin_new(c);
2655 MCOPY(co, o, u1, c->instancesize);
2657 #if defined(ENABLE_GC_CACAO)
2658 heap_init_objectheader(co, c->instancesize);
2661 #if defined(ENABLE_THREADS)
2662 lock_init_object_lock(co);
2668 #if defined(ENABLE_VMLOG)
2670 #include <vmlog_cacao.c>
2675 * These are local overrides for various environment variables in Emacs.
2676 * Please do not remove this and leave it at the end of the file, where
2677 * Emacs will automagically detect them.
2678 * ---------------------------------------------------------------------
2681 * indent-tabs-mode: t
2685 * vim:noexpandtab:sw=4:ts=4: