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
31 $Id: builtin.c 7723 2007-04-16 18:03:08Z michi $
50 #include "fdlibm/fdlibm.h"
51 #if defined(__CYGWIN__) && defined(Bias)
55 #include "mm/gc-common.h"
56 #include "mm/memory.h"
58 #include "native/jni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
62 #if defined(ENABLE_THREADS)
63 # include "threads/native/lock.h"
66 #include "toolbox/logging.h"
67 #include "toolbox/util.h"
69 #include "vm/builtin.h"
70 #include "vm/cycles-stats.h"
71 #include "vm/exceptions.h"
72 #include "vm/global.h"
73 #include "vm/initialize.h"
74 #include "vm/stringlocal.h"
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/patcher.h"
79 #include "vmcore/class.h"
80 #include "vmcore/loader.h"
81 #include "vmcore/options.h"
82 #include "vmcore/rt-timing.h"
85 /* include builtin tables *****************************************************/
87 #include "vm/builtintable.inc"
90 CYCLES_STATS_DECLARE(builtin_new ,100,5)
91 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
93 /* builtintable_init ***********************************************************
95 Parse the descriptors of builtin functions and create the parsed
98 *******************************************************************************/
100 static bool builtintable_init(void)
102 descriptor_pool *descpool;
104 builtintable_entry *bte;
106 /* mark start of dump memory area */
108 dumpsize = dump_size();
110 /* create a new descriptor pool */
112 descpool = descriptor_pool_new(class_java_lang_Object);
114 /* add some entries we need */
116 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
119 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
122 /* first add all descriptors to the pool */
124 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
125 /* create a utf8 string from descriptor */
127 bte->descriptor = utf_new_char(bte->cdescriptor);
129 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
130 /* release dump area */
132 dump_release(dumpsize);
138 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
139 bte->descriptor = utf_new_char(bte->cdescriptor);
141 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
142 dump_release(dumpsize);
147 for (bte = builtintable_function; bte->fp != NULL; bte++) {
148 bte->classname = utf_new_char(bte->cclassname);
149 bte->name = utf_new_char(bte->cname);
150 bte->descriptor = utf_new_char(bte->cdescriptor);
152 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
153 dump_release(dumpsize);
158 /* create the class reference table */
160 (void) descriptor_pool_create_classrefs(descpool, NULL);
162 /* allocate space for the parsed descriptors */
164 descriptor_pool_alloc_parsed_descriptors(descpool);
166 /* now parse all descriptors */
168 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
169 /* parse the descriptor, builtin is always static (no `this' pointer) */
171 bte->md = descriptor_pool_parse_method_descriptor(descpool,
176 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
177 bte->md = descriptor_pool_parse_method_descriptor(descpool,
182 for (bte = builtintable_function; bte->fp != NULL; bte++) {
183 bte->md = descriptor_pool_parse_method_descriptor(descpool,
188 /* release dump area */
190 dump_release(dumpsize);
196 /* builtintable_comparator *****************************************************
198 qsort comparator for the automatic builtin table.
200 *******************************************************************************/
202 static int builtintable_comparator(const void *a, const void *b)
204 builtintable_entry *bte1;
205 builtintable_entry *bte2;
207 bte1 = (builtintable_entry *) a;
208 bte2 = (builtintable_entry *) b;
210 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
214 /* builtintable_sort_automatic *************************************************
216 Sorts the automatic builtin table.
218 *******************************************************************************/
220 static void builtintable_sort_automatic(void)
224 /* calculate table size statically (`- 1' comment see builtintable.inc) */
226 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
228 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
229 builtintable_comparator);
233 /* builtin_init ****************************************************************
235 Initialize the global table of builtin functions.
237 *******************************************************************************/
239 bool builtin_init(void)
241 /* initialize the builtin tables */
243 if (!builtintable_init())
246 /* sort builtin tables */
248 builtintable_sort_automatic();
254 /* builtintable_get_internal ***************************************************
256 Finds an entry in the builtintable for internal functions and
257 returns the a pointer to the structure.
259 *******************************************************************************/
261 builtintable_entry *builtintable_get_internal(functionptr fp)
263 builtintable_entry *bte;
265 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
274 /* builtintable_get_automatic **************************************************
276 Finds an entry in the builtintable for functions which are replaced
277 automatically and returns the a pointer to the structure.
279 *******************************************************************************/
281 builtintable_entry *builtintable_get_automatic(s4 opcode)
283 builtintable_entry *first;
284 builtintable_entry *last;
285 builtintable_entry *middle;
289 /* calculate table size statically (`- 1' comment see builtintable.inc) */
291 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
293 first = builtintable_automatic;
294 last = builtintable_automatic + entries;
296 while (entries > 0) {
298 middle = first + half;
300 if (middle->opcode < opcode) {
308 return (first != last ? first : NULL);
312 /* builtintable_replace_function ***********************************************
316 *******************************************************************************/
318 #if defined(ENABLE_JIT)
319 bool builtintable_replace_function(void *iptr_)
322 builtintable_entry *bte;
325 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
327 /* get name and descriptor of the function */
330 case ICMD_INVOKESTATIC:
331 /* The instruction MUST be resolved, otherwise we run into
332 lazy loading troubles. Anyway, we should/can only replace
333 very VM-close functions. */
335 if (INSTRUCTION_IS_UNRESOLVED(iptr))
338 mr = iptr->sx.s23.s3.fmiref;
345 /* search the function table */
347 for (bte = builtintable_function; bte->fp != NULL; bte++) {
348 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
349 (mr->name == bte->name) &&
350 (mr->descriptor == bte->descriptor)) {
352 /* set the values in the instruction */
354 iptr->opc = bte->opcode;
355 iptr->sx.s23.s3.bte = bte;
357 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
358 iptr->flags.bits |= INS_FLAG_CHECK;
360 iptr->flags.bits &= ~INS_FLAG_CHECK;
368 #endif /* defined(ENABLE_JIT) */
371 /*****************************************************************************
373 *****************************************************************************/
375 /* builtin_instanceof **********************************************************
377 Checks if an object is an instance of some given class (or subclass
378 of that class). If class is an interface, checks if the interface
381 Return value: 1 ... o is an instance of class or implements the interface
382 0 ... otherwise or if o == NULL
384 *******************************************************************************/
386 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
391 return class_isanysubclass(o->vftbl->class, class);
396 /* builtin_checkcast ***********************************************************
398 The same as builtin_instanceof except that 1 is returned when o ==
401 *******************************************************************************/
403 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
408 if (class_isanysubclass(o->vftbl->class, class))
415 /* builtin_descriptorscompatible ***********************************************
417 Checks if two array type descriptors are assignment compatible
419 Return value: 1 ... target = desc is possible
422 *******************************************************************************/
424 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
425 arraydescriptor *target)
430 if (desc->arraytype != target->arraytype)
433 if (desc->arraytype != ARRAYTYPE_OBJECT)
436 /* {both arrays are arrays of references} */
438 if (desc->dimension == target->dimension) {
439 /* an array which contains elements of interface types is
440 allowed to be casted to Object (JOWENN)*/
442 if ((desc->elementvftbl->baseval < 0) &&
443 (target->elementvftbl->baseval == 1))
446 return class_isanysubclass(desc->elementvftbl->class,
447 target->elementvftbl->class);
450 if (desc->dimension < target->dimension)
453 /* {desc has higher dimension than target} */
455 return class_isanysubclass(pseudo_class_Arraystub,
456 target->elementvftbl->class);
460 /* builtin_arraycheckcast ******************************************************
462 Checks if an object is really a subtype of the requested array
463 type. The object has to be an array to begin with. For simple
464 arrays (int, short, double, etc.) the types have to match exactly.
465 For arrays of objects, the type of elements in the array has to be
466 a subtype (or the same type) of the requested element type. For
467 arrays of arrays (which in turn can again be arrays of arrays), the
468 types at the lowest level have to satisfy the corresponding sub
471 *******************************************************************************/
473 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
475 arraydescriptor *desc;
480 desc = o->vftbl->arraydesc;
485 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
489 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
494 return builtin_arraycheckcast(o, targetclass);
498 /* builtin_throw_exception *****************************************************
500 Sets the exceptionptr with the thrown exception and prints some
501 debugging information. Called from asm_vm_call_method.
503 *******************************************************************************/
505 void *builtin_throw_exception(java_objectheader *xptr)
508 java_lang_Throwable *t;
514 t = (java_lang_Throwable *) xptr;
516 /* calculate message length */
518 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
522 utf_bytes(xptr->vftbl->class->name);
523 if (t->detailMessage) {
524 logtextlen += strlen(": ") +
525 u2_utflength(t->detailMessage->value->data
526 + t->detailMessage->offset,
527 t->detailMessage->count);
531 logtextlen += strlen("(nil)");
534 /* allocate memory */
536 dumpsize = dump_size();
538 logtext = DMNEW(char, logtextlen);
540 strcpy(logtext, "Builtin exception thrown: ");
543 utf_cat_classname(logtext, xptr->vftbl->class->name);
545 if (t->detailMessage) {
548 buf = javastring_tochar((java_objectheader *) t->detailMessage);
549 strcat(logtext, ": ");
550 strcat(logtext, buf);
551 MFREE(buf, char, strlen(buf) + 1);
555 strcat(logtext, "(nil)");
562 dump_release(dumpsize);
564 #endif /* !defined(NDEBUG) */
566 /* actually set the exception */
568 exceptions_set_exception(xptr);
570 /* Return a NULL pointer. This is required for vm_call_method to
571 check for an exception. This is for convenience. */
577 /* builtin_canstore ************************************************************
579 Checks, if an object can be stored in an array.
581 Return value: 1 ... possible
582 0 ... otherwise (throws an ArrayStoreException)
584 *******************************************************************************/
586 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
588 arraydescriptor *desc;
589 arraydescriptor *valuedesc;
590 vftbl_t *componentvftbl;
593 castinfo classvalues;
599 /* The following is guaranteed (by verifier checks):
601 * *) oa->...vftbl->arraydesc != NULL
602 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
603 * *) o->vftbl is not an interface vftbl
606 desc = oa->header.objheader.vftbl->arraydesc;
607 componentvftbl = desc->componentvftbl;
608 valuevftbl = o->vftbl;
609 valuedesc = valuevftbl->arraydesc;
611 if ((desc->dimension - 1) == 0) {
612 /* {oa is a one-dimensional array} */
613 /* {oa is an array of references} */
615 if (valuevftbl == componentvftbl)
618 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
620 base = classvalues.super_baseval;
623 /* an array of interface references */
625 result = ((valuevftbl->interfacetablelength > -base) &&
626 (valuevftbl->interfacetable[base] != NULL));
629 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
630 <= (unsigned) classvalues.super_diffval);
633 else if (valuedesc == NULL) {
634 /* {oa has dimension > 1} */
635 /* {componentvftbl->arraydesc != NULL} */
637 /* check if o is an array */
642 /* {o is an array} */
644 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
647 /* if not possible, throw an exception */
650 exceptions_throw_arraystoreexception();
658 /* This is an optimized version where a is guaranteed to be one-dimensional */
659 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
661 arraydescriptor *desc;
662 vftbl_t *elementvftbl;
666 castinfo classvalues;
670 /* The following is guaranteed (by verifier checks):
672 * *) a->...vftbl->arraydesc != NULL
673 * *) a->...vftbl->arraydesc->elementvftbl != NULL
674 * *) a->...vftbl->arraydesc->dimension == 1
675 * *) o->vftbl is not an interface vftbl
678 desc = a->header.objheader.vftbl->arraydesc;
679 elementvftbl = desc->elementvftbl;
680 valuevftbl = o->vftbl;
682 /* {a is a one-dimensional array} */
684 if (valuevftbl == elementvftbl)
687 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
689 if ((base = classvalues.super_baseval) <= 0)
690 /* an array of interface references */
691 return (valuevftbl->interfacetablelength > -base &&
692 valuevftbl->interfacetable[base] != NULL);
694 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
695 <= (unsigned) classvalues.super_diffval;
701 /* This is an optimized version where a is guaranteed to be a
702 * one-dimensional array of a class type */
703 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
705 vftbl_t *elementvftbl;
708 castinfo classvalues;
712 /* The following is guaranteed (by verifier checks):
714 * *) a->...vftbl->arraydesc != NULL
715 * *) a->...vftbl->arraydesc->elementvftbl != NULL
716 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
717 * *) a->...vftbl->arraydesc->dimension == 1
718 * *) o->vftbl is not an interface vftbl
721 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
722 valuevftbl = o->vftbl;
724 /* {a is a one-dimensional array} */
726 if (valuevftbl == elementvftbl)
729 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
731 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
732 <= (unsigned) classvalues.super_diffval;
738 /* builtin_new *****************************************************************
740 Creates a new instance of class c on the heap.
742 Return value: pointer to the object or NULL if no memory is
745 *******************************************************************************/
747 java_objectheader *builtin_new(classinfo *c)
749 java_objectheader *o;
750 #if defined(ENABLE_RT_TIMING)
751 struct timespec time_start, time_end;
753 #if defined(ENABLE_CYCLES_STATS)
754 u8 cycles_start, cycles_end;
757 RT_TIMING_GET_TIME(time_start);
758 CYCLES_STATS_GET(cycles_start);
760 /* is the class loaded */
762 assert(c->state & CLASS_LOADED);
764 /* check if we can instantiate this class */
766 if (c->flags & ACC_ABSTRACT) {
767 exceptions_throw_instantiationerror(c);
771 /* is the class linked */
773 if (!(c->state & CLASS_LINKED))
777 if (!(c->state & CLASS_INITIALIZED)) {
780 log_message_class("Initialize class (from builtin_new): ", c);
783 if (!initialize_class(c))
787 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
795 #if defined(ENABLE_THREADS)
796 lock_init_object_lock(o);
799 CYCLES_STATS_GET(cycles_end);
800 RT_TIMING_GET_TIME(time_end);
802 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
803 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
809 /* builtin_fast_new ************************************************************
811 Creates a new instance of class c on the heap.
813 Return value: pointer to the object or NULL if no fast return
814 is possible for any reason.
816 *******************************************************************************/
818 java_objectheader *builtin_fast_new(classinfo *c)
820 java_objectheader *o;
821 #if defined(ENABLE_RT_TIMING)
822 struct timespec time_start, time_end;
824 #if defined(ENABLE_CYCLES_STATS)
825 u8 cycles_start, cycles_end;
828 RT_TIMING_GET_TIME(time_start);
829 CYCLES_STATS_GET(cycles_start);
831 /* is the class loaded */
833 assert(c->state & CLASS_LOADED);
835 /* check if we can instantiate this class */
837 if (c->flags & ACC_ABSTRACT)
840 /* is the class linked */
842 if (!(c->state & CLASS_LINKED))
845 if (!(c->state & CLASS_INITIALIZED))
848 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
849 c->finalizer, false);
856 #if defined(ENABLE_THREADS)
857 lock_init_object_lock(o);
860 CYCLES_STATS_GET(cycles_end);
861 RT_TIMING_GET_TIME(time_end);
863 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
864 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
870 /* builtin_newarray ************************************************************
872 Creates an array with the given vftbl on the heap. This function
873 takes as class argument an array class.
875 Return value: pointer to the array or NULL if no memory is available
877 *******************************************************************************/
879 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
881 arraydescriptor *desc;
886 #if defined(ENABLE_RT_TIMING)
887 struct timespec time_start, time_end;
890 RT_TIMING_GET_TIME(time_start);
892 desc = arrayclass->vftbl->arraydesc;
893 dataoffset = desc->dataoffset;
894 componentsize = desc->componentsize;
897 exceptions_throw_negativearraysizeexception();
901 actualsize = dataoffset + size * componentsize;
903 /* check for overflow */
905 if (((u4) actualsize) < ((u4) size)) {
906 exceptions_throw_outofmemoryerror();
910 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
915 a->objheader.vftbl = arrayclass->vftbl;
917 #if defined(ENABLE_THREADS)
918 lock_init_object_lock(&a->objheader);
923 RT_TIMING_GET_TIME(time_end);
924 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
930 /* builtin_anewarray ***********************************************************
932 Creates an array of references to the given class type on the heap.
934 Return value: pointer to the array or NULL if no memory is
937 *******************************************************************************/
939 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
941 classinfo *arrayclass;
943 /* is class loaded */
945 assert(componentclass->state & CLASS_LOADED);
947 /* is class linked */
949 if (!(componentclass->state & CLASS_LINKED))
950 if (!link_class(componentclass))
953 arrayclass = class_array_of(componentclass, true);
958 return (java_objectarray *) builtin_newarray(size, arrayclass);
962 /* builtin_newarray_boolean ****************************************************
964 Creates an array of bytes on the heap. The array is designated as
965 an array of booleans (important for casts)
967 Return value: pointer to the array or NULL if no memory is
970 *******************************************************************************/
972 java_booleanarray *builtin_newarray_boolean(s4 size)
974 return (java_booleanarray *)
975 builtin_newarray(size,
976 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
980 /* builtin_newarray_byte *******************************************************
982 Creates an array of 8 bit Integers on the heap.
984 Return value: pointer to the array or NULL if no memory is
987 *******************************************************************************/
989 java_bytearray *builtin_newarray_byte(s4 size)
991 return (java_bytearray *)
992 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
996 /* builtin_newarray_char *******************************************************
998 Creates an array of characters on the heap.
1000 Return value: pointer to the array or NULL if no memory is
1003 *******************************************************************************/
1005 java_chararray *builtin_newarray_char(s4 size)
1007 return (java_chararray *)
1008 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1012 /* builtin_newarray_short ******************************************************
1014 Creates an array of 16 bit Integers on the heap.
1016 Return value: pointer to the array or NULL if no memory is
1019 *******************************************************************************/
1021 java_shortarray *builtin_newarray_short(s4 size)
1023 return (java_shortarray *)
1024 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1028 /* builtin_newarray_int ********************************************************
1030 Creates an array of 32 bit Integers on the heap.
1032 Return value: pointer to the array or NULL if no memory is
1035 *******************************************************************************/
1037 java_intarray *builtin_newarray_int(s4 size)
1039 return (java_intarray *)
1040 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1044 /* builtin_newarray_long *******************************************************
1046 Creates an array of 64 bit Integers on the heap.
1048 Return value: pointer to the array or NULL if no memory is
1051 *******************************************************************************/
1053 java_longarray *builtin_newarray_long(s4 size)
1055 return (java_longarray *)
1056 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1060 /* builtin_newarray_float ******************************************************
1062 Creates an array of 32 bit IEEE floats on the heap.
1064 Return value: pointer to the array or NULL if no memory is
1067 *******************************************************************************/
1069 java_floatarray *builtin_newarray_float(s4 size)
1071 return (java_floatarray *)
1072 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1076 /* builtin_newarray_double *****************************************************
1078 Creates an array of 64 bit IEEE floats on the heap.
1080 Return value: pointer to the array or NULL if no memory is
1083 *******************************************************************************/
1085 java_doublearray *builtin_newarray_double(s4 size)
1087 return (java_doublearray *)
1088 builtin_newarray(size,
1089 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1093 /* builtin_multianewarray_intern ***********************************************
1095 Creates a multi-dimensional array on the heap. The dimensions are
1096 passed in an array of longs.
1099 n............number of dimensions to create
1100 arrayvftbl...vftbl of the array class
1101 dims.........array containing the size of each dimension to create
1103 Return value: pointer to the array or NULL if no memory is
1106 ******************************************************************************/
1108 static java_arrayheader *builtin_multianewarray_intern(int n,
1109 classinfo *arrayclass,
1113 java_arrayheader *a;
1114 classinfo *componentclass;
1117 /* create this dimension */
1119 size = (s4) dims[0];
1120 a = builtin_newarray(size, arrayclass);
1125 /* if this is the last dimension return */
1130 /* get the class of the components to create */
1132 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1134 /* The verifier guarantees that the dimension count is in the range. */
1136 /* create the component arrays */
1138 for (i = 0; i < size; i++) {
1139 java_arrayheader *ea =
1140 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1141 /* we save an s4 to a s8 slot, 8-byte aligned */
1143 builtin_multianewarray_intern(n, componentclass, dims + 2);
1145 builtin_multianewarray_intern(n, componentclass, dims + 1);
1151 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1158 /* builtin_multianewarray ******************************************************
1160 Wrapper for builtin_multianewarray_intern which checks all
1161 dimensions before we start allocating.
1163 ******************************************************************************/
1165 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1171 /* check all dimensions before doing anything */
1173 for (i = 0; i < n; i++) {
1174 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1175 /* we save an s4 to a s8 slot, 8-byte aligned */
1176 size = (s4) dims[i * 2];
1178 size = (s4) dims[i];
1182 exceptions_throw_negativearraysizeexception();
1187 /* now call the real function */
1189 return builtin_multianewarray_intern(n, arrayclass, dims);
1193 /*****************************************************************************
1196 Various functions for printing a message at method entry or exit (for
1199 *****************************************************************************/
1201 #if !defined(NDEBUG)
1202 static s4 methodindent = 0;
1203 static u4 callcount = 0;
1205 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1215 if (opt_verbosecall && indent)
1218 /* calculate message length */
1222 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1225 logtextlen = strlen("Some Throwable");
1228 logtextlen += strlen(" thrown in ");
1232 utf_bytes(m->class->name) +
1234 utf_bytes(m->name) +
1235 utf_bytes(m->descriptor) +
1236 strlen("(NOSYNC,NATIVE");
1238 #if SIZEOF_VOID_P == 8
1240 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1242 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1245 if (m->class->sourcefile == NULL)
1246 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1248 logtextlen += utf_bytes(m->class->sourcefile);
1250 logtextlen += strlen(":65536)");
1254 logtextlen += strlen("call_java_method");
1257 logtextlen += strlen("0");
1259 /* allocate memory */
1261 dumpsize = dump_size();
1263 logtext = DMNEW(char, logtextlen);
1266 strcpy(logtext, "Exception ");
1267 utf_cat_classname(logtext, xptr->vftbl->class->name);
1270 strcpy(logtext, "Some Throwable");
1273 strcat(logtext, " thrown in ");
1276 utf_cat_classname(logtext, m->class->name);
1277 strcat(logtext, ".");
1278 utf_cat(logtext, m->name);
1279 utf_cat(logtext, m->descriptor);
1281 if (m->flags & ACC_SYNCHRONIZED)
1282 strcat(logtext, "(SYNC");
1284 strcat(logtext, "(NOSYNC");
1286 if (m->flags & ACC_NATIVE) {
1287 strcat(logtext, ",NATIVE");
1291 #if SIZEOF_VOID_P == 8
1292 sprintf(logtext + strlen(logtext),
1293 ")(0x%016lx) at position 0x%016lx",
1294 (ptrint) code->entrypoint, (ptrint) pos);
1296 sprintf(logtext + strlen(logtext),
1297 ")(0x%08x) at position 0x%08x",
1298 (ptrint) code->entrypoint, (ptrint) pos);
1303 /* XXX preliminary: This should get the actual codeinfo */
1304 /* in which the exception happened. */
1307 #if SIZEOF_VOID_P == 8
1308 sprintf(logtext + strlen(logtext),
1309 ")(0x%016lx) at position 0x%016lx (",
1310 (ptrint) code->entrypoint, (ptrint) pos);
1312 sprintf(logtext + strlen(logtext),
1313 ")(0x%08x) at position 0x%08x (",
1314 (ptrint) code->entrypoint, (ptrint) pos);
1317 if (m->class->sourcefile == NULL)
1318 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1320 utf_cat(logtext, m->class->sourcefile);
1322 sprintf(logtext + strlen(logtext), ":%d)", 0);
1326 strcat(logtext, "call_java_method");
1330 /* release memory */
1332 dump_release(dumpsize);
1336 #endif /* !defined(NDEBUG) */
1339 /* builtin_print_argument ******************************************************
1341 Prints arguments and return values for the call trace.
1343 *******************************************************************************/
1345 #if !defined(NDEBUG)
1346 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1347 typedesc *paramtype, s8 value)
1350 java_objectheader *o;
1355 switch (paramtype->type) {
1358 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1363 #if SIZEOF_VOID_P == 4
1364 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1366 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1372 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1377 #if SIZEOF_VOID_P == 4
1378 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1380 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1385 #if SIZEOF_VOID_P == 4
1386 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1388 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1391 /* cast to java.lang.Object */
1393 o = (java_objectheader *) (ptrint) value;
1395 /* check return argument for java.lang.Class or java.lang.String */
1398 if (o->vftbl->class == class_java_lang_String) {
1399 /* get java.lang.String object and the length of the
1402 u = javastring_toutf(o, false);
1404 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1406 /* realloc memory for string length */
1408 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1411 /* convert to utf8 string and strcat it to the logtext */
1413 strcat(logtext, " (String = \"");
1414 utf_cat(logtext, u);
1415 strcat(logtext, "\")");
1418 if (o->vftbl->class == class_java_lang_Class) {
1419 /* if the object returned is a java.lang.Class
1420 cast it to classinfo structure and get the name
1423 c = (classinfo *) o;
1428 /* if the object returned is not a java.lang.String or
1429 a java.lang.Class just print the name of the class */
1431 u = o->vftbl->class->name;
1434 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1436 /* realloc memory for string length */
1438 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1441 /* strcat to the logtext */
1443 strcat(logtext, " (Class = \"");
1444 utf_cat_classname(logtext, u);
1445 strcat(logtext, "\")");
1452 #endif /* !defined(NDEBUG) */
1455 /* builtin_verbosecall_enter ***************************************************
1457 Print method call with arguments for -verbose:call.
1459 *******************************************************************************/
1461 #if !defined(NDEBUG)
1463 #ifdef TRACE_ARGS_NUM
1464 void builtin_verbosecall_enter(s8 a0, s8 a1,
1465 # if TRACE_ARGS_NUM >= 4
1468 # if TRACE_ARGS_NUM >= 6
1471 # if TRACE_ARGS_NUM == 8
1485 /* calculate message length */
1488 strlen("4294967295 ") +
1489 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1491 strlen("called: ") +
1492 utf_bytes(m->class->name) +
1494 utf_bytes(m->name) +
1495 utf_bytes(m->descriptor);
1497 /* Actually it's not possible to have all flags printed, but:
1502 strlen(" PRIVATE") +
1503 strlen(" PROTECTED") +
1506 strlen(" SYNCHRONIZED") +
1507 strlen(" VOLATILE") +
1508 strlen(" TRANSIENT") +
1510 strlen(" INTERFACE") +
1511 strlen(" ABSTRACT");
1513 /* add maximal argument length */
1517 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1518 strlen("...(255)") +
1521 /* allocate memory */
1523 dumpsize = dump_size();
1525 logtext = DMNEW(char, logtextlen);
1529 sprintf(logtext, "%10d ", callcount);
1530 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1532 pos = strlen(logtext);
1534 for (i = 0; i < methodindent; i++)
1535 logtext[pos++] = '\t';
1537 strcpy(logtext + pos, "called: ");
1539 utf_cat_classname(logtext, m->class->name);
1540 strcat(logtext, ".");
1541 utf_cat(logtext, m->name);
1542 utf_cat(logtext, m->descriptor);
1544 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1545 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1546 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1547 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1548 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1549 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1550 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1551 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1552 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1553 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1554 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1556 strcat(logtext, "(");
1558 if (md->paramcount >= 1) {
1559 logtext = builtin_print_argument(logtext, &logtextlen,
1560 &md->paramtypes[0], a0);
1563 if (md->paramcount >= 2) {
1564 strcat(logtext, ", ");
1566 logtext = builtin_print_argument(logtext, &logtextlen,
1567 &md->paramtypes[1], a1);
1570 #if TRACE_ARGS_NUM >= 4
1571 if (md->paramcount >= 3) {
1572 strcat(logtext, ", ");
1574 logtext = builtin_print_argument(logtext, &logtextlen,
1575 &md->paramtypes[2], a2);
1578 if (md->paramcount >= 4) {
1579 strcat(logtext, ", ");
1581 logtext = builtin_print_argument(logtext, &logtextlen,
1582 &md->paramtypes[3], a3);
1586 #if TRACE_ARGS_NUM >= 6
1587 if (md->paramcount >= 5) {
1588 strcat(logtext, ", ");
1590 logtext = builtin_print_argument(logtext, &logtextlen,
1591 &md->paramtypes[4], a4);
1594 if (md->paramcount >= 6) {
1595 strcat(logtext, ", ");
1597 logtext = builtin_print_argument(logtext, &logtextlen,
1598 &md->paramtypes[5], a5);
1602 #if TRACE_ARGS_NUM == 8
1603 if (md->paramcount >= 7) {
1604 strcat(logtext, ", ");
1606 logtext = builtin_print_argument(logtext, &logtextlen,
1607 &md->paramtypes[6], a6);
1610 if (md->paramcount >= 8) {
1611 strcat(logtext, ", ");
1613 logtext = builtin_print_argument(logtext, &logtextlen,
1614 &md->paramtypes[7], a7);
1618 if (md->paramcount > 8) {
1619 sprintf(logtext + strlen(logtext), ", ...(%d)",
1620 md->paramcount - TRACE_ARGS_NUM);
1623 strcat(logtext, ")");
1627 /* release memory */
1629 dump_release(dumpsize);
1634 #endif /* !defined(NDEBUG) */
1637 /* builtin_verbosecall_exit ****************************************************
1639 Print method exit for -verbose:call.
1641 *******************************************************************************/
1643 #if !defined(NDEBUG)
1644 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1656 /* calculate message length */
1659 strlen("4294967295 ") +
1660 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1662 strlen("finished: ") +
1663 utf_bytes(m->class->name) +
1665 utf_bytes(m->name) +
1666 utf_bytes(m->descriptor) +
1667 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1669 /* add maximal argument length */
1671 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1673 /* allocate memory */
1675 dumpsize = dump_size();
1677 logtext = DMNEW(char, logtextlen);
1679 /* outdent the log message */
1684 log_text("WARNING: unmatched methodindent--");
1686 /* generate the message */
1688 sprintf(logtext, " ");
1689 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1691 pos = strlen(logtext);
1693 for (i = 0; i < methodindent; i++)
1694 logtext[pos++] = '\t';
1696 strcpy(logtext + pos, "finished: ");
1697 utf_cat_classname(logtext, m->class->name);
1698 strcat(logtext, ".");
1699 utf_cat(logtext, m->name);
1700 utf_cat(logtext, m->descriptor);
1702 if (!IS_VOID_TYPE(md->returntype.type)) {
1703 strcat(logtext, "->");
1705 switch (md->returntype.type) {
1722 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1727 /* release memory */
1729 dump_release(dumpsize);
1731 #endif /* !defined(NDEBUG) */
1734 #if defined(ENABLE_CYCLES_STATS)
1735 void builtin_print_cycles_stats(FILE *file)
1737 fprintf(file,"builtin cylce count statistics:\n");
1739 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1740 CYCLES_STATS_PRINT(builtin_new ,file);
1744 #endif /* defined(ENABLE_CYCLES_STATS) */
1747 /*****************************************************************************
1748 MISCELLANEOUS HELPER FUNCTIONS
1749 *****************************************************************************/
1753 /*********** Functions for integer divisions *****************************
1755 On some systems (eg. DEC ALPHA), integer division is not supported by the
1756 CPU. These helper functions implement the missing functionality.
1758 ******************************************************************************/
1760 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1761 s4 builtin_idiv(s4 a, s4 b)
1770 s4 builtin_irem(s4 a, s4 b)
1778 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1781 /* functions for long arithmetics **********************************************
1783 On systems where 64 bit Integers are not supported by the CPU,
1784 these functions are needed.
1786 ******************************************************************************/
1788 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1789 s8 builtin_ladd(s8 a, s8 b)
1802 s8 builtin_lsub(s8 a, s8 b)
1815 s8 builtin_lneg(s8 a)
1827 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1830 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1831 s8 builtin_lmul(s8 a, s8 b)
1843 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1846 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1847 s8 builtin_ldiv(s8 a, s8 b)
1860 s8 builtin_lrem(s8 a, s8 b)
1872 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1875 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1876 s8 builtin_lshl(s8 a, s4 b)
1889 s8 builtin_lshr(s8 a, s4 b)
1902 s8 builtin_lushr(s8 a, s4 b)
1907 c = ((u8) a) >> (b & 63);
1914 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1917 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1918 s8 builtin_land(s8 a, s8 b)
1931 s8 builtin_lor(s8 a, s8 b)
1944 s8 builtin_lxor(s8 a, s8 b)
1956 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1959 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1960 s4 builtin_lcmp(s8 a, s8 b)
1974 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1977 /* functions for unsupported floating instructions ****************************/
1979 /* used to convert FLT_xxx defines into float values */
1981 static inline float intBitsToFloat(s4 i)
1990 /* used to convert DBL_xxx defines into double values */
1992 static inline float longBitsToDouble(s8 l)
2002 float builtin_fadd(float a, float b)
2004 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2005 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2016 if (copysignf(1.0, a) == copysignf(1.0, b))
2019 return intBitsToFloat(FLT_NAN);
2025 float builtin_fsub(float a, float b)
2027 return builtin_fadd(a, builtin_fneg(b));
2031 float builtin_fmul(float a, float b)
2033 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2034 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2036 if (finitef(b)) return a * b;
2038 if (a == 0) return intBitsToFloat(FLT_NAN);
2039 else return copysignf(b, copysignf(1.0, b)*a);
2044 if (b == 0) return intBitsToFloat(FLT_NAN);
2045 else return copysignf(a, copysignf(1.0, a)*b);
2048 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2054 /* builtin_ddiv ****************************************************************
2056 Implementation as described in VM Spec.
2058 *******************************************************************************/
2060 float builtin_fdiv(float a, float b)
2064 /* If neither value1' nor value2' is NaN, the sign of the result */
2065 /* is positive if both values have the same sign, negative if the */
2066 /* values have different signs. */
2072 /* If either value1' or value2' is NaN, the result is NaN. */
2074 return intBitsToFloat(FLT_NAN);
2077 /* Division of a finite value by an infinity results in a */
2078 /* signed zero, with the sign-producing rule just given. */
2080 /* is sign equal? */
2082 if (copysignf(1.0, a) == copysignf(1.0, b))
2091 /* If either value1' or value2' is NaN, the result is NaN. */
2093 return intBitsToFloat(FLT_NAN);
2095 } else if (finitef(b)) {
2096 /* Division of an infinity by a finite value results in a signed */
2097 /* infinity, with the sign-producing rule just given. */
2099 /* is sign equal? */
2101 if (copysignf(1.0, a) == copysignf(1.0, b))
2102 return intBitsToFloat(FLT_POSINF);
2104 return intBitsToFloat(FLT_NEGINF);
2107 /* Division of an infinity by an infinity results in NaN. */
2109 return intBitsToFloat(FLT_NAN);
2115 float builtin_fneg(float a)
2117 if (isnanf(a)) return a;
2119 if (finitef(a)) return -a;
2120 else return copysignf(a, -copysignf(1.0, a));
2123 #endif /* !SUPPORT_FLOAT */
2126 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2127 s4 builtin_fcmpl(float a, float b)
2135 if (!finitef(a) || !finitef(b)) {
2136 a = finitef(a) ? 0 : copysignf(1.0, a);
2137 b = finitef(b) ? 0 : copysignf(1.0, b);
2150 s4 builtin_fcmpg(float a, float b)
2152 if (isnanf(a)) return 1;
2153 if (isnanf(b)) return 1;
2154 if (!finitef(a) || !finitef(b)) {
2155 a = finitef(a) ? 0 : copysignf(1.0, a);
2156 b = finitef(b) ? 0 : copysignf(1.0, b);
2158 if (a > b) return 1;
2159 if (a == b) return 0;
2162 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2165 float builtin_frem(float a, float b)
2171 /* functions for unsupported double instructions ******************************/
2174 double builtin_dadd(double a, double b)
2176 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2177 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2179 if (finite(b)) return a + b;
2183 if (finite(b)) return a;
2185 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2186 else return longBitsToDouble(DBL_NAN);
2192 double builtin_dsub(double a, double b)
2194 return builtin_dadd(a, builtin_dneg(b));
2198 double builtin_dmul(double a, double b)
2200 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2201 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2203 if (finite(b)) return a * b;
2205 if (a == 0) return longBitsToDouble(DBL_NAN);
2206 else return copysign(b, copysign(1.0, b) * a);
2211 if (b == 0) return longBitsToDouble(DBL_NAN);
2212 else return copysign(a, copysign(1.0, a) * b);
2215 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2221 /* builtin_ddiv ****************************************************************
2223 Implementation as described in VM Spec.
2225 *******************************************************************************/
2227 double builtin_ddiv(double a, double b)
2231 /* If neither value1' nor value2' is NaN, the sign of the result */
2232 /* is positive if both values have the same sign, negative if the */
2233 /* values have different signs. */
2239 /* If either value1' or value2' is NaN, the result is NaN. */
2241 return longBitsToDouble(DBL_NAN);
2244 /* Division of a finite value by an infinity results in a */
2245 /* signed zero, with the sign-producing rule just given. */
2247 /* is sign equal? */
2249 if (copysign(1.0, a) == copysign(1.0, b))
2258 /* If either value1' or value2' is NaN, the result is NaN. */
2260 return longBitsToDouble(DBL_NAN);
2262 } else if (finite(b)) {
2263 /* Division of an infinity by a finite value results in a signed */
2264 /* infinity, with the sign-producing rule just given. */
2266 /* is sign equal? */
2268 if (copysign(1.0, a) == copysign(1.0, b))
2269 return longBitsToDouble(DBL_POSINF);
2271 return longBitsToDouble(DBL_NEGINF);
2274 /* Division of an infinity by an infinity results in NaN. */
2276 return longBitsToDouble(DBL_NAN);
2282 /* builtin_dneg ****************************************************************
2284 Implemented as described in VM Spec.
2286 *******************************************************************************/
2288 double builtin_dneg(double a)
2291 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2298 /* If the operand is a zero, the result is the zero of opposite */
2304 /* If the operand is an infinity, the result is the infinity of */
2305 /* opposite sign. */
2307 return copysign(a, -copysign(1.0, a));
2311 #endif /* !SUPPORT_DOUBLE */
2314 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2315 s4 builtin_dcmpl(double a, double b)
2323 if (!finite(a) || !finite(b)) {
2324 a = finite(a) ? 0 : copysign(1.0, a);
2325 b = finite(b) ? 0 : copysign(1.0, b);
2338 s4 builtin_dcmpg(double a, double b)
2346 if (!finite(a) || !finite(b)) {
2347 a = finite(a) ? 0 : copysign(1.0, a);
2348 b = finite(b) ? 0 : copysign(1.0, b);
2359 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2362 double builtin_drem(double a, double b)
2368 /* conversion operations ******************************************************/
2371 s8 builtin_i2l(s4 i)
2383 s4 builtin_l2i(s8 l)
2394 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2395 float builtin_i2f(s4 a)
2397 float f = (float) a;
2400 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2403 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2404 double builtin_i2d(s4 a)
2406 double d = (double) a;
2409 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2412 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2413 float builtin_l2f(s8 a)
2416 float f = (float) a;
2422 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2425 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2426 double builtin_l2d(s8 a)
2429 double d = (double) a;
2435 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2438 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2439 s4 builtin_f2i(float a)
2443 i = builtin_d2i((double) a);
2454 if (a < (-2147483648))
2455 return (-2147483648);
2458 f = copysignf((float) 1.0, a);
2461 return (-2147483648); */
2463 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2466 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2467 s8 builtin_f2l(float a)
2471 l = builtin_d2l((double) a);
2478 if (a > 9223372036854775807L)
2479 return 9223372036854775807L;
2480 if (a < (-9223372036854775808L))
2481 return (-9223372036854775808L);
2486 f = copysignf((float) 1.0, a);
2488 return 9223372036854775807L;
2489 return (-9223372036854775808L); */
2491 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2494 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2495 s4 builtin_d2i(double a)
2500 if (a >= 2147483647)
2502 if (a <= (-2147483647-1))
2503 return (-2147483647-1);
2508 d = copysign(1.0, a);
2511 return (-2147483647-1);
2513 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2516 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2517 s8 builtin_d2l(double a)
2522 if (a >= 9223372036854775807LL)
2523 return 9223372036854775807LL;
2524 if (a <= (-9223372036854775807LL-1))
2525 return (-9223372036854775807LL-1);
2530 d = copysign(1.0, a);
2532 return 9223372036854775807LL;
2533 return (-9223372036854775807LL-1);
2535 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2538 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2539 double builtin_f2d(float a)
2541 if (finitef(a)) return (double) a;
2544 return longBitsToDouble(DBL_NAN);
2546 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2550 float builtin_d2f(double a)
2556 return intBitsToFloat(FLT_NAN);
2558 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2561 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2564 /* builtin_arraycopy ***********************************************************
2566 Builtin for java.lang.System.arraycopy.
2568 ATTENTION: This builtin function returns a boolean value to signal
2569 the ICMD_BUILTIN if there was an exception.
2571 *******************************************************************************/
2573 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2574 java_arrayheader *dest, s4 destStart, s4 len)
2576 arraydescriptor *sdesc;
2577 arraydescriptor *ddesc;
2580 if ((src == NULL) || (dest == NULL)) {
2581 exceptions_throw_nullpointerexception();
2585 sdesc = src->objheader.vftbl->arraydesc;
2586 ddesc = dest->objheader.vftbl->arraydesc;
2588 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2589 exceptions_throw_arraystoreexception();
2593 /* we try to throw exception with the same message as SUN does */
2595 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2596 (srcStart + len < 0) || (srcStart + len > src->size) ||
2597 (destStart + len < 0) || (destStart + len > dest->size)) {
2598 exceptions_throw_arrayindexoutofboundsexception();
2602 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2603 /* We copy primitive values or references of exactly the same type */
2605 s4 dataoffset = sdesc->dataoffset;
2606 s4 componentsize = sdesc->componentsize;
2608 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2609 ((u1 *) src) + dataoffset + componentsize * srcStart,
2610 (size_t) len * componentsize);
2613 /* We copy references of different type */
2615 java_objectarray *oas = (java_objectarray *) src;
2616 java_objectarray *oad = (java_objectarray *) dest;
2618 if (destStart <= srcStart) {
2619 for (i = 0; i < len; i++) {
2620 java_objectheader *o = oas->data[srcStart + i];
2622 if (!builtin_canstore(oad, o))
2625 oad->data[destStart + i] = o;
2629 /* XXX this does not completely obey the specification!
2630 If an exception is thrown only the elements above the
2631 current index have been copied. The specification
2632 requires that only the elements *below* the current
2633 index have been copied before the throw. */
2635 for (i = len - 1; i >= 0; i--) {
2636 java_objectheader *o = oas->data[srcStart + i];
2638 if (!builtin_canstore(oad, o))
2641 oad->data[destStart + i] = o;
2650 /* builtin_currenttimemillis ***************************************************
2652 Return the current time in milliseconds.
2654 *******************************************************************************/
2656 s8 builtin_currenttimemillis(void)
2661 if (gettimeofday(&tv, NULL) == -1)
2662 vm_abort("gettimeofday failed: %s", strerror(errno));
2664 result = (s8) tv.tv_sec;
2666 result += (tv.tv_usec / 1000);
2672 /* builtin_clone ***************************************************************
2674 Function for cloning objects or arrays.
2676 *******************************************************************************/
2678 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2680 arraydescriptor *ad;
2681 java_arrayheader *ah;
2684 java_objectheader *co; /* cloned object header */
2686 /* get the array descriptor */
2688 ad = o->vftbl->arraydesc;
2690 /* we are cloning an array */
2693 ah = (java_arrayheader *) o;
2695 size = ad->dataoffset + ad->componentsize * ah->size;
2697 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2702 MCOPY(co, o, u1, size);
2704 #if defined(ENABLE_GC_CACAO)
2705 heap_init_objectheader(co, size);
2708 #if defined(ENABLE_THREADS)
2709 lock_init_object_lock(co);
2715 /* we are cloning a non-array */
2717 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2718 exceptions_throw_clonenotsupportedexception();
2722 /* get the class of the object */
2724 c = o->vftbl->class;
2726 /* create new object */
2728 co = builtin_new(c);
2733 MCOPY(co, o, u1, c->instancesize);
2735 #if defined(ENABLE_GC_CACAO)
2736 heap_init_objectheader(co, c->instancesize);
2739 #if defined(ENABLE_THREADS)
2740 lock_init_object_lock(co);
2748 * These are local overrides for various environment variables in Emacs.
2749 * Please do not remove this and leave it at the end of the file, where
2750 * Emacs will automagically detect them.
2751 * ---------------------------------------------------------------------
2754 * indent-tabs-mode: t
2758 * vim:noexpandtab:sw=4:ts=4: