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"
57 #include "native/include/java_lang_String.h"
58 #include "native/include/java_lang_Throwable.h"
60 #include "threads/lock-common.h"
61 #if defined(ENABLE_THREADS)
62 #include "threads/native/threads.h"
64 #include "threads/none/threads.h"
67 #include "toolbox/logging.h"
68 #include "toolbox/util.h"
71 #include "vm/builtin.h"
72 #include "vm/cycles-stats.h"
73 #include "vm/exceptions.h"
74 #include "vm/global.h"
75 #include "vm/initialize.h"
76 #include "vm/primitive.h"
77 #include "vm/stringlocal.h"
79 #include "vm/jit/asmpart.h"
81 #include "vmcore/class.h"
82 #include "vmcore/linker.h"
83 #include "vmcore/loader.h"
84 #include "vmcore/options.h"
85 #include "vmcore/rt-timing.h"
87 #if defined(ENABLE_VMLOG)
88 #include <vmlog_cacao.h>
91 #if defined(ENABLE_DEBUG_FILTER)
92 # include "vm/jit/show.h"
95 /* include builtin tables *****************************************************/
97 #include "vm/builtintable.inc"
100 CYCLES_STATS_DECLARE(builtin_new ,100,5)
101 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
103 /* builtintable_init ***********************************************************
105 Parse the descriptors of builtin functions and create the parsed
108 *******************************************************************************/
110 static bool builtintable_init(void)
112 descriptor_pool *descpool;
114 builtintable_entry *bte;
116 /* mark start of dump memory area */
118 dumpsize = dump_size();
120 /* create a new descriptor pool */
122 descpool = descriptor_pool_new(class_java_lang_Object);
124 /* add some entries we need */
126 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
129 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
132 /* first add all descriptors to the pool */
134 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
135 /* create a utf8 string from descriptor */
137 bte->descriptor = utf_new_char(bte->cdescriptor);
139 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
140 /* release dump area */
142 dump_release(dumpsize);
148 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
149 bte->descriptor = utf_new_char(bte->cdescriptor);
151 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
152 dump_release(dumpsize);
157 for (bte = builtintable_function; bte->fp != NULL; bte++) {
158 bte->classname = utf_new_char(bte->cclassname);
159 bte->name = utf_new_char(bte->cname);
160 bte->descriptor = utf_new_char(bte->cdescriptor);
162 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
163 dump_release(dumpsize);
168 /* create the class reference table */
170 (void) descriptor_pool_create_classrefs(descpool, NULL);
172 /* allocate space for the parsed descriptors */
174 descriptor_pool_alloc_parsed_descriptors(descpool);
176 /* Now parse all descriptors. NOTE: builtin-functions are treated
177 like static methods (no `this' pointer). */
179 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
181 descriptor_pool_parse_method_descriptor(descpool,
183 ACC_STATIC | ACC_METHOD_BUILTIN,
187 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
189 descriptor_pool_parse_method_descriptor(descpool,
191 ACC_STATIC | ACC_METHOD_BUILTIN,
195 for (bte = builtintable_function; bte->fp != NULL; bte++) {
197 descriptor_pool_parse_method_descriptor(descpool,
199 ACC_STATIC | ACC_METHOD_BUILTIN,
203 /* release dump area */
205 dump_release(dumpsize);
211 /* builtintable_comparator *****************************************************
213 qsort comparator for the automatic builtin table.
215 *******************************************************************************/
217 static int builtintable_comparator(const void *a, const void *b)
219 builtintable_entry *bte1;
220 builtintable_entry *bte2;
222 bte1 = (builtintable_entry *) a;
223 bte2 = (builtintable_entry *) b;
225 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
229 /* builtintable_sort_automatic *************************************************
231 Sorts the automatic builtin table.
233 *******************************************************************************/
235 static void builtintable_sort_automatic(void)
239 /* calculate table size statically (`- 1' comment see builtintable.inc) */
241 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
243 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
244 builtintable_comparator);
248 /* builtin_init ****************************************************************
250 Initialize the global table of builtin functions.
252 *******************************************************************************/
254 bool builtin_init(void)
256 /* initialize the builtin tables */
258 if (!builtintable_init())
261 /* sort builtin tables */
263 builtintable_sort_automatic();
269 /* builtintable_get_internal ***************************************************
271 Finds an entry in the builtintable for internal functions and
272 returns the a pointer to the structure.
274 *******************************************************************************/
276 builtintable_entry *builtintable_get_internal(functionptr fp)
278 builtintable_entry *bte;
280 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
289 /* builtintable_get_automatic **************************************************
291 Finds an entry in the builtintable for functions which are replaced
292 automatically and returns the a pointer to the structure.
294 *******************************************************************************/
296 builtintable_entry *builtintable_get_automatic(s4 opcode)
298 builtintable_entry *first;
299 builtintable_entry *last;
300 builtintable_entry *middle;
304 /* calculate table size statically (`- 1' comment see builtintable.inc) */
306 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
308 first = builtintable_automatic;
309 last = builtintable_automatic + entries;
311 while (entries > 0) {
313 middle = first + half;
315 if (middle->opcode < opcode) {
322 return (first != last ? first : NULL);
326 /* builtintable_replace_function ***********************************************
330 *******************************************************************************/
332 #if defined(ENABLE_JIT)
333 bool builtintable_replace_function(void *iptr_)
336 builtintable_entry *bte;
339 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
341 /* get name and descriptor of the function */
344 case ICMD_INVOKESTATIC:
345 /* The instruction MUST be resolved, otherwise we run into
346 lazy loading troubles. Anyway, we should/can only replace
347 very VM-close functions. */
349 if (INSTRUCTION_IS_UNRESOLVED(iptr))
352 mr = iptr->sx.s23.s3.fmiref;
359 /* search the function table */
361 for (bte = builtintable_function; bte->fp != NULL; bte++) {
362 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
363 (mr->name == bte->name) &&
364 (mr->descriptor == bte->descriptor)) {
366 /* set the values in the instruction */
368 iptr->opc = bte->opcode;
369 iptr->sx.s23.s3.bte = bte;
370 if (bte->checkexception)
371 iptr->flags.bits |= INS_FLAG_CHECK;
373 iptr->flags.bits &= ~INS_FLAG_CHECK;
381 #endif /* defined(ENABLE_JIT) */
384 /*****************************************************************************
386 *****************************************************************************/
388 /* builtin_instanceof **********************************************************
390 Checks if an object is an instance of some given class (or subclass
391 of that class). If class is an interface, checks if the interface
394 Return value: 1 ... o is an instance of class or implements the interface
395 0 ... otherwise or if o == NULL
397 *******************************************************************************/
399 s4 builtin_instanceof(java_handle_t *o, classinfo *class)
404 return class_isanysubclass(o->vftbl->class, class);
409 /* builtin_checkcast ***********************************************************
411 The same as builtin_instanceof except that 1 is returned when o ==
414 *******************************************************************************/
416 s4 builtin_checkcast(java_handle_t *o, classinfo *class)
421 if (class_isanysubclass(o->vftbl->class, class))
428 /* builtin_descriptorscompatible ***********************************************
430 Checks if two array type descriptors are assignment compatible
432 Return value: 1 ... target = desc is possible
435 *******************************************************************************/
437 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
438 arraydescriptor *target)
443 if (desc->arraytype != target->arraytype)
446 if (desc->arraytype != ARRAYTYPE_OBJECT)
449 /* {both arrays are arrays of references} */
451 if (desc->dimension == target->dimension) {
452 /* an array which contains elements of interface types is
453 allowed to be casted to Object (JOWENN)*/
455 if ((desc->elementvftbl->baseval < 0) &&
456 (target->elementvftbl->baseval == 1))
459 return class_isanysubclass(desc->elementvftbl->class,
460 target->elementvftbl->class);
463 if (desc->dimension < target->dimension)
466 /* {desc has higher dimension than target} */
468 return class_isanysubclass(pseudo_class_Arraystub,
469 target->elementvftbl->class);
473 /* builtin_arraycheckcast ******************************************************
475 Checks if an object is really a subtype of the requested array
476 type. The object has to be an array to begin with. For simple
477 arrays (int, short, double, etc.) the types have to match exactly.
478 For arrays of objects, the type of elements in the array has to be
479 a subtype (or the same type) of the requested element type. For
480 arrays of arrays (which in turn can again be arrays of arrays), the
481 types at the lowest level have to satisfy the corresponding sub
484 *******************************************************************************/
486 s4 builtin_arraycheckcast(java_handle_t *o, classinfo *targetclass)
488 arraydescriptor *desc;
493 desc = o->vftbl->arraydesc;
498 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
502 s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass)
507 return builtin_arraycheckcast(o, targetclass);
511 /* builtin_throw_exception *****************************************************
513 Sets the exceptionptr with the thrown exception and prints some
514 debugging information. Called from asm_vm_call_method.
516 *******************************************************************************/
518 void *builtin_throw_exception(java_handle_t *xptr)
521 java_lang_Throwable *t;
528 t = (java_lang_Throwable *) xptr;
530 /* get detail message */
532 LLNI_field_get_ref(t, detailMessage, s);
534 /* calculate message length */
536 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
540 utf_bytes(xptr->vftbl->class->name);
542 logtextlen += strlen(": ") +
543 u2_utflength(LLNI_field_direct(s, value)->data
544 + LLNI_field_direct(s, offset),
545 LLNI_field_direct(s,count));
549 logtextlen += strlen("(nil)");
552 /* allocate memory */
554 dumpsize = dump_size();
556 logtext = DMNEW(char, logtextlen);
558 strcpy(logtext, "Builtin exception thrown: ");
561 utf_cat_classname(logtext, xptr->vftbl->class->name);
566 buf = javastring_tochar((java_handle_t *) s);
567 strcat(logtext, ": ");
568 strcat(logtext, buf);
569 MFREE(buf, char, strlen(buf) + 1);
573 strcat(logtext, "(nil)");
580 dump_release(dumpsize);
582 #endif /* !defined(NDEBUG) */
584 /* actually set the exception */
586 exceptions_set_exception(xptr);
588 /* Return a NULL pointer. This is required for vm_call_method to
589 check for an exception. This is for convenience. */
595 /* builtin_canstore ************************************************************
597 Checks, if an object can be stored in an array.
599 Return value: 1 ... possible
600 0 ... otherwise (throws an ArrayStoreException)
602 *******************************************************************************/
604 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
606 arraydescriptor *desc;
607 arraydescriptor *valuedesc;
608 vftbl_t *componentvftbl;
617 /* The following is guaranteed (by verifier checks):
619 * *) oa->...vftbl->arraydesc != NULL
620 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
621 * *) o->vftbl is not an interface vftbl
624 desc = oa->header.objheader.vftbl->arraydesc;
625 componentvftbl = desc->componentvftbl;
626 valuevftbl = o->vftbl;
627 valuedesc = valuevftbl->arraydesc;
629 if ((desc->dimension - 1) == 0) {
630 /* {oa is a one-dimensional array} */
631 /* {oa is an array of references} */
633 if (valuevftbl == componentvftbl)
636 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
638 baseval = componentvftbl->baseval;
641 /* an array of interface references */
643 result = ((valuevftbl->interfacetablelength > -baseval) &&
644 (valuevftbl->interfacetable[baseval] != NULL));
647 diffval = valuevftbl->baseval - componentvftbl->baseval;
648 result = diffval <= (uint32_t) componentvftbl->diffval;
651 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
653 else if (valuedesc == NULL) {
654 /* {oa has dimension > 1} */
655 /* {componentvftbl->arraydesc != NULL} */
657 /* check if o is an array */
662 /* {o is an array} */
664 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
667 /* if not possible, throw an exception */
670 exceptions_throw_arraystoreexception();
678 /* This is an optimized version where a is guaranteed to be one-dimensional */
679 s4 builtin_canstore_onedim (java_handle_objectarray_t *a, java_handle_t *o)
681 arraydescriptor *desc;
682 vftbl_t *elementvftbl;
691 /* The following is guaranteed (by verifier checks):
693 * *) a->...vftbl->arraydesc != NULL
694 * *) a->...vftbl->arraydesc->elementvftbl != NULL
695 * *) a->...vftbl->arraydesc->dimension == 1
696 * *) o->vftbl is not an interface vftbl
699 desc = a->header.objheader.vftbl->arraydesc;
700 elementvftbl = desc->elementvftbl;
701 valuevftbl = o->vftbl;
703 /* {a is a one-dimensional array} */
705 if (valuevftbl == elementvftbl)
708 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
710 baseval = elementvftbl->baseval;
713 /* an array of interface references */
714 result = ((valuevftbl->interfacetablelength > -baseval) &&
715 (valuevftbl->interfacetable[baseval] != NULL));
718 diffval = valuevftbl->baseval - elementvftbl->baseval;
719 result = diffval <= (uint32_t) elementvftbl->diffval;
722 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
728 /* This is an optimized version where a is guaranteed to be a
729 * one-dimensional array of a class type */
730 s4 builtin_canstore_onedim_class(java_handle_objectarray_t *a, java_handle_t *o)
732 vftbl_t *elementvftbl;
740 /* The following is guaranteed (by verifier checks):
742 * *) a->...vftbl->arraydesc != NULL
743 * *) a->...vftbl->arraydesc->elementvftbl != NULL
744 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
745 * *) a->...vftbl->arraydesc->dimension == 1
746 * *) o->vftbl is not an interface vftbl
749 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
750 valuevftbl = o->vftbl;
752 /* {a is a one-dimensional array} */
754 if (valuevftbl == elementvftbl)
757 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
759 diffval = valuevftbl->baseval - elementvftbl->baseval;
760 result = diffval <= (uint32_t) elementvftbl->diffval;
762 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
768 /* builtin_new *****************************************************************
770 Creates a new instance of class c on the heap.
772 Return value: pointer to the object or NULL if no memory is
775 *******************************************************************************/
777 java_handle_t *builtin_new(classinfo *c)
780 #if defined(ENABLE_RT_TIMING)
781 struct timespec time_start, time_end;
783 #if defined(ENABLE_CYCLES_STATS)
784 u8 cycles_start, cycles_end;
787 RT_TIMING_GET_TIME(time_start);
788 CYCLES_STATS_GET(cycles_start);
790 /* is the class loaded */
792 assert(c->state & CLASS_LOADED);
794 /* check if we can instantiate this class */
796 if (c->flags & ACC_ABSTRACT) {
797 exceptions_throw_instantiationerror(c);
801 /* is the class linked */
803 if (!(c->state & CLASS_LINKED))
807 if (!(c->state & CLASS_INITIALIZED)) {
810 log_message_class("Initialize class (from builtin_new): ", c);
813 if (!initialize_class(c))
817 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
825 #if defined(ENABLE_THREADS)
826 lock_init_object_lock(o);
829 CYCLES_STATS_GET(cycles_end);
830 RT_TIMING_GET_TIME(time_end);
832 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
833 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
839 /* builtin_newarray ************************************************************
841 Creates an array with the given vftbl on the heap. This function
842 takes as class argument an array class.
844 Return value: pointer to the array or NULL if no memory is available
846 *******************************************************************************/
848 java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
850 arraydescriptor *desc;
855 #if defined(ENABLE_RT_TIMING)
856 struct timespec time_start, time_end;
859 RT_TIMING_GET_TIME(time_start);
861 desc = arrayclass->vftbl->arraydesc;
862 dataoffset = desc->dataoffset;
863 componentsize = desc->componentsize;
866 exceptions_throw_negativearraysizeexception();
870 actualsize = dataoffset + size * componentsize;
872 /* check for overflow */
874 if (((u4) actualsize) < ((u4) size)) {
875 exceptions_throw_outofmemoryerror();
879 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
884 a->objheader.vftbl = arrayclass->vftbl;
886 #if defined(ENABLE_THREADS)
887 lock_init_object_lock(&a->objheader);
890 LLNI_array_size(a) = size;
892 RT_TIMING_GET_TIME(time_end);
893 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
899 /* builtin_anewarray ***********************************************************
901 Creates an array of references to the given class type on the heap.
903 Return value: pointer to the array or NULL if no memory is
906 *******************************************************************************/
908 java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
910 classinfo *arrayclass;
912 /* is class loaded */
914 assert(componentclass->state & CLASS_LOADED);
916 /* is class linked */
918 if (!(componentclass->state & CLASS_LINKED))
919 if (!link_class(componentclass))
922 arrayclass = class_array_of(componentclass, true);
927 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
931 /* builtin_newarray_boolean ****************************************************
933 Creates an array of bytes on the heap. The array is designated as
934 an array of booleans (important for casts)
936 Return value: pointer to the array or NULL if no memory is
939 *******************************************************************************/
941 java_handle_booleanarray_t *builtin_newarray_boolean(s4 size)
943 return (java_handle_booleanarray_t *)
944 builtin_newarray(size,
945 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
949 /* builtin_newarray_byte *******************************************************
951 Creates an array of 8 bit Integers on the heap.
953 Return value: pointer to the array or NULL if no memory is
956 *******************************************************************************/
958 java_handle_bytearray_t *builtin_newarray_byte(s4 size)
960 return (java_handle_bytearray_t *)
961 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
965 /* builtin_newarray_char *******************************************************
967 Creates an array of characters on the heap.
969 Return value: pointer to the array or NULL if no memory is
972 *******************************************************************************/
974 java_handle_chararray_t *builtin_newarray_char(s4 size)
976 return (java_handle_chararray_t *)
977 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
981 /* builtin_newarray_short ******************************************************
983 Creates an array of 16 bit Integers on the heap.
985 Return value: pointer to the array or NULL if no memory is
988 *******************************************************************************/
990 java_handle_shortarray_t *builtin_newarray_short(s4 size)
992 return (java_handle_shortarray_t *)
993 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
997 /* builtin_newarray_int ********************************************************
999 Creates an array of 32 bit Integers on the heap.
1001 Return value: pointer to the array or NULL if no memory is
1004 *******************************************************************************/
1006 java_handle_intarray_t *builtin_newarray_int(s4 size)
1008 return (java_handle_intarray_t *)
1009 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1013 /* builtin_newarray_long *******************************************************
1015 Creates an array of 64 bit Integers on the heap.
1017 Return value: pointer to the array or NULL if no memory is
1020 *******************************************************************************/
1022 java_handle_longarray_t *builtin_newarray_long(s4 size)
1024 return (java_handle_longarray_t *)
1025 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1029 /* builtin_newarray_float ******************************************************
1031 Creates an array of 32 bit IEEE floats on the heap.
1033 Return value: pointer to the array or NULL if no memory is
1036 *******************************************************************************/
1038 java_handle_floatarray_t *builtin_newarray_float(s4 size)
1040 return (java_handle_floatarray_t *)
1041 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1045 /* builtin_newarray_double *****************************************************
1047 Creates an array of 64 bit IEEE floats on the heap.
1049 Return value: pointer to the array or NULL if no memory is
1052 *******************************************************************************/
1054 java_handle_doublearray_t *builtin_newarray_double(s4 size)
1056 return (java_handle_doublearray_t *)
1057 builtin_newarray(size,
1058 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1062 /* builtin_multianewarray_intern ***********************************************
1064 Creates a multi-dimensional array on the heap. The dimensions are
1065 passed in an array of longs.
1068 n.............number of dimensions to create
1069 arrayclass....the array class
1070 dims..........array containing the size of each dimension to create
1072 Return value: pointer to the array or NULL if no memory is
1075 ******************************************************************************/
1077 static java_handle_t *builtin_multianewarray_intern(int n,
1078 classinfo *arrayclass,
1083 classinfo *componentclass;
1086 /* create this dimension */
1088 size = (s4) dims[0];
1089 a = builtin_newarray(size, arrayclass);
1094 /* if this is the last dimension return */
1099 /* get the class of the components to create */
1101 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1103 /* The verifier guarantees that the dimension count is in the range. */
1105 /* create the component arrays */
1107 for (i = 0; i < size; i++) {
1109 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1110 /* we save an s4 to a s8 slot, 8-byte aligned */
1112 builtin_multianewarray_intern(n, componentclass, dims + 2);
1114 builtin_multianewarray_intern(n, componentclass, dims + 1);
1120 ((java_handle_objectarray_t *) a)->data[i] = (java_object_t *) ea;
1127 /* builtin_multianewarray ******************************************************
1129 Wrapper for builtin_multianewarray_intern which checks all
1130 dimensions before we start allocating.
1132 ******************************************************************************/
1134 java_handle_objectarray_t *builtin_multianewarray(int n, classinfo *arrayclass,
1140 /* check all dimensions before doing anything */
1142 for (i = 0; i < n; i++) {
1143 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1144 /* we save an s4 to a s8 slot, 8-byte aligned */
1145 size = (s4) dims[i * 2];
1147 size = (s4) dims[i];
1151 exceptions_throw_negativearraysizeexception();
1156 /* now call the real function */
1158 return builtin_multianewarray_intern(n, arrayclass, dims);
1162 /*****************************************************************************
1165 Various functions for printing a message at method entry or exit (for
1168 *****************************************************************************/
1170 #if !defined(NDEBUG)
1171 static s4 methodindent = 0;
1172 static u4 callcount = 0;
1174 java_handle_t *builtin_trace_exception(java_handle_t *xptr,
1184 #if defined(ENABLE_DEBUG_FILTER)
1185 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1188 #if defined(ENABLE_VMLOG)
1192 if (opt_verbosecall && indent)
1193 #if defined(__S390__)
1194 TRACEJAVACALLINDENT--;
1199 /* calculate message length */
1203 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1206 logtextlen = strlen("Some Throwable");
1209 logtextlen += strlen(" thrown in ");
1213 utf_bytes(m->class->name) +
1215 utf_bytes(m->name) +
1216 utf_bytes(m->descriptor) +
1217 strlen("(NOSYNC,NATIVE");
1219 #if SIZEOF_VOID_P == 8
1221 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1223 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1226 if (m->class->sourcefile == NULL)
1227 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1229 logtextlen += utf_bytes(m->class->sourcefile);
1231 logtextlen += strlen(":65536)");
1235 logtextlen += strlen("call_java_method");
1238 logtextlen += strlen("0");
1240 /* allocate memory */
1242 dumpsize = dump_size();
1244 logtext = DMNEW(char, logtextlen);
1247 strcpy(logtext, "Exception ");
1248 utf_cat_classname(logtext, xptr->vftbl->class->name);
1251 strcpy(logtext, "Some Throwable");
1254 strcat(logtext, " thrown in ");
1257 utf_cat_classname(logtext, m->class->name);
1258 strcat(logtext, ".");
1259 utf_cat(logtext, m->name);
1260 utf_cat(logtext, m->descriptor);
1262 if (m->flags & ACC_SYNCHRONIZED)
1263 strcat(logtext, "(SYNC");
1265 strcat(logtext, "(NOSYNC");
1267 if (m->flags & ACC_NATIVE) {
1268 strcat(logtext, ",NATIVE");
1272 #if SIZEOF_VOID_P == 8
1273 sprintf(logtext + strlen(logtext),
1274 ")(0x%016lx) at position 0x%016lx",
1275 (ptrint) code->entrypoint, (ptrint) pos);
1277 sprintf(logtext + strlen(logtext),
1278 ")(0x%08x) at position 0x%08x",
1279 (ptrint) code->entrypoint, (ptrint) pos);
1284 /* XXX preliminary: This should get the actual codeinfo */
1285 /* in which the exception happened. */
1288 #if SIZEOF_VOID_P == 8
1289 sprintf(logtext + strlen(logtext),
1290 ")(0x%016lx) at position 0x%016lx (",
1291 (ptrint) code->entrypoint, (ptrint) pos);
1293 sprintf(logtext + strlen(logtext),
1294 ")(0x%08x) at position 0x%08x (",
1295 (ptrint) code->entrypoint, (ptrint) pos);
1298 if (m->class->sourcefile == NULL)
1299 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1301 utf_cat(logtext, m->class->sourcefile);
1303 sprintf(logtext + strlen(logtext), ":%d)", 0);
1307 strcat(logtext, "call_java_method");
1311 /* release memory */
1313 dump_release(dumpsize);
1317 #endif /* !defined(NDEBUG) */
1320 /* builtin_print_argument ******************************************************
1322 Prints arguments and return values for the call trace.
1324 *******************************************************************************/
1326 #if !defined(NDEBUG)
1327 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1328 typedesc *paramtype, s8 value)
1336 switch (paramtype->type) {
1339 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1344 #if SIZEOF_VOID_P == 4
1345 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1347 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1352 #if defined(__S390__)
1354 /* The below won't work on S390 */
1358 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1363 #if SIZEOF_VOID_P == 4
1364 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1366 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1371 #if SIZEOF_VOID_P == 4
1372 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1374 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1377 /* cast to java.lang.Object */
1379 o = (java_handle_t *) (ptrint) value;
1381 /* check return argument for java.lang.Class or java.lang.String */
1384 if (o->vftbl->class == class_java_lang_String) {
1385 /* get java.lang.String object and the length of the
1388 u = javastring_toutf(o, false);
1390 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1392 /* realloc memory for string length */
1394 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1397 /* convert to utf8 string and strcat it to the logtext */
1399 strcat(logtext, " (String = \"");
1400 utf_cat(logtext, u);
1401 strcat(logtext, "\")");
1404 if (o->vftbl->class == class_java_lang_Class) {
1405 /* if the object returned is a java.lang.Class
1406 cast it to classinfo structure and get the name
1409 c = (classinfo *) o;
1414 /* if the object returned is not a java.lang.String or
1415 a java.lang.Class just print the name of the class */
1417 u = o->vftbl->class->name;
1420 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1422 /* realloc memory for string length */
1424 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1427 /* strcat to the logtext */
1429 strcat(logtext, " (Class = \"");
1430 utf_cat_classname(logtext, u);
1431 strcat(logtext, "\")");
1438 #endif /* !defined(NDEBUG) */
1440 /* builtin_verbosecall_enter ***************************************************
1442 Print method call with arguments for -verbose:call.
1444 *******************************************************************************/
1446 #if !defined(NDEBUG)
1448 #ifdef TRACE_ARGS_NUM
1449 void builtin_verbosecall_enter(s8 a0, s8 a1,
1450 # if TRACE_ARGS_NUM >= 4
1453 # if TRACE_ARGS_NUM >= 6
1456 # if TRACE_ARGS_NUM == 8
1468 #if defined(ENABLE_DEBUG_FILTER)
1469 if (! show_filters_test_verbosecall_enter(m)) return;
1472 #if defined(ENABLE_VMLOG)
1473 vmlog_cacao_enter_method(m);
1479 /* calculate message length */
1482 strlen("4294967295 ") +
1483 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1485 strlen("called: ") +
1486 utf_bytes(m->class->name) +
1488 utf_bytes(m->name) +
1489 utf_bytes(m->descriptor);
1491 /* Actually it's not possible to have all flags printed, but:
1496 strlen(" PRIVATE") +
1497 strlen(" PROTECTED") +
1500 strlen(" SYNCHRONIZED") +
1501 strlen(" VOLATILE") +
1502 strlen(" TRANSIENT") +
1504 strlen(" INTERFACE") +
1505 strlen(" ABSTRACT");
1507 /* add maximal argument length */
1511 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1512 strlen("...(255)") +
1515 /* allocate memory */
1517 dumpsize = dump_size();
1519 logtext = DMNEW(char, logtextlen);
1523 sprintf(logtext, "%10d ", callcount);
1524 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1526 pos = strlen(logtext);
1528 for (i = 0; i < methodindent; i++)
1529 logtext[pos++] = '\t';
1531 strcpy(logtext + pos, "called: ");
1533 utf_cat_classname(logtext, m->class->name);
1534 strcat(logtext, ".");
1535 utf_cat(logtext, m->name);
1536 utf_cat(logtext, m->descriptor);
1538 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1539 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1540 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1541 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1542 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1543 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1544 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1545 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1546 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1547 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1548 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1550 strcat(logtext, "(");
1552 if (md->paramcount >= 1) {
1553 logtext = builtin_print_argument(logtext, &logtextlen,
1554 &md->paramtypes[0], a0);
1557 if (md->paramcount >= 2) {
1558 strcat(logtext, ", ");
1560 logtext = builtin_print_argument(logtext, &logtextlen,
1561 &md->paramtypes[1], a1);
1564 #if TRACE_ARGS_NUM >= 4
1565 if (md->paramcount >= 3) {
1566 strcat(logtext, ", ");
1568 logtext = builtin_print_argument(logtext, &logtextlen,
1569 &md->paramtypes[2], a2);
1572 if (md->paramcount >= 4) {
1573 strcat(logtext, ", ");
1575 logtext = builtin_print_argument(logtext, &logtextlen,
1576 &md->paramtypes[3], a3);
1580 #if TRACE_ARGS_NUM >= 6
1581 if (md->paramcount >= 5) {
1582 strcat(logtext, ", ");
1584 logtext = builtin_print_argument(logtext, &logtextlen,
1585 &md->paramtypes[4], a4);
1588 if (md->paramcount >= 6) {
1589 strcat(logtext, ", ");
1591 logtext = builtin_print_argument(logtext, &logtextlen,
1592 &md->paramtypes[5], a5);
1596 #if TRACE_ARGS_NUM == 8
1597 if (md->paramcount >= 7) {
1598 strcat(logtext, ", ");
1600 logtext = builtin_print_argument(logtext, &logtextlen,
1601 &md->paramtypes[6], a6);
1604 if (md->paramcount >= 8) {
1605 strcat(logtext, ", ");
1607 logtext = builtin_print_argument(logtext, &logtextlen,
1608 &md->paramtypes[7], a7);
1612 if (md->paramcount > 8) {
1613 sprintf(logtext + strlen(logtext), ", ...(%d)",
1614 md->paramcount - TRACE_ARGS_NUM);
1617 strcat(logtext, ")");
1621 /* release memory */
1623 dump_release(dumpsize);
1629 #endif /* !defined(NDEBUG) */
1632 /* builtin_verbosecall_exit ****************************************************
1634 Print method exit for -verbose:call.
1636 *******************************************************************************/
1638 #if !defined(NDEBUG)
1639 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1649 #if defined(ENABLE_DEBUG_FILTER)
1650 if (! show_filters_test_verbosecall_exit(m)) return;
1653 #if defined(ENABLE_VMLOG)
1654 vmlog_cacao_leave_method(m);
1660 /* calculate message length */
1663 strlen("4294967295 ") +
1664 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1666 strlen("finished: ") +
1667 utf_bytes(m->class->name) +
1669 utf_bytes(m->name) +
1670 utf_bytes(m->descriptor) +
1671 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1673 /* add maximal argument length */
1675 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1677 /* allocate memory */
1679 dumpsize = dump_size();
1681 logtext = DMNEW(char, logtextlen);
1683 /* outdent the log message */
1688 log_text("WARNING: unmatched methodindent--");
1690 /* generate the message */
1692 sprintf(logtext, " ");
1693 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1695 pos = strlen(logtext);
1697 for (i = 0; i < methodindent; i++)
1698 logtext[pos++] = '\t';
1700 strcpy(logtext + pos, "finished: ");
1701 utf_cat_classname(logtext, m->class->name);
1702 strcat(logtext, ".");
1703 utf_cat(logtext, m->name);
1704 utf_cat(logtext, m->descriptor);
1706 if (!IS_VOID_TYPE(md->returntype.type)) {
1707 strcat(logtext, "->");
1709 switch (md->returntype.type) {
1726 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1731 /* release memory */
1733 dump_release(dumpsize);
1736 #endif /* !defined(NDEBUG) */
1739 #if defined(ENABLE_CYCLES_STATS)
1740 void builtin_print_cycles_stats(FILE *file)
1742 fprintf(file,"builtin cylce count statistics:\n");
1744 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1745 CYCLES_STATS_PRINT(builtin_new ,file);
1749 #endif /* defined(ENABLE_CYCLES_STATS) */
1752 /*****************************************************************************
1753 MISCELLANEOUS HELPER FUNCTIONS
1754 *****************************************************************************/
1758 /*********** Functions for integer divisions *****************************
1760 On some systems (eg. DEC ALPHA), integer division is not supported by the
1761 CPU. These helper functions implement the missing functionality.
1763 ******************************************************************************/
1765 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1766 s4 builtin_idiv(s4 a, s4 b)
1775 s4 builtin_irem(s4 a, s4 b)
1783 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1786 /* functions for long arithmetics **********************************************
1788 On systems where 64 bit Integers are not supported by the CPU,
1789 these functions are needed.
1791 ******************************************************************************/
1793 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1794 s8 builtin_ladd(s8 a, s8 b)
1807 s8 builtin_lsub(s8 a, s8 b)
1820 s8 builtin_lneg(s8 a)
1832 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1835 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1836 s8 builtin_lmul(s8 a, s8 b)
1848 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1851 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1852 s8 builtin_ldiv(s8 a, s8 b)
1865 s8 builtin_lrem(s8 a, s8 b)
1877 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1880 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1881 s8 builtin_lshl(s8 a, s4 b)
1894 s8 builtin_lshr(s8 a, s4 b)
1907 s8 builtin_lushr(s8 a, s4 b)
1912 c = ((u8) a) >> (b & 63);
1919 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1922 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1923 s8 builtin_land(s8 a, s8 b)
1936 s8 builtin_lor(s8 a, s8 b)
1949 s8 builtin_lxor(s8 a, s8 b)
1961 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1964 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1965 s4 builtin_lcmp(s8 a, s8 b)
1979 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1982 /* functions for unsupported floating instructions ****************************/
1984 /* used to convert FLT_xxx defines into float values */
1986 static inline float intBitsToFloat(s4 i)
1995 /* used to convert DBL_xxx defines into double values */
1997 static inline float longBitsToDouble(s8 l)
2007 float builtin_fadd(float a, float b)
2009 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2010 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2021 if (copysignf(1.0, a) == copysignf(1.0, b))
2024 return intBitsToFloat(FLT_NAN);
2030 float builtin_fsub(float a, float b)
2032 return builtin_fadd(a, builtin_fneg(b));
2036 float builtin_fmul(float a, float b)
2038 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2039 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2041 if (finitef(b)) return a * b;
2043 if (a == 0) return intBitsToFloat(FLT_NAN);
2044 else return copysignf(b, copysignf(1.0, b)*a);
2049 if (b == 0) return intBitsToFloat(FLT_NAN);
2050 else return copysignf(a, copysignf(1.0, a)*b);
2053 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2059 /* builtin_ddiv ****************************************************************
2061 Implementation as described in VM Spec.
2063 *******************************************************************************/
2065 float builtin_fdiv(float a, float b)
2069 /* If neither value1' nor value2' is NaN, the sign of the result */
2070 /* is positive if both values have the same sign, negative if the */
2071 /* values have different signs. */
2077 /* If either value1' or value2' is NaN, the result is NaN. */
2079 return intBitsToFloat(FLT_NAN);
2082 /* Division of a finite value by an infinity results in a */
2083 /* signed zero, with the sign-producing rule just given. */
2085 /* is sign equal? */
2087 if (copysignf(1.0, a) == copysignf(1.0, b))
2096 /* If either value1' or value2' is NaN, the result is NaN. */
2098 return intBitsToFloat(FLT_NAN);
2100 } else if (finitef(b)) {
2101 /* Division of an infinity by a finite value results in a signed */
2102 /* infinity, with the sign-producing rule just given. */
2104 /* is sign equal? */
2106 if (copysignf(1.0, a) == copysignf(1.0, b))
2107 return intBitsToFloat(FLT_POSINF);
2109 return intBitsToFloat(FLT_NEGINF);
2112 /* Division of an infinity by an infinity results in NaN. */
2114 return intBitsToFloat(FLT_NAN);
2120 float builtin_fneg(float a)
2122 if (isnanf(a)) return a;
2124 if (finitef(a)) return -a;
2125 else return copysignf(a, -copysignf(1.0, a));
2128 #endif /* !SUPPORT_FLOAT */
2131 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2132 s4 builtin_fcmpl(float a, float b)
2140 if (!finitef(a) || !finitef(b)) {
2141 a = finitef(a) ? 0 : copysignf(1.0, a);
2142 b = finitef(b) ? 0 : copysignf(1.0, b);
2155 s4 builtin_fcmpg(float a, float b)
2157 if (isnanf(a)) return 1;
2158 if (isnanf(b)) return 1;
2159 if (!finitef(a) || !finitef(b)) {
2160 a = finitef(a) ? 0 : copysignf(1.0, a);
2161 b = finitef(b) ? 0 : copysignf(1.0, b);
2163 if (a > b) return 1;
2164 if (a == b) return 0;
2167 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2170 float builtin_frem(float a, float b)
2176 /* functions for unsupported double instructions ******************************/
2179 double builtin_dadd(double a, double b)
2181 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2182 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2184 if (finite(b)) return a + b;
2188 if (finite(b)) return a;
2190 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2191 else return longBitsToDouble(DBL_NAN);
2197 double builtin_dsub(double a, double b)
2199 return builtin_dadd(a, builtin_dneg(b));
2203 double builtin_dmul(double a, double b)
2205 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2206 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2208 if (finite(b)) return a * b;
2210 if (a == 0) return longBitsToDouble(DBL_NAN);
2211 else return copysign(b, copysign(1.0, b) * a);
2216 if (b == 0) return longBitsToDouble(DBL_NAN);
2217 else return copysign(a, copysign(1.0, a) * b);
2220 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2226 /* builtin_ddiv ****************************************************************
2228 Implementation as described in VM Spec.
2230 *******************************************************************************/
2232 double builtin_ddiv(double a, double b)
2236 /* If neither value1' nor value2' is NaN, the sign of the result */
2237 /* is positive if both values have the same sign, negative if the */
2238 /* values have different signs. */
2244 /* If either value1' or value2' is NaN, the result is NaN. */
2246 return longBitsToDouble(DBL_NAN);
2249 /* Division of a finite value by an infinity results in a */
2250 /* signed zero, with the sign-producing rule just given. */
2252 /* is sign equal? */
2254 if (copysign(1.0, a) == copysign(1.0, b))
2263 /* If either value1' or value2' is NaN, the result is NaN. */
2265 return longBitsToDouble(DBL_NAN);
2267 } else if (finite(b)) {
2268 /* Division of an infinity by a finite value results in a signed */
2269 /* infinity, with the sign-producing rule just given. */
2271 /* is sign equal? */
2273 if (copysign(1.0, a) == copysign(1.0, b))
2274 return longBitsToDouble(DBL_POSINF);
2276 return longBitsToDouble(DBL_NEGINF);
2279 /* Division of an infinity by an infinity results in NaN. */
2281 return longBitsToDouble(DBL_NAN);
2287 /* builtin_dneg ****************************************************************
2289 Implemented as described in VM Spec.
2291 *******************************************************************************/
2293 double builtin_dneg(double a)
2296 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2303 /* If the operand is a zero, the result is the zero of opposite */
2309 /* If the operand is an infinity, the result is the infinity of */
2310 /* opposite sign. */
2312 return copysign(a, -copysign(1.0, a));
2316 #endif /* !SUPPORT_DOUBLE */
2319 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2320 s4 builtin_dcmpl(double a, double b)
2328 if (!finite(a) || !finite(b)) {
2329 a = finite(a) ? 0 : copysign(1.0, a);
2330 b = finite(b) ? 0 : copysign(1.0, b);
2343 s4 builtin_dcmpg(double a, double b)
2351 if (!finite(a) || !finite(b)) {
2352 a = finite(a) ? 0 : copysign(1.0, a);
2353 b = finite(b) ? 0 : copysign(1.0, b);
2364 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2367 double builtin_drem(double a, double b)
2373 /* conversion operations ******************************************************/
2376 s8 builtin_i2l(s4 i)
2388 s4 builtin_l2i(s8 l)
2399 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2400 float builtin_i2f(s4 a)
2402 float f = (float) a;
2405 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2408 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2409 double builtin_i2d(s4 a)
2411 double d = (double) a;
2414 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2417 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2418 float builtin_l2f(s8 a)
2421 float f = (float) a;
2427 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2430 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2431 double builtin_l2d(s8 a)
2434 double d = (double) a;
2440 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2443 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2444 s4 builtin_f2i(float a)
2448 i = builtin_d2i((double) a);
2459 if (a < (-2147483648))
2460 return (-2147483648);
2463 f = copysignf((float) 1.0, a);
2466 return (-2147483648); */
2468 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2471 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2472 s8 builtin_f2l(float a)
2476 l = builtin_d2l((double) a);
2483 if (a > 9223372036854775807L)
2484 return 9223372036854775807L;
2485 if (a < (-9223372036854775808L))
2486 return (-9223372036854775808L);
2491 f = copysignf((float) 1.0, a);
2493 return 9223372036854775807L;
2494 return (-9223372036854775808L); */
2496 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2499 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2500 s4 builtin_d2i(double a)
2505 if (a >= 2147483647)
2507 if (a <= (-2147483647-1))
2508 return (-2147483647-1);
2513 d = copysign(1.0, a);
2516 return (-2147483647-1);
2518 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2521 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2522 s8 builtin_d2l(double a)
2527 if (a >= 9223372036854775807LL)
2528 return 9223372036854775807LL;
2529 if (a <= (-9223372036854775807LL-1))
2530 return (-9223372036854775807LL-1);
2535 d = copysign(1.0, a);
2537 return 9223372036854775807LL;
2538 return (-9223372036854775807LL-1);
2540 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2543 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2544 double builtin_f2d(float a)
2546 if (finitef(a)) return (double) a;
2549 return longBitsToDouble(DBL_NAN);
2551 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2555 float builtin_d2f(double a)
2561 return intBitsToFloat(FLT_NAN);
2563 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2566 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2569 /* builtin_arraycopy ***********************************************************
2571 Builtin for java.lang.System.arraycopy.
2573 ATTENTION: This builtin function returns a boolean value to signal
2574 the ICMD_BUILTIN if there was an exception.
2576 *******************************************************************************/
2578 bool builtin_arraycopy(java_handle_t *src, s4 srcStart,
2579 java_handle_t *dest, s4 destStart, s4 len)
2581 arraydescriptor *sdesc;
2582 arraydescriptor *ddesc;
2585 if ((src == NULL) || (dest == NULL)) {
2586 exceptions_throw_nullpointerexception();
2590 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2591 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2593 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2594 exceptions_throw_arraystoreexception();
2598 /* we try to throw exception with the same message as SUN does */
2600 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2601 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2602 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2603 exceptions_throw_arrayindexoutofboundsexception();
2607 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2608 /* We copy primitive values or references of exactly the same type */
2610 s4 dataoffset = sdesc->dataoffset;
2611 s4 componentsize = sdesc->componentsize;
2613 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2614 ((u1 *) src) + dataoffset + componentsize * srcStart,
2615 (size_t) len * componentsize);
2618 /* We copy references of different type */
2620 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2621 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2623 if (destStart <= srcStart) {
2624 for (i = 0; i < len; i++) {
2625 java_handle_t *o = oas->data[srcStart + i];
2627 if (!builtin_canstore(oad, o))
2630 oad->data[destStart + i] = o;
2634 /* XXX this does not completely obey the specification!
2635 If an exception is thrown only the elements above the
2636 current index have been copied. The specification
2637 requires that only the elements *below* the current
2638 index have been copied before the throw. */
2640 for (i = len - 1; i >= 0; i--) {
2641 java_handle_t *o = oas->data[srcStart + i];
2643 if (!builtin_canstore(oad, o))
2646 oad->data[destStart + i] = o;
2655 /* builtin_nanotime ************************************************************
2657 Return the current time in nanoseconds.
2659 *******************************************************************************/
2661 s8 builtin_nanotime(void)
2666 if (gettimeofday(&tv, NULL) == -1)
2667 vm_abort("gettimeofday failed: %s", strerror(errno));
2669 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2671 return usecs * 1000;
2675 /* builtin_currenttimemillis ***************************************************
2677 Return the current time in milliseconds.
2679 *******************************************************************************/
2681 s8 builtin_currenttimemillis(void)
2685 msecs = builtin_nanotime() / 1000 / 1000;
2691 /* builtin_clone ***************************************************************
2693 Function for cloning objects or arrays.
2695 *******************************************************************************/
2697 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2699 arraydescriptor *ad;
2703 java_handle_t *co; /* cloned object header */
2705 /* get the array descriptor */
2707 ad = o->vftbl->arraydesc;
2709 /* we are cloning an array */
2712 ah = (java_handle_t *) o;
2714 size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah);
2716 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2721 MCOPY(co, o, u1, size);
2723 #if defined(ENABLE_GC_CACAO)
2724 heap_init_objectheader(co, size);
2727 #if defined(ENABLE_THREADS)
2728 lock_init_object_lock(co);
2734 /* we are cloning a non-array */
2736 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2737 exceptions_throw_clonenotsupportedexception();
2741 /* get the class of the object */
2743 c = o->vftbl->class;
2745 /* create new object */
2747 co = builtin_new(c);
2752 MCOPY(co, o, u1, c->instancesize);
2754 #if defined(ENABLE_GC_CACAO)
2755 heap_init_objectheader(co, c->instancesize);
2758 #if defined(ENABLE_THREADS)
2759 lock_init_object_lock(co);
2765 #if defined(ENABLE_VMLOG)
2767 #include <vmlog_cacao.c>
2772 * These are local overrides for various environment variables in Emacs.
2773 * Please do not remove this and leave it at the end of the file, where
2774 * Emacs will automagically detect them.
2775 * ---------------------------------------------------------------------
2778 * indent-tabs-mode: t
2782 * vim:noexpandtab:sw=4:ts=4: