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 7577 2007-03-25 20:55:06Z twisti $
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) {
307 return (first != last ? first : NULL);
311 /* builtintable_replace_function ***********************************************
315 *******************************************************************************/
317 #if defined(ENABLE_JIT)
318 bool builtintable_replace_function(void *iptr_)
321 builtintable_entry *bte;
324 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
326 /* get name and descriptor of the function */
329 case ICMD_INVOKESTATIC:
330 /* The instruction MUST be resolved, otherwise we run into
331 lazy loading troubles. Anyway, we should/can only replace
332 very VM-close functions. */
334 if (INSTRUCTION_IS_UNRESOLVED(iptr))
337 mr = iptr->sx.s23.s3.fmiref;
344 /* search the function table */
346 for (bte = builtintable_function; bte->fp != NULL; bte++) {
347 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
348 (mr->name == bte->name) &&
349 (mr->descriptor == bte->descriptor)) {
351 /* set the values in the instruction */
353 iptr->opc = bte->opcode;
354 iptr->sx.s23.s3.bte = bte;
355 if (bte->checkexception)
356 iptr->flags.bits |= INS_FLAG_CHECK;
358 iptr->flags.bits &= ~INS_FLAG_CHECK;
366 #endif /* defined(ENABLE_JIT) */
369 /*****************************************************************************
371 *****************************************************************************/
373 /* builtin_instanceof **********************************************************
375 Checks if an object is an instance of some given class (or subclass
376 of that class). If class is an interface, checks if the interface
379 Return value: 1 ... o is an instance of class or implements the interface
380 0 ... otherwise or if o == NULL
382 *******************************************************************************/
384 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
389 return class_isanysubclass(o->vftbl->class, class);
394 /* builtin_checkcast ***********************************************************
396 The same as builtin_instanceof except that 1 is returned when o ==
399 *******************************************************************************/
401 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
406 if (class_isanysubclass(o->vftbl->class, class))
413 /* builtin_descriptorscompatible ***********************************************
415 Checks if two array type descriptors are assignment compatible
417 Return value: 1 ... target = desc is possible
420 *******************************************************************************/
422 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
423 arraydescriptor *target)
428 if (desc->arraytype != target->arraytype)
431 if (desc->arraytype != ARRAYTYPE_OBJECT)
434 /* {both arrays are arrays of references} */
436 if (desc->dimension == target->dimension) {
437 /* an array which contains elements of interface types is
438 allowed to be casted to Object (JOWENN)*/
440 if ((desc->elementvftbl->baseval < 0) &&
441 (target->elementvftbl->baseval == 1))
444 return class_isanysubclass(desc->elementvftbl->class,
445 target->elementvftbl->class);
448 if (desc->dimension < target->dimension)
451 /* {desc has higher dimension than target} */
453 return class_isanysubclass(pseudo_class_Arraystub,
454 target->elementvftbl->class);
458 /* builtin_arraycheckcast ******************************************************
460 Checks if an object is really a subtype of the requested array
461 type. The object has to be an array to begin with. For simple
462 arrays (int, short, double, etc.) the types have to match exactly.
463 For arrays of objects, the type of elements in the array has to be
464 a subtype (or the same type) of the requested element type. For
465 arrays of arrays (which in turn can again be arrays of arrays), the
466 types at the lowest level have to satisfy the corresponding sub
469 *******************************************************************************/
471 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
473 arraydescriptor *desc;
478 desc = o->vftbl->arraydesc;
483 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
487 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
492 return builtin_arraycheckcast(o, targetclass);
496 /* builtin_throw_exception *****************************************************
498 Sets the exceptionptr with the thrown exception and prints some
499 debugging information. Called from asm_vm_call_method.
501 *******************************************************************************/
503 void *builtin_throw_exception(java_objectheader *xptr)
506 java_lang_Throwable *t;
512 t = (java_lang_Throwable *) xptr;
514 /* calculate message length */
516 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
520 utf_bytes(xptr->vftbl->class->name);
521 if (t->detailMessage) {
522 logtextlen += strlen(": ") +
523 u2_utflength(t->detailMessage->value->data
524 + t->detailMessage->offset,
525 t->detailMessage->count);
529 logtextlen += strlen("(nil)");
532 /* allocate memory */
534 dumpsize = dump_size();
536 logtext = DMNEW(char, logtextlen);
538 strcpy(logtext, "Builtin exception thrown: ");
541 utf_cat_classname(logtext, xptr->vftbl->class->name);
543 if (t->detailMessage) {
546 buf = javastring_tochar((java_objectheader *) t->detailMessage);
547 strcat(logtext, ": ");
548 strcat(logtext, buf);
549 MFREE(buf, char, strlen(buf) + 1);
553 strcat(logtext, "(nil)");
560 dump_release(dumpsize);
562 #endif /* !defined(NDEBUG) */
564 /* actually set the exception */
566 exceptions_set_exception(xptr);
568 /* Return a NULL pointer. This is required for vm_call_method to
569 check for an exception. This is for convenience. */
575 /* builtin_canstore ************************************************************
577 Checks, if an object can be stored in an array.
579 Return value: 1 ... possible
580 0 ... otherwise (throws an ArrayStoreException)
582 *******************************************************************************/
584 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
586 arraydescriptor *desc;
587 arraydescriptor *valuedesc;
588 vftbl_t *componentvftbl;
591 castinfo classvalues;
597 /* The following is guaranteed (by verifier checks):
599 * *) oa->...vftbl->arraydesc != NULL
600 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
601 * *) o->vftbl is not an interface vftbl
604 desc = oa->header.objheader.vftbl->arraydesc;
605 componentvftbl = desc->componentvftbl;
606 valuevftbl = o->vftbl;
607 valuedesc = valuevftbl->arraydesc;
609 if ((desc->dimension - 1) == 0) {
610 /* {oa is a one-dimensional array} */
611 /* {oa is an array of references} */
613 if (valuevftbl == componentvftbl)
616 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
618 base = classvalues.super_baseval;
621 /* an array of interface references */
623 result = ((valuevftbl->interfacetablelength > -base) &&
624 (valuevftbl->interfacetable[base] != NULL));
627 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
628 <= (unsigned) classvalues.super_diffval);
631 else if (valuedesc == NULL) {
632 /* {oa has dimension > 1} */
633 /* {componentvftbl->arraydesc != NULL} */
635 /* check if o is an array */
640 /* {o is an array} */
642 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
645 /* if not possible, throw an exception */
648 exceptions_throw_arraystoreexception();
656 /* This is an optimized version where a is guaranteed to be one-dimensional */
657 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
659 arraydescriptor *desc;
660 vftbl_t *elementvftbl;
664 castinfo classvalues;
668 /* The following is guaranteed (by verifier checks):
670 * *) a->...vftbl->arraydesc != NULL
671 * *) a->...vftbl->arraydesc->elementvftbl != NULL
672 * *) a->...vftbl->arraydesc->dimension == 1
673 * *) o->vftbl is not an interface vftbl
676 desc = a->header.objheader.vftbl->arraydesc;
677 elementvftbl = desc->elementvftbl;
678 valuevftbl = o->vftbl;
680 /* {a is a one-dimensional array} */
682 if (valuevftbl == elementvftbl)
685 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
687 if ((base = classvalues.super_baseval) <= 0)
688 /* an array of interface references */
689 return (valuevftbl->interfacetablelength > -base &&
690 valuevftbl->interfacetable[base] != NULL);
692 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
693 <= (unsigned) classvalues.super_diffval;
699 /* This is an optimized version where a is guaranteed to be a
700 * one-dimensional array of a class type */
701 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
703 vftbl_t *elementvftbl;
706 castinfo classvalues;
710 /* The following is guaranteed (by verifier checks):
712 * *) a->...vftbl->arraydesc != NULL
713 * *) a->...vftbl->arraydesc->elementvftbl != NULL
714 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
715 * *) a->...vftbl->arraydesc->dimension == 1
716 * *) o->vftbl is not an interface vftbl
719 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
720 valuevftbl = o->vftbl;
722 /* {a is a one-dimensional array} */
724 if (valuevftbl == elementvftbl)
727 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
729 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
730 <= (unsigned) classvalues.super_diffval;
736 /* builtin_new *****************************************************************
738 Creates a new instance of class c on the heap.
740 Return value: pointer to the object or NULL if no memory is
743 *******************************************************************************/
745 java_objectheader *builtin_new(classinfo *c)
747 java_objectheader *o;
748 #if defined(ENABLE_RT_TIMING)
749 struct timespec time_start, time_end;
751 #if defined(ENABLE_CYCLES_STATS)
752 u8 cycles_start, cycles_end;
755 RT_TIMING_GET_TIME(time_start);
756 CYCLES_STATS_GET(cycles_start);
758 /* is the class loaded */
760 assert(c->state & CLASS_LOADED);
762 /* check if we can instantiate this class */
764 if (c->flags & ACC_ABSTRACT) {
765 exceptions_throw_instantiationerror(c);
769 /* is the class linked */
771 if (!(c->state & CLASS_LINKED))
775 if (!(c->state & CLASS_INITIALIZED)) {
778 log_message_class("Initialize class (from builtin_new): ", c);
781 if (!initialize_class(c))
785 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
793 #if defined(ENABLE_THREADS)
794 lock_init_object_lock(o);
797 CYCLES_STATS_GET(cycles_end);
798 RT_TIMING_GET_TIME(time_end);
800 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
801 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
807 /* builtin_newarray ************************************************************
809 Creates an array with the given vftbl on the heap. This function
810 takes as class argument an array class.
812 Return value: pointer to the array or NULL if no memory is available
814 *******************************************************************************/
816 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
818 arraydescriptor *desc;
823 #if defined(ENABLE_RT_TIMING)
824 struct timespec time_start, time_end;
827 RT_TIMING_GET_TIME(time_start);
829 desc = arrayclass->vftbl->arraydesc;
830 dataoffset = desc->dataoffset;
831 componentsize = desc->componentsize;
834 exceptions_throw_negativearraysizeexception();
838 actualsize = dataoffset + size * componentsize;
840 /* check for overflow */
842 if (((u4) actualsize) < ((u4) size)) {
843 exceptions_throw_outofmemoryerror();
847 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
852 a->objheader.vftbl = arrayclass->vftbl;
854 #if defined(ENABLE_THREADS)
855 lock_init_object_lock(&a->objheader);
860 RT_TIMING_GET_TIME(time_end);
861 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
867 /* builtin_anewarray ***********************************************************
869 Creates an array of references to the given class type on the heap.
871 Return value: pointer to the array or NULL if no memory is
874 *******************************************************************************/
876 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
878 classinfo *arrayclass;
880 /* is class loaded */
882 assert(componentclass->state & CLASS_LOADED);
884 /* is class linked */
886 if (!(componentclass->state & CLASS_LINKED))
887 if (!link_class(componentclass))
890 arrayclass = class_array_of(componentclass, true);
895 return (java_objectarray *) builtin_newarray(size, arrayclass);
899 /* builtin_newarray_boolean ****************************************************
901 Creates an array of bytes on the heap. The array is designated as
902 an array of booleans (important for casts)
904 Return value: pointer to the array or NULL if no memory is
907 *******************************************************************************/
909 java_booleanarray *builtin_newarray_boolean(s4 size)
911 return (java_booleanarray *)
912 builtin_newarray(size,
913 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
917 /* builtin_newarray_byte *******************************************************
919 Creates an array of 8 bit Integers on the heap.
921 Return value: pointer to the array or NULL if no memory is
924 *******************************************************************************/
926 java_bytearray *builtin_newarray_byte(s4 size)
928 return (java_bytearray *)
929 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
933 /* builtin_newarray_char *******************************************************
935 Creates an array of characters on the heap.
937 Return value: pointer to the array or NULL if no memory is
940 *******************************************************************************/
942 java_chararray *builtin_newarray_char(s4 size)
944 return (java_chararray *)
945 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
949 /* builtin_newarray_short ******************************************************
951 Creates an array of 16 bit Integers on the heap.
953 Return value: pointer to the array or NULL if no memory is
956 *******************************************************************************/
958 java_shortarray *builtin_newarray_short(s4 size)
960 return (java_shortarray *)
961 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
965 /* builtin_newarray_int ********************************************************
967 Creates an array of 32 bit Integers on the heap.
969 Return value: pointer to the array or NULL if no memory is
972 *******************************************************************************/
974 java_intarray *builtin_newarray_int(s4 size)
976 return (java_intarray *)
977 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
981 /* builtin_newarray_long *******************************************************
983 Creates an array of 64 bit Integers on the heap.
985 Return value: pointer to the array or NULL if no memory is
988 *******************************************************************************/
990 java_longarray *builtin_newarray_long(s4 size)
992 return (java_longarray *)
993 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
997 /* builtin_newarray_float ******************************************************
999 Creates an array of 32 bit IEEE floats on the heap.
1001 Return value: pointer to the array or NULL if no memory is
1004 *******************************************************************************/
1006 java_floatarray *builtin_newarray_float(s4 size)
1008 return (java_floatarray *)
1009 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1013 /* builtin_newarray_double *****************************************************
1015 Creates an array of 64 bit IEEE floats on the heap.
1017 Return value: pointer to the array or NULL if no memory is
1020 *******************************************************************************/
1022 java_doublearray *builtin_newarray_double(s4 size)
1024 return (java_doublearray *)
1025 builtin_newarray(size,
1026 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1030 /* builtin_multianewarray_intern ***********************************************
1032 Creates a multi-dimensional array on the heap. The dimensions are
1033 passed in an array of longs.
1036 n............number of dimensions to create
1037 arrayvftbl...vftbl of the array class
1038 dims.........array containing the size of each dimension to create
1040 Return value: pointer to the array or NULL if no memory is
1043 ******************************************************************************/
1045 static java_arrayheader *builtin_multianewarray_intern(int n,
1046 classinfo *arrayclass,
1050 java_arrayheader *a;
1051 classinfo *componentclass;
1054 /* create this dimension */
1056 size = (s4) dims[0];
1057 a = builtin_newarray(size, arrayclass);
1062 /* if this is the last dimension return */
1067 /* get the class of the components to create */
1069 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1071 /* The verifier guarantees that the dimension count is in the range. */
1073 /* create the component arrays */
1075 for (i = 0; i < size; i++) {
1076 java_arrayheader *ea =
1077 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1078 /* we save an s4 to a s8 slot, 8-byte aligned */
1080 builtin_multianewarray_intern(n, componentclass, dims + 2);
1082 builtin_multianewarray_intern(n, componentclass, dims + 1);
1088 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1095 /* builtin_multianewarray ******************************************************
1097 Wrapper for builtin_multianewarray_intern which checks all
1098 dimensions before we start allocating.
1100 ******************************************************************************/
1102 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1108 /* check all dimensions before doing anything */
1110 for (i = 0; i < n; i++) {
1111 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1112 /* we save an s4 to a s8 slot, 8-byte aligned */
1113 size = (s4) dims[i * 2];
1115 size = (s4) dims[i];
1119 exceptions_throw_negativearraysizeexception();
1124 /* now call the real function */
1126 return builtin_multianewarray_intern(n, arrayclass, dims);
1130 /*****************************************************************************
1133 Various functions for printing a message at method entry or exit (for
1136 *****************************************************************************/
1138 #if !defined(NDEBUG)
1139 static s4 methodindent = 0;
1140 static u4 callcount = 0;
1142 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1152 if (opt_verbosecall && indent)
1155 /* calculate message length */
1159 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1162 logtextlen = strlen("Some Throwable");
1165 logtextlen += strlen(" thrown in ");
1169 utf_bytes(m->class->name) +
1171 utf_bytes(m->name) +
1172 utf_bytes(m->descriptor) +
1173 strlen("(NOSYNC,NATIVE");
1175 #if SIZEOF_VOID_P == 8
1177 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1179 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1182 if (m->class->sourcefile == NULL)
1183 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1185 logtextlen += utf_bytes(m->class->sourcefile);
1187 logtextlen += strlen(":65536)");
1191 logtextlen += strlen("call_java_method");
1194 logtextlen += strlen("0");
1196 /* allocate memory */
1198 dumpsize = dump_size();
1200 logtext = DMNEW(char, logtextlen);
1203 strcpy(logtext, "Exception ");
1204 utf_cat_classname(logtext, xptr->vftbl->class->name);
1207 strcpy(logtext, "Some Throwable");
1210 strcat(logtext, " thrown in ");
1213 utf_cat_classname(logtext, m->class->name);
1214 strcat(logtext, ".");
1215 utf_cat(logtext, m->name);
1216 utf_cat(logtext, m->descriptor);
1218 if (m->flags & ACC_SYNCHRONIZED)
1219 strcat(logtext, "(SYNC");
1221 strcat(logtext, "(NOSYNC");
1223 if (m->flags & ACC_NATIVE) {
1224 strcat(logtext, ",NATIVE");
1228 #if SIZEOF_VOID_P == 8
1229 sprintf(logtext + strlen(logtext),
1230 ")(0x%016lx) at position 0x%016lx",
1231 (ptrint) code->entrypoint, (ptrint) pos);
1233 sprintf(logtext + strlen(logtext),
1234 ")(0x%08x) at position 0x%08x",
1235 (ptrint) code->entrypoint, (ptrint) pos);
1240 /* XXX preliminary: This should get the actual codeinfo */
1241 /* in which the exception happened. */
1244 #if SIZEOF_VOID_P == 8
1245 sprintf(logtext + strlen(logtext),
1246 ")(0x%016lx) at position 0x%016lx (",
1247 (ptrint) code->entrypoint, (ptrint) pos);
1249 sprintf(logtext + strlen(logtext),
1250 ")(0x%08x) at position 0x%08x (",
1251 (ptrint) code->entrypoint, (ptrint) pos);
1254 if (m->class->sourcefile == NULL)
1255 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1257 utf_cat(logtext, m->class->sourcefile);
1259 sprintf(logtext + strlen(logtext), ":%d)", 0);
1263 strcat(logtext, "call_java_method");
1267 /* release memory */
1269 dump_release(dumpsize);
1273 #endif /* !defined(NDEBUG) */
1276 /* builtin_print_argument ******************************************************
1278 Prints arguments and return values for the call trace.
1280 *******************************************************************************/
1282 #if !defined(NDEBUG)
1283 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1284 typedesc *paramtype, s8 value)
1287 java_objectheader *o;
1288 java_lang_String *s;
1293 switch (paramtype->type) {
1296 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1301 #if SIZEOF_VOID_P == 4
1302 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1304 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1310 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1315 #if SIZEOF_VOID_P == 4
1316 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1318 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1323 #if SIZEOF_VOID_P == 4
1324 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1326 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1329 /* cast to java.lang.Object */
1331 o = (java_objectheader *) (ptrint) value;
1333 /* check return argument for java.lang.Class or java.lang.String */
1336 if (o->vftbl->class == class_java_lang_String) {
1337 /* get java.lang.String object and the length of the
1340 s = (java_lang_String *) o;
1342 u = javastring_toutf(s, false);
1344 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1346 /* realloc memory for string length */
1348 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1351 /* convert to utf8 string and strcat it to the logtext */
1353 strcat(logtext, " (String = \"");
1354 utf_cat(logtext, u);
1355 strcat(logtext, "\")");
1358 if (o->vftbl->class == class_java_lang_Class) {
1359 /* if the object returned is a java.lang.Class
1360 cast it to classinfo structure and get the name
1363 c = (classinfo *) o;
1368 /* if the object returned is not a java.lang.String or
1369 a java.lang.Class just print the name of the class */
1371 u = o->vftbl->class->name;
1374 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1376 /* realloc memory for string length */
1378 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1381 /* strcat to the logtext */
1383 strcat(logtext, " (Class = \"");
1384 utf_cat_classname(logtext, u);
1385 strcat(logtext, "\")");
1392 #endif /* !defined(NDEBUG) */
1395 /* builtin_verbosecall_enter ***************************************************
1397 Print method call with arguments for -verbose:call.
1399 *******************************************************************************/
1401 #if !defined(NDEBUG)
1403 #ifdef TRACE_ARGS_NUM
1404 void builtin_verbosecall_enter(s8 a0, s8 a1,
1405 # if TRACE_ARGS_NUM >= 4
1408 # if TRACE_ARGS_NUM >= 6
1411 # if TRACE_ARGS_NUM == 8
1425 /* calculate message length */
1428 strlen("4294967295 ") +
1429 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1431 strlen("called: ") +
1432 utf_bytes(m->class->name) +
1434 utf_bytes(m->name) +
1435 utf_bytes(m->descriptor);
1437 /* Actually it's not possible to have all flags printed, but:
1442 strlen(" PRIVATE") +
1443 strlen(" PROTECTED") +
1446 strlen(" SYNCHRONIZED") +
1447 strlen(" VOLATILE") +
1448 strlen(" TRANSIENT") +
1450 strlen(" INTERFACE") +
1451 strlen(" ABSTRACT");
1453 /* add maximal argument length */
1457 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1458 strlen("...(255)") +
1461 /* allocate memory */
1463 dumpsize = dump_size();
1465 logtext = DMNEW(char, logtextlen);
1469 sprintf(logtext, "%10d ", callcount);
1470 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1472 pos = strlen(logtext);
1474 for (i = 0; i < methodindent; i++)
1475 logtext[pos++] = '\t';
1477 strcpy(logtext + pos, "called: ");
1479 utf_cat_classname(logtext, m->class->name);
1480 strcat(logtext, ".");
1481 utf_cat(logtext, m->name);
1482 utf_cat(logtext, m->descriptor);
1484 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1485 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1486 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1487 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1488 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1489 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1490 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1491 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1492 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1493 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1494 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1496 strcat(logtext, "(");
1498 if (md->paramcount >= 1) {
1499 logtext = builtin_print_argument(logtext, &logtextlen,
1500 &md->paramtypes[0], a0);
1503 if (md->paramcount >= 2) {
1504 strcat(logtext, ", ");
1506 logtext = builtin_print_argument(logtext, &logtextlen,
1507 &md->paramtypes[1], a1);
1510 #if TRACE_ARGS_NUM >= 4
1511 if (md->paramcount >= 3) {
1512 strcat(logtext, ", ");
1514 logtext = builtin_print_argument(logtext, &logtextlen,
1515 &md->paramtypes[2], a2);
1518 if (md->paramcount >= 4) {
1519 strcat(logtext, ", ");
1521 logtext = builtin_print_argument(logtext, &logtextlen,
1522 &md->paramtypes[3], a3);
1526 #if TRACE_ARGS_NUM >= 6
1527 if (md->paramcount >= 5) {
1528 strcat(logtext, ", ");
1530 logtext = builtin_print_argument(logtext, &logtextlen,
1531 &md->paramtypes[4], a4);
1534 if (md->paramcount >= 6) {
1535 strcat(logtext, ", ");
1537 logtext = builtin_print_argument(logtext, &logtextlen,
1538 &md->paramtypes[5], a5);
1542 #if TRACE_ARGS_NUM == 8
1543 if (md->paramcount >= 7) {
1544 strcat(logtext, ", ");
1546 logtext = builtin_print_argument(logtext, &logtextlen,
1547 &md->paramtypes[6], a6);
1550 if (md->paramcount >= 8) {
1551 strcat(logtext, ", ");
1553 logtext = builtin_print_argument(logtext, &logtextlen,
1554 &md->paramtypes[7], a7);
1558 if (md->paramcount > 8) {
1559 sprintf(logtext + strlen(logtext), ", ...(%d)",
1560 md->paramcount - TRACE_ARGS_NUM);
1563 strcat(logtext, ")");
1567 /* release memory */
1569 dump_release(dumpsize);
1574 #endif /* !defined(NDEBUG) */
1577 /* builtin_verbosecall_exit ****************************************************
1579 Print method exit for -verbose:call.
1581 *******************************************************************************/
1583 #if !defined(NDEBUG)
1584 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1596 /* calculate message length */
1599 strlen("4294967295 ") +
1600 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1602 strlen("finished: ") +
1603 utf_bytes(m->class->name) +
1605 utf_bytes(m->name) +
1606 utf_bytes(m->descriptor) +
1607 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1609 /* add maximal argument length */
1611 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1613 /* allocate memory */
1615 dumpsize = dump_size();
1617 logtext = DMNEW(char, logtextlen);
1619 /* outdent the log message */
1624 log_text("WARNING: unmatched methodindent--");
1626 /* generate the message */
1628 sprintf(logtext, " ");
1629 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1631 pos = strlen(logtext);
1633 for (i = 0; i < methodindent; i++)
1634 logtext[pos++] = '\t';
1636 strcpy(logtext + pos, "finished: ");
1637 utf_cat_classname(logtext, m->class->name);
1638 strcat(logtext, ".");
1639 utf_cat(logtext, m->name);
1640 utf_cat(logtext, m->descriptor);
1642 if (!IS_VOID_TYPE(md->returntype.type)) {
1643 strcat(logtext, "->");
1645 switch (md->returntype.type) {
1662 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1667 /* release memory */
1669 dump_release(dumpsize);
1671 #endif /* !defined(NDEBUG) */
1674 #if defined(ENABLE_CYCLES_STATS)
1675 void builtin_print_cycles_stats(FILE *file)
1677 fprintf(file,"builtin cylce count statistics:\n");
1679 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1680 CYCLES_STATS_PRINT(builtin_new ,file);
1684 #endif /* defined(ENABLE_CYCLES_STATS) */
1687 /*****************************************************************************
1688 MISCELLANEOUS HELPER FUNCTIONS
1689 *****************************************************************************/
1693 /*********** Functions for integer divisions *****************************
1695 On some systems (eg. DEC ALPHA), integer division is not supported by the
1696 CPU. These helper functions implement the missing functionality.
1698 ******************************************************************************/
1700 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1701 s4 builtin_idiv(s4 a, s4 b)
1710 s4 builtin_irem(s4 a, s4 b)
1718 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1721 /* functions for long arithmetics **********************************************
1723 On systems where 64 bit Integers are not supported by the CPU,
1724 these functions are needed.
1726 ******************************************************************************/
1728 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1729 s8 builtin_ladd(s8 a, s8 b)
1742 s8 builtin_lsub(s8 a, s8 b)
1755 s8 builtin_lneg(s8 a)
1767 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1770 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1771 s8 builtin_lmul(s8 a, s8 b)
1783 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1786 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1787 s8 builtin_ldiv(s8 a, s8 b)
1800 s8 builtin_lrem(s8 a, s8 b)
1812 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1815 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1816 s8 builtin_lshl(s8 a, s4 b)
1829 s8 builtin_lshr(s8 a, s4 b)
1842 s8 builtin_lushr(s8 a, s4 b)
1847 c = ((u8) a) >> (b & 63);
1854 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1857 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1858 s8 builtin_land(s8 a, s8 b)
1871 s8 builtin_lor(s8 a, s8 b)
1884 s8 builtin_lxor(s8 a, s8 b)
1896 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1899 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1900 s4 builtin_lcmp(s8 a, s8 b)
1914 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1917 /* functions for unsupported floating instructions ****************************/
1919 /* used to convert FLT_xxx defines into float values */
1921 static inline float intBitsToFloat(s4 i)
1930 /* used to convert DBL_xxx defines into double values */
1932 static inline float longBitsToDouble(s8 l)
1942 float builtin_fadd(float a, float b)
1944 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1945 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1956 if (copysignf(1.0, a) == copysignf(1.0, b))
1959 return intBitsToFloat(FLT_NAN);
1965 float builtin_fsub(float a, float b)
1967 return builtin_fadd(a, builtin_fneg(b));
1971 float builtin_fmul(float a, float b)
1973 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1974 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1976 if (finitef(b)) return a * b;
1978 if (a == 0) return intBitsToFloat(FLT_NAN);
1979 else return copysignf(b, copysignf(1.0, b)*a);
1984 if (b == 0) return intBitsToFloat(FLT_NAN);
1985 else return copysignf(a, copysignf(1.0, a)*b);
1988 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1994 /* builtin_ddiv ****************************************************************
1996 Implementation as described in VM Spec.
1998 *******************************************************************************/
2000 float builtin_fdiv(float a, float b)
2004 /* If neither value1' nor value2' is NaN, the sign of the result */
2005 /* is positive if both values have the same sign, negative if the */
2006 /* values have different signs. */
2012 /* If either value1' or value2' is NaN, the result is NaN. */
2014 return intBitsToFloat(FLT_NAN);
2017 /* Division of a finite value by an infinity results in a */
2018 /* signed zero, with the sign-producing rule just given. */
2020 /* is sign equal? */
2022 if (copysignf(1.0, a) == copysignf(1.0, b))
2031 /* If either value1' or value2' is NaN, the result is NaN. */
2033 return intBitsToFloat(FLT_NAN);
2035 } else if (finitef(b)) {
2036 /* Division of an infinity by a finite value results in a signed */
2037 /* infinity, with the sign-producing rule just given. */
2039 /* is sign equal? */
2041 if (copysignf(1.0, a) == copysignf(1.0, b))
2042 return intBitsToFloat(FLT_POSINF);
2044 return intBitsToFloat(FLT_NEGINF);
2047 /* Division of an infinity by an infinity results in NaN. */
2049 return intBitsToFloat(FLT_NAN);
2055 float builtin_fneg(float a)
2057 if (isnanf(a)) return a;
2059 if (finitef(a)) return -a;
2060 else return copysignf(a, -copysignf(1.0, a));
2063 #endif /* !SUPPORT_FLOAT */
2066 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2067 s4 builtin_fcmpl(float a, float b)
2075 if (!finitef(a) || !finitef(b)) {
2076 a = finitef(a) ? 0 : copysignf(1.0, a);
2077 b = finitef(b) ? 0 : copysignf(1.0, b);
2090 s4 builtin_fcmpg(float a, float b)
2092 if (isnanf(a)) return 1;
2093 if (isnanf(b)) return 1;
2094 if (!finitef(a) || !finitef(b)) {
2095 a = finitef(a) ? 0 : copysignf(1.0, a);
2096 b = finitef(b) ? 0 : copysignf(1.0, b);
2098 if (a > b) return 1;
2099 if (a == b) return 0;
2102 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2105 float builtin_frem(float a, float b)
2111 /* functions for unsupported double instructions ******************************/
2114 double builtin_dadd(double a, double b)
2116 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2117 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2119 if (finite(b)) return a + b;
2123 if (finite(b)) return a;
2125 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2126 else return longBitsToDouble(DBL_NAN);
2132 double builtin_dsub(double a, double b)
2134 return builtin_dadd(a, builtin_dneg(b));
2138 double builtin_dmul(double a, double b)
2140 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2141 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2143 if (finite(b)) return a * b;
2145 if (a == 0) return longBitsToDouble(DBL_NAN);
2146 else return copysign(b, copysign(1.0, b) * a);
2151 if (b == 0) return longBitsToDouble(DBL_NAN);
2152 else return copysign(a, copysign(1.0, a) * b);
2155 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2161 /* builtin_ddiv ****************************************************************
2163 Implementation as described in VM Spec.
2165 *******************************************************************************/
2167 double builtin_ddiv(double a, double b)
2171 /* If neither value1' nor value2' is NaN, the sign of the result */
2172 /* is positive if both values have the same sign, negative if the */
2173 /* values have different signs. */
2179 /* If either value1' or value2' is NaN, the result is NaN. */
2181 return longBitsToDouble(DBL_NAN);
2184 /* Division of a finite value by an infinity results in a */
2185 /* signed zero, with the sign-producing rule just given. */
2187 /* is sign equal? */
2189 if (copysign(1.0, a) == copysign(1.0, b))
2198 /* If either value1' or value2' is NaN, the result is NaN. */
2200 return longBitsToDouble(DBL_NAN);
2202 } else if (finite(b)) {
2203 /* Division of an infinity by a finite value results in a signed */
2204 /* infinity, with the sign-producing rule just given. */
2206 /* is sign equal? */
2208 if (copysign(1.0, a) == copysign(1.0, b))
2209 return longBitsToDouble(DBL_POSINF);
2211 return longBitsToDouble(DBL_NEGINF);
2214 /* Division of an infinity by an infinity results in NaN. */
2216 return longBitsToDouble(DBL_NAN);
2222 /* builtin_dneg ****************************************************************
2224 Implemented as described in VM Spec.
2226 *******************************************************************************/
2228 double builtin_dneg(double a)
2231 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2238 /* If the operand is a zero, the result is the zero of opposite */
2244 /* If the operand is an infinity, the result is the infinity of */
2245 /* opposite sign. */
2247 return copysign(a, -copysign(1.0, a));
2251 #endif /* !SUPPORT_DOUBLE */
2254 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2255 s4 builtin_dcmpl(double a, double b)
2263 if (!finite(a) || !finite(b)) {
2264 a = finite(a) ? 0 : copysign(1.0, a);
2265 b = finite(b) ? 0 : copysign(1.0, b);
2278 s4 builtin_dcmpg(double a, double b)
2286 if (!finite(a) || !finite(b)) {
2287 a = finite(a) ? 0 : copysign(1.0, a);
2288 b = finite(b) ? 0 : copysign(1.0, b);
2299 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2302 double builtin_drem(double a, double b)
2308 /* conversion operations ******************************************************/
2311 s8 builtin_i2l(s4 i)
2323 s4 builtin_l2i(s8 l)
2334 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2335 float builtin_i2f(s4 a)
2337 float f = (float) a;
2340 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2343 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2344 double builtin_i2d(s4 a)
2346 double d = (double) a;
2349 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2352 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2353 float builtin_l2f(s8 a)
2356 float f = (float) a;
2362 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2365 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2366 double builtin_l2d(s8 a)
2369 double d = (double) a;
2375 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2378 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2379 s4 builtin_f2i(float a)
2383 i = builtin_d2i((double) a);
2394 if (a < (-2147483648))
2395 return (-2147483648);
2398 f = copysignf((float) 1.0, a);
2401 return (-2147483648); */
2403 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2406 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2407 s8 builtin_f2l(float a)
2411 l = builtin_d2l((double) a);
2418 if (a > 9223372036854775807L)
2419 return 9223372036854775807L;
2420 if (a < (-9223372036854775808L))
2421 return (-9223372036854775808L);
2426 f = copysignf((float) 1.0, a);
2428 return 9223372036854775807L;
2429 return (-9223372036854775808L); */
2431 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2434 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2435 s4 builtin_d2i(double a)
2440 if (a >= 2147483647)
2442 if (a <= (-2147483647-1))
2443 return (-2147483647-1);
2448 d = copysign(1.0, a);
2451 return (-2147483647-1);
2453 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2456 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2457 s8 builtin_d2l(double a)
2462 if (a >= 9223372036854775807LL)
2463 return 9223372036854775807LL;
2464 if (a <= (-9223372036854775807LL-1))
2465 return (-9223372036854775807LL-1);
2470 d = copysign(1.0, a);
2472 return 9223372036854775807LL;
2473 return (-9223372036854775807LL-1);
2475 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2478 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2479 double builtin_f2d(float a)
2481 if (finitef(a)) return (double) a;
2484 return longBitsToDouble(DBL_NAN);
2486 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2490 float builtin_d2f(double a)
2496 return intBitsToFloat(FLT_NAN);
2498 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2501 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2504 /* builtin_arraycopy ***********************************************************
2506 Builtin for java.lang.System.arraycopy.
2508 ATTENTION: This builtin function returns a boolean value to signal
2509 the ICMD_BUILTIN if there was an exception.
2511 *******************************************************************************/
2513 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2514 java_arrayheader *dest, s4 destStart, s4 len)
2516 arraydescriptor *sdesc;
2517 arraydescriptor *ddesc;
2520 if ((src == NULL) || (dest == NULL)) {
2521 exceptions_throw_nullpointerexception();
2525 sdesc = src->objheader.vftbl->arraydesc;
2526 ddesc = dest->objheader.vftbl->arraydesc;
2528 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2529 exceptions_throw_arraystoreexception();
2533 /* we try to throw exception with the same message as SUN does */
2535 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2536 (srcStart + len < 0) || (srcStart + len > src->size) ||
2537 (destStart + len < 0) || (destStart + len > dest->size)) {
2538 exceptions_throw_arrayindexoutofboundsexception();
2542 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2543 /* We copy primitive values or references of exactly the same type */
2545 s4 dataoffset = sdesc->dataoffset;
2546 s4 componentsize = sdesc->componentsize;
2548 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2549 ((u1 *) src) + dataoffset + componentsize * srcStart,
2550 (size_t) len * componentsize);
2553 /* We copy references of different type */
2555 java_objectarray *oas = (java_objectarray *) src;
2556 java_objectarray *oad = (java_objectarray *) dest;
2558 if (destStart <= srcStart) {
2559 for (i = 0; i < len; i++) {
2560 java_objectheader *o = oas->data[srcStart + i];
2562 if (!builtin_canstore(oad, o))
2565 oad->data[destStart + i] = o;
2569 /* XXX this does not completely obey the specification!
2570 If an exception is thrown only the elements above the
2571 current index have been copied. The specification
2572 requires that only the elements *below* the current
2573 index have been copied before the throw. */
2575 for (i = len - 1; i >= 0; i--) {
2576 java_objectheader *o = oas->data[srcStart + i];
2578 if (!builtin_canstore(oad, o))
2581 oad->data[destStart + i] = o;
2590 /* builtin_currenttimemillis ***************************************************
2592 Return the current time in milliseconds.
2594 *******************************************************************************/
2596 s8 builtin_currenttimemillis(void)
2601 if (gettimeofday(&tv, NULL) == -1)
2602 vm_abort("gettimeofday failed: %s", strerror(errno));
2604 result = (s8) tv.tv_sec;
2606 result += (tv.tv_usec / 1000);
2612 /* builtin_clone ***************************************************************
2614 Function for cloning objects or arrays.
2616 *******************************************************************************/
2618 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2620 arraydescriptor *ad;
2621 java_arrayheader *ah;
2624 java_objectheader *co; /* cloned object header */
2626 /* get the array descriptor */
2628 ad = o->vftbl->arraydesc;
2630 /* we are cloning an array */
2633 ah = (java_arrayheader *) o;
2635 size = ad->dataoffset + ad->componentsize * ah->size;
2637 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2642 MCOPY(co, o, u1, size);
2644 #if defined(ENABLE_GC_CACAO)
2645 heap_init_objectheader(co, size);
2648 #if defined(ENABLE_THREADS)
2649 lock_init_object_lock(co);
2655 /* we are cloning a non-array */
2657 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2658 exceptions_throw_clonenotsupportedexception();
2662 /* get the class of the object */
2664 c = o->vftbl->class;
2666 /* create new object */
2668 co = builtin_new(c);
2673 MCOPY(co, o, u1, c->instancesize);
2675 #if defined(ENABLE_GC_CACAO)
2676 heap_init_objectheader(co, c->instancesize);
2679 #if defined(ENABLE_THREADS)
2680 lock_init_object_lock(co);
2688 * These are local overrides for various environment variables in Emacs.
2689 * Please do not remove this and leave it at the end of the file, where
2690 * Emacs will automagically detect them.
2691 * ---------------------------------------------------------------------
2694 * indent-tabs-mode: t
2698 * vim:noexpandtab:sw=4:ts=4: