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 7966 2007-05-25 12:41:03Z pm $
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 #include "threads/lock-common.h"
64 #include "toolbox/logging.h"
65 #include "toolbox/util.h"
67 #include "vm/builtin.h"
68 #include "vm/cycles-stats.h"
69 #include "vm/exceptions.h"
70 #include "vm/global.h"
71 #include "vm/initialize.h"
72 #include "vm/stringlocal.h"
74 #include "vm/jit/asmpart.h"
75 #include "vm/jit/patcher.h"
77 #include "vmcore/class.h"
78 #include "vmcore/loader.h"
79 #include "vmcore/options.h"
80 #include "vmcore/rt-timing.h"
82 #if defined(ENABLE_VMLOG)
83 #include <vmlog_cacao.h>
86 #if defined(ENABLE_DEBUG_FILTER)
87 # include "vm/jit/show.h"
90 /* include builtin tables *****************************************************/
92 #include "vm/builtintable.inc"
95 CYCLES_STATS_DECLARE(builtin_new ,100,5)
96 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
98 /* builtintable_init ***********************************************************
100 Parse the descriptors of builtin functions and create the parsed
103 *******************************************************************************/
105 static bool builtintable_init(void)
107 descriptor_pool *descpool;
109 builtintable_entry *bte;
111 /* mark start of dump memory area */
113 dumpsize = dump_size();
115 /* create a new descriptor pool */
117 descpool = descriptor_pool_new(class_java_lang_Object);
119 /* add some entries we need */
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
124 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
127 /* first add all descriptors to the pool */
129 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
130 /* create a utf8 string from descriptor */
132 bte->descriptor = utf_new_char(bte->cdescriptor);
134 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
135 /* release dump area */
137 dump_release(dumpsize);
143 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
144 bte->descriptor = utf_new_char(bte->cdescriptor);
146 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
147 dump_release(dumpsize);
152 for (bte = builtintable_function; bte->fp != NULL; bte++) {
153 bte->classname = utf_new_char(bte->cclassname);
154 bte->name = utf_new_char(bte->cname);
155 bte->descriptor = utf_new_char(bte->cdescriptor);
157 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
158 dump_release(dumpsize);
163 /* create the class reference table */
165 (void) descriptor_pool_create_classrefs(descpool, NULL);
167 /* allocate space for the parsed descriptors */
169 descriptor_pool_alloc_parsed_descriptors(descpool);
171 /* now parse all descriptors */
173 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
174 /* parse the descriptor, builtin is always static (no `this' pointer) */
176 bte->md = descriptor_pool_parse_method_descriptor(descpool,
181 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
182 bte->md = descriptor_pool_parse_method_descriptor(descpool,
187 for (bte = builtintable_function; bte->fp != NULL; bte++) {
188 bte->md = descriptor_pool_parse_method_descriptor(descpool,
193 /* release dump area */
195 dump_release(dumpsize);
201 /* builtintable_comparator *****************************************************
203 qsort comparator for the automatic builtin table.
205 *******************************************************************************/
207 static int builtintable_comparator(const void *a, const void *b)
209 builtintable_entry *bte1;
210 builtintable_entry *bte2;
212 bte1 = (builtintable_entry *) a;
213 bte2 = (builtintable_entry *) b;
215 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
219 /* builtintable_sort_automatic *************************************************
221 Sorts the automatic builtin table.
223 *******************************************************************************/
225 static void builtintable_sort_automatic(void)
229 /* calculate table size statically (`- 1' comment see builtintable.inc) */
231 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
233 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
234 builtintable_comparator);
238 /* builtin_init ****************************************************************
240 Initialize the global table of builtin functions.
242 *******************************************************************************/
244 bool builtin_init(void)
246 /* initialize the builtin tables */
248 if (!builtintable_init())
251 /* sort builtin tables */
253 builtintable_sort_automatic();
259 /* builtintable_get_internal ***************************************************
261 Finds an entry in the builtintable for internal functions and
262 returns the a pointer to the structure.
264 *******************************************************************************/
266 builtintable_entry *builtintable_get_internal(functionptr fp)
268 builtintable_entry *bte;
270 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
279 /* builtintable_get_automatic **************************************************
281 Finds an entry in the builtintable for functions which are replaced
282 automatically and returns the a pointer to the structure.
284 *******************************************************************************/
286 builtintable_entry *builtintable_get_automatic(s4 opcode)
288 builtintable_entry *first;
289 builtintable_entry *last;
290 builtintable_entry *middle;
294 /* calculate table size statically (`- 1' comment see builtintable.inc) */
296 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
298 first = builtintable_automatic;
299 last = builtintable_automatic + entries;
301 while (entries > 0) {
303 middle = first + half;
305 if (middle->opcode < opcode) {
312 return (first != last ? first : NULL);
316 /* builtintable_replace_function ***********************************************
320 *******************************************************************************/
322 #if defined(ENABLE_JIT)
323 bool builtintable_replace_function(void *iptr_)
326 builtintable_entry *bte;
329 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
331 /* get name and descriptor of the function */
334 case ICMD_INVOKESTATIC:
335 /* The instruction MUST be resolved, otherwise we run into
336 lazy loading troubles. Anyway, we should/can only replace
337 very VM-close functions. */
339 if (INSTRUCTION_IS_UNRESOLVED(iptr))
342 mr = iptr->sx.s23.s3.fmiref;
349 /* search the function table */
351 for (bte = builtintable_function; bte->fp != NULL; bte++) {
352 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
353 (mr->name == bte->name) &&
354 (mr->descriptor == bte->descriptor)) {
356 /* set the values in the instruction */
358 iptr->opc = bte->opcode;
359 iptr->sx.s23.s3.bte = bte;
360 if (bte->checkexception)
361 iptr->flags.bits |= INS_FLAG_CHECK;
363 iptr->flags.bits &= ~INS_FLAG_CHECK;
371 #endif /* defined(ENABLE_JIT) */
374 /*****************************************************************************
376 *****************************************************************************/
378 /* builtin_instanceof **********************************************************
380 Checks if an object is an instance of some given class (or subclass
381 of that class). If class is an interface, checks if the interface
384 Return value: 1 ... o is an instance of class or implements the interface
385 0 ... otherwise or if o == NULL
387 *******************************************************************************/
389 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
394 return class_isanysubclass(o->vftbl->class, class);
399 /* builtin_checkcast ***********************************************************
401 The same as builtin_instanceof except that 1 is returned when o ==
404 *******************************************************************************/
406 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
411 if (class_isanysubclass(o->vftbl->class, class))
418 /* builtin_descriptorscompatible ***********************************************
420 Checks if two array type descriptors are assignment compatible
422 Return value: 1 ... target = desc is possible
425 *******************************************************************************/
427 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
428 arraydescriptor *target)
433 if (desc->arraytype != target->arraytype)
436 if (desc->arraytype != ARRAYTYPE_OBJECT)
439 /* {both arrays are arrays of references} */
441 if (desc->dimension == target->dimension) {
442 /* an array which contains elements of interface types is
443 allowed to be casted to Object (JOWENN)*/
445 if ((desc->elementvftbl->baseval < 0) &&
446 (target->elementvftbl->baseval == 1))
449 return class_isanysubclass(desc->elementvftbl->class,
450 target->elementvftbl->class);
453 if (desc->dimension < target->dimension)
456 /* {desc has higher dimension than target} */
458 return class_isanysubclass(pseudo_class_Arraystub,
459 target->elementvftbl->class);
463 /* builtin_arraycheckcast ******************************************************
465 Checks if an object is really a subtype of the requested array
466 type. The object has to be an array to begin with. For simple
467 arrays (int, short, double, etc.) the types have to match exactly.
468 For arrays of objects, the type of elements in the array has to be
469 a subtype (or the same type) of the requested element type. For
470 arrays of arrays (which in turn can again be arrays of arrays), the
471 types at the lowest level have to satisfy the corresponding sub
474 *******************************************************************************/
476 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
478 arraydescriptor *desc;
483 desc = o->vftbl->arraydesc;
488 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
492 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
497 return builtin_arraycheckcast(o, targetclass);
501 /* builtin_throw_exception *****************************************************
503 Sets the exceptionptr with the thrown exception and prints some
504 debugging information. Called from asm_vm_call_method.
506 *******************************************************************************/
508 void *builtin_throw_exception(java_objectheader *xptr)
511 java_lang_Throwable *t;
517 t = (java_lang_Throwable *) xptr;
519 /* calculate message length */
521 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
525 utf_bytes(xptr->vftbl->class->name);
526 if (t->detailMessage) {
527 logtextlen += strlen(": ") +
528 u2_utflength(t->detailMessage->value->data
529 + t->detailMessage->offset,
530 t->detailMessage->count);
534 logtextlen += strlen("(nil)");
537 /* allocate memory */
539 dumpsize = dump_size();
541 logtext = DMNEW(char, logtextlen);
543 strcpy(logtext, "Builtin exception thrown: ");
546 utf_cat_classname(logtext, xptr->vftbl->class->name);
548 if (t->detailMessage) {
551 buf = javastring_tochar((java_objectheader *) t->detailMessage);
552 strcat(logtext, ": ");
553 strcat(logtext, buf);
554 MFREE(buf, char, strlen(buf) + 1);
558 strcat(logtext, "(nil)");
565 dump_release(dumpsize);
567 #endif /* !defined(NDEBUG) */
569 /* actually set the exception */
571 exceptions_set_exception(xptr);
573 /* Return a NULL pointer. This is required for vm_call_method to
574 check for an exception. This is for convenience. */
580 /* builtin_canstore ************************************************************
582 Checks, if an object can be stored in an array.
584 Return value: 1 ... possible
585 0 ... otherwise (throws an ArrayStoreException)
587 *******************************************************************************/
589 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
591 arraydescriptor *desc;
592 arraydescriptor *valuedesc;
593 vftbl_t *componentvftbl;
596 castinfo classvalues;
602 /* The following is guaranteed (by verifier checks):
604 * *) oa->...vftbl->arraydesc != NULL
605 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
606 * *) o->vftbl is not an interface vftbl
609 desc = oa->header.objheader.vftbl->arraydesc;
610 componentvftbl = desc->componentvftbl;
611 valuevftbl = o->vftbl;
612 valuedesc = valuevftbl->arraydesc;
614 if ((desc->dimension - 1) == 0) {
615 /* {oa is a one-dimensional array} */
616 /* {oa is an array of references} */
618 if (valuevftbl == componentvftbl)
621 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
623 base = classvalues.super_baseval;
626 /* an array of interface references */
628 result = ((valuevftbl->interfacetablelength > -base) &&
629 (valuevftbl->interfacetable[base] != NULL));
632 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
633 <= (unsigned) classvalues.super_diffval);
636 else if (valuedesc == NULL) {
637 /* {oa has dimension > 1} */
638 /* {componentvftbl->arraydesc != NULL} */
640 /* check if o is an array */
645 /* {o is an array} */
647 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
650 /* if not possible, throw an exception */
653 exceptions_throw_arraystoreexception();
661 /* This is an optimized version where a is guaranteed to be one-dimensional */
662 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
664 arraydescriptor *desc;
665 vftbl_t *elementvftbl;
669 castinfo classvalues;
673 /* The following is guaranteed (by verifier checks):
675 * *) a->...vftbl->arraydesc != NULL
676 * *) a->...vftbl->arraydesc->elementvftbl != NULL
677 * *) a->...vftbl->arraydesc->dimension == 1
678 * *) o->vftbl is not an interface vftbl
681 desc = a->header.objheader.vftbl->arraydesc;
682 elementvftbl = desc->elementvftbl;
683 valuevftbl = o->vftbl;
685 /* {a is a one-dimensional array} */
687 if (valuevftbl == elementvftbl)
690 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
692 if ((base = classvalues.super_baseval) <= 0)
693 /* an array of interface references */
694 return (valuevftbl->interfacetablelength > -base &&
695 valuevftbl->interfacetable[base] != NULL);
697 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
698 <= (unsigned) classvalues.super_diffval;
704 /* This is an optimized version where a is guaranteed to be a
705 * one-dimensional array of a class type */
706 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
708 vftbl_t *elementvftbl;
711 castinfo classvalues;
715 /* The following is guaranteed (by verifier checks):
717 * *) a->...vftbl->arraydesc != NULL
718 * *) a->...vftbl->arraydesc->elementvftbl != NULL
719 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
720 * *) a->...vftbl->arraydesc->dimension == 1
721 * *) o->vftbl is not an interface vftbl
724 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
725 valuevftbl = o->vftbl;
727 /* {a is a one-dimensional array} */
729 if (valuevftbl == elementvftbl)
732 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
734 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
735 <= (unsigned) classvalues.super_diffval;
741 /* builtin_new *****************************************************************
743 Creates a new instance of class c on the heap.
745 Return value: pointer to the object or NULL if no memory is
748 *******************************************************************************/
750 java_objectheader *builtin_new(classinfo *c)
752 java_objectheader *o;
753 #if defined(ENABLE_RT_TIMING)
754 struct timespec time_start, time_end;
756 #if defined(ENABLE_CYCLES_STATS)
757 u8 cycles_start, cycles_end;
760 RT_TIMING_GET_TIME(time_start);
761 CYCLES_STATS_GET(cycles_start);
763 /* is the class loaded */
765 assert(c->state & CLASS_LOADED);
767 /* check if we can instantiate this class */
769 if (c->flags & ACC_ABSTRACT) {
770 exceptions_throw_instantiationerror(c);
774 /* is the class linked */
776 if (!(c->state & CLASS_LINKED))
780 if (!(c->state & CLASS_INITIALIZED)) {
783 log_message_class("Initialize class (from builtin_new): ", c);
786 if (!initialize_class(c))
790 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
798 #if defined(ENABLE_THREADS)
799 lock_init_object_lock(o);
802 CYCLES_STATS_GET(cycles_end);
803 RT_TIMING_GET_TIME(time_end);
805 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
806 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
812 /* builtin_newarray ************************************************************
814 Creates an array with the given vftbl on the heap. This function
815 takes as class argument an array class.
817 Return value: pointer to the array or NULL if no memory is available
819 *******************************************************************************/
821 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
823 arraydescriptor *desc;
828 #if defined(ENABLE_RT_TIMING)
829 struct timespec time_start, time_end;
832 RT_TIMING_GET_TIME(time_start);
834 desc = arrayclass->vftbl->arraydesc;
835 dataoffset = desc->dataoffset;
836 componentsize = desc->componentsize;
839 exceptions_throw_negativearraysizeexception();
843 actualsize = dataoffset + size * componentsize;
845 /* check for overflow */
847 if (((u4) actualsize) < ((u4) size)) {
848 exceptions_throw_outofmemoryerror();
852 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
857 a->objheader.vftbl = arrayclass->vftbl;
859 #if defined(ENABLE_THREADS)
860 lock_init_object_lock(&a->objheader);
865 RT_TIMING_GET_TIME(time_end);
866 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
872 /* builtin_anewarray ***********************************************************
874 Creates an array of references to the given class type on the heap.
876 Return value: pointer to the array or NULL if no memory is
879 *******************************************************************************/
881 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
883 classinfo *arrayclass;
885 /* is class loaded */
887 assert(componentclass->state & CLASS_LOADED);
889 /* is class linked */
891 if (!(componentclass->state & CLASS_LINKED))
892 if (!link_class(componentclass))
895 arrayclass = class_array_of(componentclass, true);
900 return (java_objectarray *) builtin_newarray(size, arrayclass);
904 /* builtin_newarray_boolean ****************************************************
906 Creates an array of bytes on the heap. The array is designated as
907 an array of booleans (important for casts)
909 Return value: pointer to the array or NULL if no memory is
912 *******************************************************************************/
914 java_booleanarray *builtin_newarray_boolean(s4 size)
916 return (java_booleanarray *)
917 builtin_newarray(size,
918 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
922 /* builtin_newarray_byte *******************************************************
924 Creates an array of 8 bit Integers on the heap.
926 Return value: pointer to the array or NULL if no memory is
929 *******************************************************************************/
931 java_bytearray *builtin_newarray_byte(s4 size)
933 return (java_bytearray *)
934 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
938 /* builtin_newarray_char *******************************************************
940 Creates an array of characters on the heap.
942 Return value: pointer to the array or NULL if no memory is
945 *******************************************************************************/
947 java_chararray *builtin_newarray_char(s4 size)
949 return (java_chararray *)
950 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
954 /* builtin_newarray_short ******************************************************
956 Creates an array of 16 bit Integers on the heap.
958 Return value: pointer to the array or NULL if no memory is
961 *******************************************************************************/
963 java_shortarray *builtin_newarray_short(s4 size)
965 return (java_shortarray *)
966 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
970 /* builtin_newarray_int ********************************************************
972 Creates an array of 32 bit Integers on the heap.
974 Return value: pointer to the array or NULL if no memory is
977 *******************************************************************************/
979 java_intarray *builtin_newarray_int(s4 size)
981 return (java_intarray *)
982 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
986 /* builtin_newarray_long *******************************************************
988 Creates an array of 64 bit Integers on the heap.
990 Return value: pointer to the array or NULL if no memory is
993 *******************************************************************************/
995 java_longarray *builtin_newarray_long(s4 size)
997 return (java_longarray *)
998 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1002 /* builtin_newarray_float ******************************************************
1004 Creates an array of 32 bit IEEE floats on the heap.
1006 Return value: pointer to the array or NULL if no memory is
1009 *******************************************************************************/
1011 java_floatarray *builtin_newarray_float(s4 size)
1013 return (java_floatarray *)
1014 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1018 /* builtin_newarray_double *****************************************************
1020 Creates an array of 64 bit IEEE floats on the heap.
1022 Return value: pointer to the array or NULL if no memory is
1025 *******************************************************************************/
1027 java_doublearray *builtin_newarray_double(s4 size)
1029 return (java_doublearray *)
1030 builtin_newarray(size,
1031 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1035 /* builtin_multianewarray_intern ***********************************************
1037 Creates a multi-dimensional array on the heap. The dimensions are
1038 passed in an array of longs.
1041 n............number of dimensions to create
1042 arrayvftbl...vftbl of the array class
1043 dims.........array containing the size of each dimension to create
1045 Return value: pointer to the array or NULL if no memory is
1048 ******************************************************************************/
1050 static java_arrayheader *builtin_multianewarray_intern(int n,
1051 classinfo *arrayclass,
1055 java_arrayheader *a;
1056 classinfo *componentclass;
1059 /* create this dimension */
1061 size = (s4) dims[0];
1062 a = builtin_newarray(size, arrayclass);
1067 /* if this is the last dimension return */
1072 /* get the class of the components to create */
1074 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1076 /* The verifier guarantees that the dimension count is in the range. */
1078 /* create the component arrays */
1080 for (i = 0; i < size; i++) {
1081 java_arrayheader *ea =
1082 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1083 /* we save an s4 to a s8 slot, 8-byte aligned */
1085 builtin_multianewarray_intern(n, componentclass, dims + 2);
1087 builtin_multianewarray_intern(n, componentclass, dims + 1);
1093 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1100 /* builtin_multianewarray ******************************************************
1102 Wrapper for builtin_multianewarray_intern which checks all
1103 dimensions before we start allocating.
1105 ******************************************************************************/
1107 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1113 /* check all dimensions before doing anything */
1115 for (i = 0; i < n; i++) {
1116 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1117 /* we save an s4 to a s8 slot, 8-byte aligned */
1118 size = (s4) dims[i * 2];
1120 size = (s4) dims[i];
1124 exceptions_throw_negativearraysizeexception();
1129 /* now call the real function */
1131 return builtin_multianewarray_intern(n, arrayclass, dims);
1135 /*****************************************************************************
1138 Various functions for printing a message at method entry or exit (for
1141 *****************************************************************************/
1143 #if !defined(NDEBUG)
1144 static s4 methodindent = 0;
1145 static u4 callcount = 0;
1147 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1157 #if defined(ENABLE_DEBUG_FILTER)
1158 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1161 #if defined(ENABLE_VMLOG)
1165 if (opt_verbosecall && indent)
1168 /* calculate message length */
1172 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1175 logtextlen = strlen("Some Throwable");
1178 logtextlen += strlen(" thrown in ");
1182 utf_bytes(m->class->name) +
1184 utf_bytes(m->name) +
1185 utf_bytes(m->descriptor) +
1186 strlen("(NOSYNC,NATIVE");
1188 #if SIZEOF_VOID_P == 8
1190 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1192 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1195 if (m->class->sourcefile == NULL)
1196 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1198 logtextlen += utf_bytes(m->class->sourcefile);
1200 logtextlen += strlen(":65536)");
1204 logtextlen += strlen("call_java_method");
1207 logtextlen += strlen("0");
1209 /* allocate memory */
1211 dumpsize = dump_size();
1213 logtext = DMNEW(char, logtextlen);
1216 strcpy(logtext, "Exception ");
1217 utf_cat_classname(logtext, xptr->vftbl->class->name);
1220 strcpy(logtext, "Some Throwable");
1223 strcat(logtext, " thrown in ");
1226 utf_cat_classname(logtext, m->class->name);
1227 strcat(logtext, ".");
1228 utf_cat(logtext, m->name);
1229 utf_cat(logtext, m->descriptor);
1231 if (m->flags & ACC_SYNCHRONIZED)
1232 strcat(logtext, "(SYNC");
1234 strcat(logtext, "(NOSYNC");
1236 if (m->flags & ACC_NATIVE) {
1237 strcat(logtext, ",NATIVE");
1241 #if SIZEOF_VOID_P == 8
1242 sprintf(logtext + strlen(logtext),
1243 ")(0x%016lx) at position 0x%016lx",
1244 (ptrint) code->entrypoint, (ptrint) pos);
1246 sprintf(logtext + strlen(logtext),
1247 ")(0x%08x) at position 0x%08x",
1248 (ptrint) code->entrypoint, (ptrint) pos);
1253 /* XXX preliminary: This should get the actual codeinfo */
1254 /* in which the exception happened. */
1257 #if SIZEOF_VOID_P == 8
1258 sprintf(logtext + strlen(logtext),
1259 ")(0x%016lx) at position 0x%016lx (",
1260 (ptrint) code->entrypoint, (ptrint) pos);
1262 sprintf(logtext + strlen(logtext),
1263 ")(0x%08x) at position 0x%08x (",
1264 (ptrint) code->entrypoint, (ptrint) pos);
1267 if (m->class->sourcefile == NULL)
1268 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1270 utf_cat(logtext, m->class->sourcefile);
1272 sprintf(logtext + strlen(logtext), ":%d)", 0);
1276 strcat(logtext, "call_java_method");
1280 /* release memory */
1282 dump_release(dumpsize);
1286 #endif /* !defined(NDEBUG) */
1289 /* builtin_print_argument ******************************************************
1291 Prints arguments and return values for the call trace.
1293 *******************************************************************************/
1295 #if !defined(NDEBUG)
1296 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1297 typedesc *paramtype, s8 value)
1300 java_objectheader *o;
1305 switch (paramtype->type) {
1308 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1313 #if SIZEOF_VOID_P == 4
1314 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1316 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1322 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1327 #if SIZEOF_VOID_P == 4
1328 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1330 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1335 #if SIZEOF_VOID_P == 4
1336 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1338 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1341 /* cast to java.lang.Object */
1343 o = (java_objectheader *) (ptrint) value;
1345 /* check return argument for java.lang.Class or java.lang.String */
1348 if (o->vftbl->class == class_java_lang_String) {
1349 /* get java.lang.String object and the length of the
1352 u = javastring_toutf(o, false);
1354 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1356 /* realloc memory for string length */
1358 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1361 /* convert to utf8 string and strcat it to the logtext */
1363 strcat(logtext, " (String = \"");
1364 utf_cat(logtext, u);
1365 strcat(logtext, "\")");
1368 if (o->vftbl->class == class_java_lang_Class) {
1369 /* if the object returned is a java.lang.Class
1370 cast it to classinfo structure and get the name
1373 c = (classinfo *) o;
1378 /* if the object returned is not a java.lang.String or
1379 a java.lang.Class just print the name of the class */
1381 u = o->vftbl->class->name;
1384 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1386 /* realloc memory for string length */
1388 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1391 /* strcat to the logtext */
1393 strcat(logtext, " (Class = \"");
1394 utf_cat_classname(logtext, u);
1395 strcat(logtext, "\")");
1402 #endif /* !defined(NDEBUG) */
1404 /* builtin_verbosecall_enter ***************************************************
1406 Print method call with arguments for -verbose:call.
1408 *******************************************************************************/
1410 #if !defined(NDEBUG)
1412 #ifdef TRACE_ARGS_NUM
1413 void builtin_verbosecall_enter(s8 a0, s8 a1,
1414 # if TRACE_ARGS_NUM >= 4
1417 # if TRACE_ARGS_NUM >= 6
1420 # if TRACE_ARGS_NUM == 8
1432 #if defined(ENABLE_DEBUG_FILTER)
1433 if (! show_filters_test_verbosecall_enter(m)) return;
1436 #if defined(ENABLE_VMLOG)
1437 vmlog_cacao_enter_method(m);
1443 /* calculate message length */
1446 strlen("4294967295 ") +
1447 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1449 strlen("called: ") +
1450 utf_bytes(m->class->name) +
1452 utf_bytes(m->name) +
1453 utf_bytes(m->descriptor);
1455 /* Actually it's not possible to have all flags printed, but:
1460 strlen(" PRIVATE") +
1461 strlen(" PROTECTED") +
1464 strlen(" SYNCHRONIZED") +
1465 strlen(" VOLATILE") +
1466 strlen(" TRANSIENT") +
1468 strlen(" INTERFACE") +
1469 strlen(" ABSTRACT");
1471 /* add maximal argument length */
1475 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1476 strlen("...(255)") +
1479 /* allocate memory */
1481 dumpsize = dump_size();
1483 logtext = DMNEW(char, logtextlen);
1487 sprintf(logtext, "%10d ", callcount);
1488 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1490 pos = strlen(logtext);
1492 for (i = 0; i < methodindent; i++)
1493 logtext[pos++] = '\t';
1495 strcpy(logtext + pos, "called: ");
1497 utf_cat_classname(logtext, m->class->name);
1498 strcat(logtext, ".");
1499 utf_cat(logtext, m->name);
1500 utf_cat(logtext, m->descriptor);
1502 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1503 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1504 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1505 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1506 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1507 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1508 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1509 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1510 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1511 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1512 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1514 strcat(logtext, "(");
1516 if (md->paramcount >= 1) {
1517 logtext = builtin_print_argument(logtext, &logtextlen,
1518 &md->paramtypes[0], a0);
1521 if (md->paramcount >= 2) {
1522 strcat(logtext, ", ");
1524 logtext = builtin_print_argument(logtext, &logtextlen,
1525 &md->paramtypes[1], a1);
1528 #if TRACE_ARGS_NUM >= 4
1529 if (md->paramcount >= 3) {
1530 strcat(logtext, ", ");
1532 logtext = builtin_print_argument(logtext, &logtextlen,
1533 &md->paramtypes[2], a2);
1536 if (md->paramcount >= 4) {
1537 strcat(logtext, ", ");
1539 logtext = builtin_print_argument(logtext, &logtextlen,
1540 &md->paramtypes[3], a3);
1544 #if TRACE_ARGS_NUM >= 6
1545 if (md->paramcount >= 5) {
1546 strcat(logtext, ", ");
1548 logtext = builtin_print_argument(logtext, &logtextlen,
1549 &md->paramtypes[4], a4);
1552 if (md->paramcount >= 6) {
1553 strcat(logtext, ", ");
1555 logtext = builtin_print_argument(logtext, &logtextlen,
1556 &md->paramtypes[5], a5);
1560 #if TRACE_ARGS_NUM == 8
1561 if (md->paramcount >= 7) {
1562 strcat(logtext, ", ");
1564 logtext = builtin_print_argument(logtext, &logtextlen,
1565 &md->paramtypes[6], a6);
1568 if (md->paramcount >= 8) {
1569 strcat(logtext, ", ");
1571 logtext = builtin_print_argument(logtext, &logtextlen,
1572 &md->paramtypes[7], a7);
1576 if (md->paramcount > 8) {
1577 sprintf(logtext + strlen(logtext), ", ...(%d)",
1578 md->paramcount - TRACE_ARGS_NUM);
1581 strcat(logtext, ")");
1585 /* release memory */
1587 dump_release(dumpsize);
1593 #endif /* !defined(NDEBUG) */
1596 /* builtin_verbosecall_exit ****************************************************
1598 Print method exit for -verbose:call.
1600 *******************************************************************************/
1602 #if !defined(NDEBUG)
1603 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1613 #if defined(ENABLE_DEBUG_FILTER)
1614 if (! show_filters_test_verbosecall_exit(m)) return;
1617 #if defined(ENABLE_VMLOG)
1618 vmlog_cacao_leave_method(m);
1624 /* calculate message length */
1627 strlen("4294967295 ") +
1628 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1630 strlen("finished: ") +
1631 utf_bytes(m->class->name) +
1633 utf_bytes(m->name) +
1634 utf_bytes(m->descriptor) +
1635 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1637 /* add maximal argument length */
1639 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1641 /* allocate memory */
1643 dumpsize = dump_size();
1645 logtext = DMNEW(char, logtextlen);
1647 /* outdent the log message */
1652 log_text("WARNING: unmatched methodindent--");
1654 /* generate the message */
1656 sprintf(logtext, " ");
1657 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1659 pos = strlen(logtext);
1661 for (i = 0; i < methodindent; i++)
1662 logtext[pos++] = '\t';
1664 strcpy(logtext + pos, "finished: ");
1665 utf_cat_classname(logtext, m->class->name);
1666 strcat(logtext, ".");
1667 utf_cat(logtext, m->name);
1668 utf_cat(logtext, m->descriptor);
1670 if (!IS_VOID_TYPE(md->returntype.type)) {
1671 strcat(logtext, "->");
1673 switch (md->returntype.type) {
1690 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1695 /* release memory */
1697 dump_release(dumpsize);
1700 #endif /* !defined(NDEBUG) */
1703 #if defined(ENABLE_CYCLES_STATS)
1704 void builtin_print_cycles_stats(FILE *file)
1706 fprintf(file,"builtin cylce count statistics:\n");
1708 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1709 CYCLES_STATS_PRINT(builtin_new ,file);
1713 #endif /* defined(ENABLE_CYCLES_STATS) */
1716 /*****************************************************************************
1717 MISCELLANEOUS HELPER FUNCTIONS
1718 *****************************************************************************/
1722 /*********** Functions for integer divisions *****************************
1724 On some systems (eg. DEC ALPHA), integer division is not supported by the
1725 CPU. These helper functions implement the missing functionality.
1727 ******************************************************************************/
1729 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1730 s4 builtin_idiv(s4 a, s4 b)
1739 s4 builtin_irem(s4 a, s4 b)
1747 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1750 /* functions for long arithmetics **********************************************
1752 On systems where 64 bit Integers are not supported by the CPU,
1753 these functions are needed.
1755 ******************************************************************************/
1757 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1758 s8 builtin_ladd(s8 a, s8 b)
1771 s8 builtin_lsub(s8 a, s8 b)
1784 s8 builtin_lneg(s8 a)
1796 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1799 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1800 s8 builtin_lmul(s8 a, s8 b)
1812 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1815 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1816 s8 builtin_ldiv(s8 a, s8 b)
1829 s8 builtin_lrem(s8 a, s8 b)
1841 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1844 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1845 s8 builtin_lshl(s8 a, s4 b)
1858 s8 builtin_lshr(s8 a, s4 b)
1871 s8 builtin_lushr(s8 a, s4 b)
1876 c = ((u8) a) >> (b & 63);
1883 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1886 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1887 s8 builtin_land(s8 a, s8 b)
1900 s8 builtin_lor(s8 a, s8 b)
1913 s8 builtin_lxor(s8 a, s8 b)
1925 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1928 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1929 s4 builtin_lcmp(s8 a, s8 b)
1943 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1946 /* functions for unsupported floating instructions ****************************/
1948 /* used to convert FLT_xxx defines into float values */
1950 static inline float intBitsToFloat(s4 i)
1959 /* used to convert DBL_xxx defines into double values */
1961 static inline float longBitsToDouble(s8 l)
1971 float builtin_fadd(float a, float b)
1973 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1974 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1985 if (copysignf(1.0, a) == copysignf(1.0, b))
1988 return intBitsToFloat(FLT_NAN);
1994 float builtin_fsub(float a, float b)
1996 return builtin_fadd(a, builtin_fneg(b));
2000 float builtin_fmul(float a, float b)
2002 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2003 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2005 if (finitef(b)) return a * b;
2007 if (a == 0) return intBitsToFloat(FLT_NAN);
2008 else return copysignf(b, copysignf(1.0, b)*a);
2013 if (b == 0) return intBitsToFloat(FLT_NAN);
2014 else return copysignf(a, copysignf(1.0, a)*b);
2017 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2023 /* builtin_ddiv ****************************************************************
2025 Implementation as described in VM Spec.
2027 *******************************************************************************/
2029 float builtin_fdiv(float a, float b)
2033 /* If neither value1' nor value2' is NaN, the sign of the result */
2034 /* is positive if both values have the same sign, negative if the */
2035 /* values have different signs. */
2041 /* If either value1' or value2' is NaN, the result is NaN. */
2043 return intBitsToFloat(FLT_NAN);
2046 /* Division of a finite value by an infinity results in a */
2047 /* signed zero, with the sign-producing rule just given. */
2049 /* is sign equal? */
2051 if (copysignf(1.0, a) == copysignf(1.0, b))
2060 /* If either value1' or value2' is NaN, the result is NaN. */
2062 return intBitsToFloat(FLT_NAN);
2064 } else if (finitef(b)) {
2065 /* Division of an infinity by a finite value results in a signed */
2066 /* infinity, with the sign-producing rule just given. */
2068 /* is sign equal? */
2070 if (copysignf(1.0, a) == copysignf(1.0, b))
2071 return intBitsToFloat(FLT_POSINF);
2073 return intBitsToFloat(FLT_NEGINF);
2076 /* Division of an infinity by an infinity results in NaN. */
2078 return intBitsToFloat(FLT_NAN);
2084 float builtin_fneg(float a)
2086 if (isnanf(a)) return a;
2088 if (finitef(a)) return -a;
2089 else return copysignf(a, -copysignf(1.0, a));
2092 #endif /* !SUPPORT_FLOAT */
2095 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2096 s4 builtin_fcmpl(float a, float b)
2104 if (!finitef(a) || !finitef(b)) {
2105 a = finitef(a) ? 0 : copysignf(1.0, a);
2106 b = finitef(b) ? 0 : copysignf(1.0, b);
2119 s4 builtin_fcmpg(float a, float b)
2121 if (isnanf(a)) return 1;
2122 if (isnanf(b)) return 1;
2123 if (!finitef(a) || !finitef(b)) {
2124 a = finitef(a) ? 0 : copysignf(1.0, a);
2125 b = finitef(b) ? 0 : copysignf(1.0, b);
2127 if (a > b) return 1;
2128 if (a == b) return 0;
2131 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2134 float builtin_frem(float a, float b)
2140 /* functions for unsupported double instructions ******************************/
2143 double builtin_dadd(double a, double b)
2145 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2146 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2148 if (finite(b)) return a + b;
2152 if (finite(b)) return a;
2154 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2155 else return longBitsToDouble(DBL_NAN);
2161 double builtin_dsub(double a, double b)
2163 return builtin_dadd(a, builtin_dneg(b));
2167 double builtin_dmul(double a, double b)
2169 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2170 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2172 if (finite(b)) return a * b;
2174 if (a == 0) return longBitsToDouble(DBL_NAN);
2175 else return copysign(b, copysign(1.0, b) * a);
2180 if (b == 0) return longBitsToDouble(DBL_NAN);
2181 else return copysign(a, copysign(1.0, a) * b);
2184 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2190 /* builtin_ddiv ****************************************************************
2192 Implementation as described in VM Spec.
2194 *******************************************************************************/
2196 double builtin_ddiv(double a, double b)
2200 /* If neither value1' nor value2' is NaN, the sign of the result */
2201 /* is positive if both values have the same sign, negative if the */
2202 /* values have different signs. */
2208 /* If either value1' or value2' is NaN, the result is NaN. */
2210 return longBitsToDouble(DBL_NAN);
2213 /* Division of a finite value by an infinity results in a */
2214 /* signed zero, with the sign-producing rule just given. */
2216 /* is sign equal? */
2218 if (copysign(1.0, a) == copysign(1.0, b))
2227 /* If either value1' or value2' is NaN, the result is NaN. */
2229 return longBitsToDouble(DBL_NAN);
2231 } else if (finite(b)) {
2232 /* Division of an infinity by a finite value results in a signed */
2233 /* infinity, with the sign-producing rule just given. */
2235 /* is sign equal? */
2237 if (copysign(1.0, a) == copysign(1.0, b))
2238 return longBitsToDouble(DBL_POSINF);
2240 return longBitsToDouble(DBL_NEGINF);
2243 /* Division of an infinity by an infinity results in NaN. */
2245 return longBitsToDouble(DBL_NAN);
2251 /* builtin_dneg ****************************************************************
2253 Implemented as described in VM Spec.
2255 *******************************************************************************/
2257 double builtin_dneg(double a)
2260 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2267 /* If the operand is a zero, the result is the zero of opposite */
2273 /* If the operand is an infinity, the result is the infinity of */
2274 /* opposite sign. */
2276 return copysign(a, -copysign(1.0, a));
2280 #endif /* !SUPPORT_DOUBLE */
2283 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2284 s4 builtin_dcmpl(double a, double b)
2292 if (!finite(a) || !finite(b)) {
2293 a = finite(a) ? 0 : copysign(1.0, a);
2294 b = finite(b) ? 0 : copysign(1.0, b);
2307 s4 builtin_dcmpg(double a, double b)
2315 if (!finite(a) || !finite(b)) {
2316 a = finite(a) ? 0 : copysign(1.0, a);
2317 b = finite(b) ? 0 : copysign(1.0, b);
2328 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2331 double builtin_drem(double a, double b)
2337 /* conversion operations ******************************************************/
2340 s8 builtin_i2l(s4 i)
2352 s4 builtin_l2i(s8 l)
2363 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2364 float builtin_i2f(s4 a)
2366 float f = (float) a;
2369 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2372 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2373 double builtin_i2d(s4 a)
2375 double d = (double) a;
2378 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2381 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2382 float builtin_l2f(s8 a)
2385 float f = (float) a;
2391 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2394 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2395 double builtin_l2d(s8 a)
2398 double d = (double) a;
2404 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2407 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2408 s4 builtin_f2i(float a)
2412 i = builtin_d2i((double) a);
2423 if (a < (-2147483648))
2424 return (-2147483648);
2427 f = copysignf((float) 1.0, a);
2430 return (-2147483648); */
2432 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2435 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2436 s8 builtin_f2l(float a)
2440 l = builtin_d2l((double) a);
2447 if (a > 9223372036854775807L)
2448 return 9223372036854775807L;
2449 if (a < (-9223372036854775808L))
2450 return (-9223372036854775808L);
2455 f = copysignf((float) 1.0, a);
2457 return 9223372036854775807L;
2458 return (-9223372036854775808L); */
2460 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2463 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2464 s4 builtin_d2i(double a)
2469 if (a >= 2147483647)
2471 if (a <= (-2147483647-1))
2472 return (-2147483647-1);
2477 d = copysign(1.0, a);
2480 return (-2147483647-1);
2482 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2485 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2486 s8 builtin_d2l(double a)
2491 if (a >= 9223372036854775807LL)
2492 return 9223372036854775807LL;
2493 if (a <= (-9223372036854775807LL-1))
2494 return (-9223372036854775807LL-1);
2499 d = copysign(1.0, a);
2501 return 9223372036854775807LL;
2502 return (-9223372036854775807LL-1);
2504 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2507 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2508 double builtin_f2d(float a)
2510 if (finitef(a)) return (double) a;
2513 return longBitsToDouble(DBL_NAN);
2515 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2519 float builtin_d2f(double a)
2525 return intBitsToFloat(FLT_NAN);
2527 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2530 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2533 /* builtin_arraycopy ***********************************************************
2535 Builtin for java.lang.System.arraycopy.
2537 ATTENTION: This builtin function returns a boolean value to signal
2538 the ICMD_BUILTIN if there was an exception.
2540 *******************************************************************************/
2542 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2543 java_arrayheader *dest, s4 destStart, s4 len)
2545 arraydescriptor *sdesc;
2546 arraydescriptor *ddesc;
2549 if ((src == NULL) || (dest == NULL)) {
2550 exceptions_throw_nullpointerexception();
2554 sdesc = src->objheader.vftbl->arraydesc;
2555 ddesc = dest->objheader.vftbl->arraydesc;
2557 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2558 exceptions_throw_arraystoreexception();
2562 /* we try to throw exception with the same message as SUN does */
2564 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2565 (srcStart + len < 0) || (srcStart + len > src->size) ||
2566 (destStart + len < 0) || (destStart + len > dest->size)) {
2567 exceptions_throw_arrayindexoutofboundsexception();
2571 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2572 /* We copy primitive values or references of exactly the same type */
2574 s4 dataoffset = sdesc->dataoffset;
2575 s4 componentsize = sdesc->componentsize;
2577 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2578 ((u1 *) src) + dataoffset + componentsize * srcStart,
2579 (size_t) len * componentsize);
2582 /* We copy references of different type */
2584 java_objectarray *oas = (java_objectarray *) src;
2585 java_objectarray *oad = (java_objectarray *) dest;
2587 if (destStart <= srcStart) {
2588 for (i = 0; i < len; i++) {
2589 java_objectheader *o = oas->data[srcStart + i];
2591 if (!builtin_canstore(oad, o))
2594 oad->data[destStart + i] = o;
2598 /* XXX this does not completely obey the specification!
2599 If an exception is thrown only the elements above the
2600 current index have been copied. The specification
2601 requires that only the elements *below* the current
2602 index have been copied before the throw. */
2604 for (i = len - 1; i >= 0; i--) {
2605 java_objectheader *o = oas->data[srcStart + i];
2607 if (!builtin_canstore(oad, o))
2610 oad->data[destStart + i] = o;
2619 /* builtin_currenttimemillis ***************************************************
2621 Return the current time in milliseconds.
2623 *******************************************************************************/
2625 s8 builtin_currenttimemillis(void)
2630 if (gettimeofday(&tv, NULL) == -1)
2631 vm_abort("gettimeofday failed: %s", strerror(errno));
2633 result = (s8) tv.tv_sec;
2635 result += (tv.tv_usec / 1000);
2641 /* builtin_clone ***************************************************************
2643 Function for cloning objects or arrays.
2645 *******************************************************************************/
2647 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2649 arraydescriptor *ad;
2650 java_arrayheader *ah;
2653 java_objectheader *co; /* cloned object header */
2655 /* get the array descriptor */
2657 ad = o->vftbl->arraydesc;
2659 /* we are cloning an array */
2662 ah = (java_arrayheader *) o;
2664 size = ad->dataoffset + ad->componentsize * ah->size;
2666 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2671 MCOPY(co, o, u1, size);
2673 #if defined(ENABLE_GC_CACAO)
2674 heap_init_objectheader(co, size);
2677 #if defined(ENABLE_THREADS)
2678 lock_init_object_lock(co);
2684 /* we are cloning a non-array */
2686 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2687 exceptions_throw_clonenotsupportedexception();
2691 /* get the class of the object */
2693 c = o->vftbl->class;
2695 /* create new object */
2697 co = builtin_new(c);
2702 MCOPY(co, o, u1, c->instancesize);
2704 #if defined(ENABLE_GC_CACAO)
2705 heap_init_objectheader(co, c->instancesize);
2708 #if defined(ENABLE_THREADS)
2709 lock_init_object_lock(co);
2715 #if defined(ENABLE_VMLOG)
2717 #include <vmlog_cacao.c>
2722 * These are local overrides for various environment variables in Emacs.
2723 * Please do not remove this and leave it at the end of the file, where
2724 * Emacs will automagically detect them.
2725 * ---------------------------------------------------------------------
2728 * indent-tabs-mode: t
2732 * vim:noexpandtab:sw=4:ts=4: