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 8210 2007-07-18 12:51:00Z twisti $
49 #include "fdlibm/fdlibm.h"
50 #if defined(__CYGWIN__) && defined(Bias)
54 #include "mm/gc-common.h"
55 #include "mm/memory.h"
57 #include "native/jni.h"
58 #include "native/include/java_lang_String.h"
59 #include "native/include/java_lang_Throwable.h"
61 #include "threads/lock-common.h"
63 #include "toolbox/logging.h"
64 #include "toolbox/util.h"
66 #include "vm/builtin.h"
67 #include "vm/cycles-stats.h"
68 #include "vm/exceptions.h"
69 #include "vm/global.h"
70 #include "vm/initialize.h"
71 #include "vm/stringlocal.h"
73 #include "vm/jit/asmpart.h"
75 #include "vmcore/class.h"
76 #include "vmcore/loader.h"
77 #include "vmcore/options.h"
78 #include "vmcore/primitive.h"
79 #include "vmcore/rt-timing.h"
81 #if defined(ENABLE_VMLOG)
82 #include <vmlog_cacao.h>
85 #if defined(ENABLE_DEBUG_FILTER)
86 # include "vm/jit/show.h"
89 /* include builtin tables *****************************************************/
91 #include "vm/builtintable.inc"
94 CYCLES_STATS_DECLARE(builtin_new ,100,5)
95 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
97 /* builtintable_init ***********************************************************
99 Parse the descriptors of builtin functions and create the parsed
102 *******************************************************************************/
104 static bool builtintable_init(void)
106 descriptor_pool *descpool;
108 builtintable_entry *bte;
110 /* mark start of dump memory area */
112 dumpsize = dump_size();
114 /* create a new descriptor pool */
116 descpool = descriptor_pool_new(class_java_lang_Object);
118 /* add some entries we need */
120 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
123 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
126 /* first add all descriptors to the pool */
128 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
129 /* create a utf8 string from descriptor */
131 bte->descriptor = utf_new_char(bte->cdescriptor);
133 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
134 /* release dump area */
136 dump_release(dumpsize);
142 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
143 bte->descriptor = utf_new_char(bte->cdescriptor);
145 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
146 dump_release(dumpsize);
151 for (bte = builtintable_function; bte->fp != NULL; bte++) {
152 bte->classname = utf_new_char(bte->cclassname);
153 bte->name = utf_new_char(bte->cname);
154 bte->descriptor = utf_new_char(bte->cdescriptor);
156 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
157 dump_release(dumpsize);
162 /* create the class reference table */
164 (void) descriptor_pool_create_classrefs(descpool, NULL);
166 /* allocate space for the parsed descriptors */
168 descriptor_pool_alloc_parsed_descriptors(descpool);
170 /* Now parse all descriptors. NOTE: builtin-functions are treated
171 like static methods (no `this' pointer). */
173 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
175 descriptor_pool_parse_method_descriptor(descpool,
177 ACC_STATIC | ACC_METHOD_BUILTIN,
181 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
183 descriptor_pool_parse_method_descriptor(descpool,
185 ACC_STATIC | ACC_METHOD_BUILTIN,
189 for (bte = builtintable_function; bte->fp != NULL; bte++) {
191 descriptor_pool_parse_method_descriptor(descpool,
193 ACC_STATIC | ACC_METHOD_BUILTIN,
197 /* release dump area */
199 dump_release(dumpsize);
205 /* builtintable_comparator *****************************************************
207 qsort comparator for the automatic builtin table.
209 *******************************************************************************/
211 static int builtintable_comparator(const void *a, const void *b)
213 builtintable_entry *bte1;
214 builtintable_entry *bte2;
216 bte1 = (builtintable_entry *) a;
217 bte2 = (builtintable_entry *) b;
219 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
223 /* builtintable_sort_automatic *************************************************
225 Sorts the automatic builtin table.
227 *******************************************************************************/
229 static void builtintable_sort_automatic(void)
233 /* calculate table size statically (`- 1' comment see builtintable.inc) */
235 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
237 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
238 builtintable_comparator);
242 /* builtin_init ****************************************************************
244 Initialize the global table of builtin functions.
246 *******************************************************************************/
248 bool builtin_init(void)
250 /* initialize the builtin tables */
252 if (!builtintable_init())
255 /* sort builtin tables */
257 builtintable_sort_automatic();
263 /* builtintable_get_internal ***************************************************
265 Finds an entry in the builtintable for internal functions and
266 returns the a pointer to the structure.
268 *******************************************************************************/
270 builtintable_entry *builtintable_get_internal(functionptr fp)
272 builtintable_entry *bte;
274 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
283 /* builtintable_get_automatic **************************************************
285 Finds an entry in the builtintable for functions which are replaced
286 automatically and returns the a pointer to the structure.
288 *******************************************************************************/
290 builtintable_entry *builtintable_get_automatic(s4 opcode)
292 builtintable_entry *first;
293 builtintable_entry *last;
294 builtintable_entry *middle;
298 /* calculate table size statically (`- 1' comment see builtintable.inc) */
300 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
302 first = builtintable_automatic;
303 last = builtintable_automatic + entries;
305 while (entries > 0) {
307 middle = first + half;
309 if (middle->opcode < opcode) {
316 return (first != last ? first : NULL);
320 /* builtintable_replace_function ***********************************************
324 *******************************************************************************/
326 #if defined(ENABLE_JIT)
327 bool builtintable_replace_function(void *iptr_)
330 builtintable_entry *bte;
333 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
335 /* get name and descriptor of the function */
338 case ICMD_INVOKESTATIC:
339 /* The instruction MUST be resolved, otherwise we run into
340 lazy loading troubles. Anyway, we should/can only replace
341 very VM-close functions. */
343 if (INSTRUCTION_IS_UNRESOLVED(iptr))
346 mr = iptr->sx.s23.s3.fmiref;
353 /* search the function table */
355 for (bte = builtintable_function; bte->fp != NULL; bte++) {
356 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
357 (mr->name == bte->name) &&
358 (mr->descriptor == bte->descriptor)) {
360 /* set the values in the instruction */
362 iptr->opc = bte->opcode;
363 iptr->sx.s23.s3.bte = bte;
364 if (bte->checkexception)
365 iptr->flags.bits |= INS_FLAG_CHECK;
367 iptr->flags.bits &= ~INS_FLAG_CHECK;
375 #endif /* defined(ENABLE_JIT) */
378 /*****************************************************************************
380 *****************************************************************************/
382 /* builtin_instanceof **********************************************************
384 Checks if an object is an instance of some given class (or subclass
385 of that class). If class is an interface, checks if the interface
388 Return value: 1 ... o is an instance of class or implements the interface
389 0 ... otherwise or if o == NULL
391 *******************************************************************************/
393 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
398 return class_isanysubclass(o->vftbl->class, class);
403 /* builtin_checkcast ***********************************************************
405 The same as builtin_instanceof except that 1 is returned when o ==
408 *******************************************************************************/
410 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
415 if (class_isanysubclass(o->vftbl->class, class))
422 /* builtin_descriptorscompatible ***********************************************
424 Checks if two array type descriptors are assignment compatible
426 Return value: 1 ... target = desc is possible
429 *******************************************************************************/
431 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
432 arraydescriptor *target)
437 if (desc->arraytype != target->arraytype)
440 if (desc->arraytype != ARRAYTYPE_OBJECT)
443 /* {both arrays are arrays of references} */
445 if (desc->dimension == target->dimension) {
446 /* an array which contains elements of interface types is
447 allowed to be casted to Object (JOWENN)*/
449 if ((desc->elementvftbl->baseval < 0) &&
450 (target->elementvftbl->baseval == 1))
453 return class_isanysubclass(desc->elementvftbl->class,
454 target->elementvftbl->class);
457 if (desc->dimension < target->dimension)
460 /* {desc has higher dimension than target} */
462 return class_isanysubclass(pseudo_class_Arraystub,
463 target->elementvftbl->class);
467 /* builtin_arraycheckcast ******************************************************
469 Checks if an object is really a subtype of the requested array
470 type. The object has to be an array to begin with. For simple
471 arrays (int, short, double, etc.) the types have to match exactly.
472 For arrays of objects, the type of elements in the array has to be
473 a subtype (or the same type) of the requested element type. For
474 arrays of arrays (which in turn can again be arrays of arrays), the
475 types at the lowest level have to satisfy the corresponding sub
478 *******************************************************************************/
480 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
482 arraydescriptor *desc;
487 desc = o->vftbl->arraydesc;
492 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
496 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
501 return builtin_arraycheckcast(o, targetclass);
505 /* builtin_throw_exception *****************************************************
507 Sets the exceptionptr with the thrown exception and prints some
508 debugging information. Called from asm_vm_call_method.
510 *******************************************************************************/
512 void *builtin_throw_exception(java_objectheader *xptr)
515 java_lang_Throwable *t;
521 t = (java_lang_Throwable *) xptr;
523 /* calculate message length */
525 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
529 utf_bytes(xptr->vftbl->class->name);
530 if (t->detailMessage) {
531 logtextlen += strlen(": ") +
532 u2_utflength(t->detailMessage->value->data
533 + t->detailMessage->offset,
534 t->detailMessage->count);
538 logtextlen += strlen("(nil)");
541 /* allocate memory */
543 dumpsize = dump_size();
545 logtext = DMNEW(char, logtextlen);
547 strcpy(logtext, "Builtin exception thrown: ");
550 utf_cat_classname(logtext, xptr->vftbl->class->name);
552 if (t->detailMessage) {
555 buf = javastring_tochar((java_objectheader *) t->detailMessage);
556 strcat(logtext, ": ");
557 strcat(logtext, buf);
558 MFREE(buf, char, strlen(buf) + 1);
562 strcat(logtext, "(nil)");
569 dump_release(dumpsize);
571 #endif /* !defined(NDEBUG) */
573 /* actually set the exception */
575 exceptions_set_exception(xptr);
577 /* Return a NULL pointer. This is required for vm_call_method to
578 check for an exception. This is for convenience. */
584 /* builtin_canstore ************************************************************
586 Checks, if an object can be stored in an array.
588 Return value: 1 ... possible
589 0 ... otherwise (throws an ArrayStoreException)
591 *******************************************************************************/
593 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
595 arraydescriptor *desc;
596 arraydescriptor *valuedesc;
597 vftbl_t *componentvftbl;
600 castinfo classvalues;
606 /* The following is guaranteed (by verifier checks):
608 * *) oa->...vftbl->arraydesc != NULL
609 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
610 * *) o->vftbl is not an interface vftbl
613 desc = oa->header.objheader.vftbl->arraydesc;
614 componentvftbl = desc->componentvftbl;
615 valuevftbl = o->vftbl;
616 valuedesc = valuevftbl->arraydesc;
618 if ((desc->dimension - 1) == 0) {
619 /* {oa is a one-dimensional array} */
620 /* {oa is an array of references} */
622 if (valuevftbl == componentvftbl)
625 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
627 base = classvalues.super_baseval;
630 /* an array of interface references */
632 result = ((valuevftbl->interfacetablelength > -base) &&
633 (valuevftbl->interfacetable[base] != NULL));
636 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
637 <= (unsigned) classvalues.super_diffval);
640 else if (valuedesc == NULL) {
641 /* {oa has dimension > 1} */
642 /* {componentvftbl->arraydesc != NULL} */
644 /* check if o is an array */
649 /* {o is an array} */
651 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
654 /* if not possible, throw an exception */
657 exceptions_throw_arraystoreexception();
665 /* This is an optimized version where a is guaranteed to be one-dimensional */
666 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
668 arraydescriptor *desc;
669 vftbl_t *elementvftbl;
673 castinfo classvalues;
677 /* The following is guaranteed (by verifier checks):
679 * *) a->...vftbl->arraydesc != NULL
680 * *) a->...vftbl->arraydesc->elementvftbl != NULL
681 * *) a->...vftbl->arraydesc->dimension == 1
682 * *) o->vftbl is not an interface vftbl
685 desc = a->header.objheader.vftbl->arraydesc;
686 elementvftbl = desc->elementvftbl;
687 valuevftbl = o->vftbl;
689 /* {a is a one-dimensional array} */
691 if (valuevftbl == elementvftbl)
694 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
696 if ((base = classvalues.super_baseval) <= 0)
697 /* an array of interface references */
698 return (valuevftbl->interfacetablelength > -base &&
699 valuevftbl->interfacetable[base] != NULL);
701 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
702 <= (unsigned) classvalues.super_diffval;
708 /* This is an optimized version where a is guaranteed to be a
709 * one-dimensional array of a class type */
710 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
712 vftbl_t *elementvftbl;
715 castinfo classvalues;
719 /* The following is guaranteed (by verifier checks):
721 * *) a->...vftbl->arraydesc != NULL
722 * *) a->...vftbl->arraydesc->elementvftbl != NULL
723 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
724 * *) a->...vftbl->arraydesc->dimension == 1
725 * *) o->vftbl is not an interface vftbl
728 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
729 valuevftbl = o->vftbl;
731 /* {a is a one-dimensional array} */
733 if (valuevftbl == elementvftbl)
736 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
738 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
739 <= (unsigned) classvalues.super_diffval;
745 /* builtin_new *****************************************************************
747 Creates a new instance of class c on the heap.
749 Return value: pointer to the object or NULL if no memory is
752 *******************************************************************************/
754 java_objectheader *builtin_new(classinfo *c)
756 java_objectheader *o;
757 #if defined(ENABLE_RT_TIMING)
758 struct timespec time_start, time_end;
760 #if defined(ENABLE_CYCLES_STATS)
761 u8 cycles_start, cycles_end;
764 RT_TIMING_GET_TIME(time_start);
765 CYCLES_STATS_GET(cycles_start);
767 /* is the class loaded */
769 assert(c->state & CLASS_LOADED);
771 /* check if we can instantiate this class */
773 if (c->flags & ACC_ABSTRACT) {
774 exceptions_throw_instantiationerror(c);
778 /* is the class linked */
780 if (!(c->state & CLASS_LINKED))
784 if (!(c->state & CLASS_INITIALIZED)) {
787 log_message_class("Initialize class (from builtin_new): ", c);
790 if (!initialize_class(c))
794 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
802 #if defined(ENABLE_THREADS)
803 lock_init_object_lock(o);
806 CYCLES_STATS_GET(cycles_end);
807 RT_TIMING_GET_TIME(time_end);
809 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
810 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
816 /* builtin_newarray ************************************************************
818 Creates an array with the given vftbl on the heap. This function
819 takes as class argument an array class.
821 Return value: pointer to the array or NULL if no memory is available
823 *******************************************************************************/
825 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
827 arraydescriptor *desc;
832 #if defined(ENABLE_RT_TIMING)
833 struct timespec time_start, time_end;
836 RT_TIMING_GET_TIME(time_start);
838 desc = arrayclass->vftbl->arraydesc;
839 dataoffset = desc->dataoffset;
840 componentsize = desc->componentsize;
843 exceptions_throw_negativearraysizeexception();
847 actualsize = dataoffset + size * componentsize;
849 /* check for overflow */
851 if (((u4) actualsize) < ((u4) size)) {
852 exceptions_throw_outofmemoryerror();
856 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
861 a->objheader.vftbl = arrayclass->vftbl;
863 #if defined(ENABLE_THREADS)
864 lock_init_object_lock(&a->objheader);
869 RT_TIMING_GET_TIME(time_end);
870 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
876 /* builtin_anewarray ***********************************************************
878 Creates an array of references to the given class type on the heap.
880 Return value: pointer to the array or NULL if no memory is
883 *******************************************************************************/
885 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
887 classinfo *arrayclass;
889 /* is class loaded */
891 assert(componentclass->state & CLASS_LOADED);
893 /* is class linked */
895 if (!(componentclass->state & CLASS_LINKED))
896 if (!link_class(componentclass))
899 arrayclass = class_array_of(componentclass, true);
904 return (java_objectarray *) builtin_newarray(size, arrayclass);
908 /* builtin_newarray_boolean ****************************************************
910 Creates an array of bytes on the heap. The array is designated as
911 an array of booleans (important for casts)
913 Return value: pointer to the array or NULL if no memory is
916 *******************************************************************************/
918 java_booleanarray *builtin_newarray_boolean(s4 size)
920 return (java_booleanarray *)
921 builtin_newarray(size,
922 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
926 /* builtin_newarray_byte *******************************************************
928 Creates an array of 8 bit Integers on the heap.
930 Return value: pointer to the array or NULL if no memory is
933 *******************************************************************************/
935 java_bytearray *builtin_newarray_byte(s4 size)
937 return (java_bytearray *)
938 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
942 /* builtin_newarray_char *******************************************************
944 Creates an array of characters on the heap.
946 Return value: pointer to the array or NULL if no memory is
949 *******************************************************************************/
951 java_chararray *builtin_newarray_char(s4 size)
953 return (java_chararray *)
954 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
958 /* builtin_newarray_short ******************************************************
960 Creates an array of 16 bit Integers on the heap.
962 Return value: pointer to the array or NULL if no memory is
965 *******************************************************************************/
967 java_shortarray *builtin_newarray_short(s4 size)
969 return (java_shortarray *)
970 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
974 /* builtin_newarray_int ********************************************************
976 Creates an array of 32 bit Integers on the heap.
978 Return value: pointer to the array or NULL if no memory is
981 *******************************************************************************/
983 java_intarray *builtin_newarray_int(s4 size)
985 return (java_intarray *)
986 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
990 /* builtin_newarray_long *******************************************************
992 Creates an array of 64 bit Integers on the heap.
994 Return value: pointer to the array or NULL if no memory is
997 *******************************************************************************/
999 java_longarray *builtin_newarray_long(s4 size)
1001 return (java_longarray *)
1002 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1006 /* builtin_newarray_float ******************************************************
1008 Creates an array of 32 bit IEEE floats on the heap.
1010 Return value: pointer to the array or NULL if no memory is
1013 *******************************************************************************/
1015 java_floatarray *builtin_newarray_float(s4 size)
1017 return (java_floatarray *)
1018 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1022 /* builtin_newarray_double *****************************************************
1024 Creates an array of 64 bit IEEE floats on the heap.
1026 Return value: pointer to the array or NULL if no memory is
1029 *******************************************************************************/
1031 java_doublearray *builtin_newarray_double(s4 size)
1033 return (java_doublearray *)
1034 builtin_newarray(size,
1035 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1039 /* builtin_multianewarray_intern ***********************************************
1041 Creates a multi-dimensional array on the heap. The dimensions are
1042 passed in an array of longs.
1045 n.............number of dimensions to create
1046 arrayclass....the array class
1047 dims..........array containing the size of each dimension to create
1049 Return value: pointer to the array or NULL if no memory is
1052 ******************************************************************************/
1054 static java_arrayheader *builtin_multianewarray_intern(int n,
1055 classinfo *arrayclass,
1059 java_arrayheader *a;
1060 classinfo *componentclass;
1063 /* create this dimension */
1065 size = (s4) dims[0];
1066 a = builtin_newarray(size, arrayclass);
1071 /* if this is the last dimension return */
1076 /* get the class of the components to create */
1078 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1080 /* The verifier guarantees that the dimension count is in the range. */
1082 /* create the component arrays */
1084 for (i = 0; i < size; i++) {
1085 java_arrayheader *ea =
1086 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1087 /* we save an s4 to a s8 slot, 8-byte aligned */
1089 builtin_multianewarray_intern(n, componentclass, dims + 2);
1091 builtin_multianewarray_intern(n, componentclass, dims + 1);
1097 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1104 /* builtin_multianewarray ******************************************************
1106 Wrapper for builtin_multianewarray_intern which checks all
1107 dimensions before we start allocating.
1109 ******************************************************************************/
1111 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1117 /* check all dimensions before doing anything */
1119 for (i = 0; i < n; i++) {
1120 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1121 /* we save an s4 to a s8 slot, 8-byte aligned */
1122 size = (s4) dims[i * 2];
1124 size = (s4) dims[i];
1128 exceptions_throw_negativearraysizeexception();
1133 /* now call the real function */
1135 return builtin_multianewarray_intern(n, arrayclass, dims);
1139 /*****************************************************************************
1142 Various functions for printing a message at method entry or exit (for
1145 *****************************************************************************/
1147 #if !defined(NDEBUG)
1148 static s4 methodindent = 0;
1149 static u4 callcount = 0;
1151 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1161 #if defined(ENABLE_DEBUG_FILTER)
1162 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1165 #if defined(ENABLE_VMLOG)
1169 if (opt_verbosecall && indent)
1172 /* calculate message length */
1176 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1179 logtextlen = strlen("Some Throwable");
1182 logtextlen += strlen(" thrown in ");
1186 utf_bytes(m->class->name) +
1188 utf_bytes(m->name) +
1189 utf_bytes(m->descriptor) +
1190 strlen("(NOSYNC,NATIVE");
1192 #if SIZEOF_VOID_P == 8
1194 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1196 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1199 if (m->class->sourcefile == NULL)
1200 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1202 logtextlen += utf_bytes(m->class->sourcefile);
1204 logtextlen += strlen(":65536)");
1208 logtextlen += strlen("call_java_method");
1211 logtextlen += strlen("0");
1213 /* allocate memory */
1215 dumpsize = dump_size();
1217 logtext = DMNEW(char, logtextlen);
1220 strcpy(logtext, "Exception ");
1221 utf_cat_classname(logtext, xptr->vftbl->class->name);
1224 strcpy(logtext, "Some Throwable");
1227 strcat(logtext, " thrown in ");
1230 utf_cat_classname(logtext, m->class->name);
1231 strcat(logtext, ".");
1232 utf_cat(logtext, m->name);
1233 utf_cat(logtext, m->descriptor);
1235 if (m->flags & ACC_SYNCHRONIZED)
1236 strcat(logtext, "(SYNC");
1238 strcat(logtext, "(NOSYNC");
1240 if (m->flags & ACC_NATIVE) {
1241 strcat(logtext, ",NATIVE");
1245 #if SIZEOF_VOID_P == 8
1246 sprintf(logtext + strlen(logtext),
1247 ")(0x%016lx) at position 0x%016lx",
1248 (ptrint) code->entrypoint, (ptrint) pos);
1250 sprintf(logtext + strlen(logtext),
1251 ")(0x%08x) at position 0x%08x",
1252 (ptrint) code->entrypoint, (ptrint) pos);
1257 /* XXX preliminary: This should get the actual codeinfo */
1258 /* in which the exception happened. */
1261 #if SIZEOF_VOID_P == 8
1262 sprintf(logtext + strlen(logtext),
1263 ")(0x%016lx) at position 0x%016lx (",
1264 (ptrint) code->entrypoint, (ptrint) pos);
1266 sprintf(logtext + strlen(logtext),
1267 ")(0x%08x) at position 0x%08x (",
1268 (ptrint) code->entrypoint, (ptrint) pos);
1271 if (m->class->sourcefile == NULL)
1272 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1274 utf_cat(logtext, m->class->sourcefile);
1276 sprintf(logtext + strlen(logtext), ":%d)", 0);
1280 strcat(logtext, "call_java_method");
1284 /* release memory */
1286 dump_release(dumpsize);
1290 #endif /* !defined(NDEBUG) */
1293 /* builtin_print_argument ******************************************************
1295 Prints arguments and return values for the call trace.
1297 *******************************************************************************/
1299 #if !defined(NDEBUG)
1300 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1301 typedesc *paramtype, s8 value)
1304 java_objectheader *o;
1309 switch (paramtype->type) {
1312 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1317 #if SIZEOF_VOID_P == 4
1318 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1320 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1325 #if defined(__S390__)
1327 /* The below won't work on S390 */
1331 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1336 #if SIZEOF_VOID_P == 4
1337 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1339 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1344 #if SIZEOF_VOID_P == 4
1345 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1347 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1350 /* cast to java.lang.Object */
1352 o = (java_objectheader *) (ptrint) value;
1354 /* check return argument for java.lang.Class or java.lang.String */
1357 if (o->vftbl->class == class_java_lang_String) {
1358 /* get java.lang.String object and the length of the
1361 u = javastring_toutf(o, false);
1363 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1365 /* realloc memory for string length */
1367 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1370 /* convert to utf8 string and strcat it to the logtext */
1372 strcat(logtext, " (String = \"");
1373 utf_cat(logtext, u);
1374 strcat(logtext, "\")");
1377 if (o->vftbl->class == class_java_lang_Class) {
1378 /* if the object returned is a java.lang.Class
1379 cast it to classinfo structure and get the name
1382 c = (classinfo *) o;
1387 /* if the object returned is not a java.lang.String or
1388 a java.lang.Class just print the name of the class */
1390 u = o->vftbl->class->name;
1393 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1395 /* realloc memory for string length */
1397 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1400 /* strcat to the logtext */
1402 strcat(logtext, " (Class = \"");
1403 utf_cat_classname(logtext, u);
1404 strcat(logtext, "\")");
1411 #endif /* !defined(NDEBUG) */
1413 /* builtin_verbosecall_enter ***************************************************
1415 Print method call with arguments for -verbose:call.
1417 *******************************************************************************/
1419 #if !defined(NDEBUG)
1421 #ifdef TRACE_ARGS_NUM
1422 void builtin_verbosecall_enter(s8 a0, s8 a1,
1423 # if TRACE_ARGS_NUM >= 4
1426 # if TRACE_ARGS_NUM >= 6
1429 # if TRACE_ARGS_NUM == 8
1441 #if defined(ENABLE_DEBUG_FILTER)
1442 if (! show_filters_test_verbosecall_enter(m)) return;
1445 #if defined(ENABLE_VMLOG)
1446 vmlog_cacao_enter_method(m);
1452 /* calculate message length */
1455 strlen("4294967295 ") +
1456 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1458 strlen("called: ") +
1459 utf_bytes(m->class->name) +
1461 utf_bytes(m->name) +
1462 utf_bytes(m->descriptor);
1464 /* Actually it's not possible to have all flags printed, but:
1469 strlen(" PRIVATE") +
1470 strlen(" PROTECTED") +
1473 strlen(" SYNCHRONIZED") +
1474 strlen(" VOLATILE") +
1475 strlen(" TRANSIENT") +
1477 strlen(" INTERFACE") +
1478 strlen(" ABSTRACT");
1480 /* add maximal argument length */
1484 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1485 strlen("...(255)") +
1488 /* allocate memory */
1490 dumpsize = dump_size();
1492 logtext = DMNEW(char, logtextlen);
1496 sprintf(logtext, "%10d ", callcount);
1497 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1499 pos = strlen(logtext);
1501 for (i = 0; i < methodindent; i++)
1502 logtext[pos++] = '\t';
1504 strcpy(logtext + pos, "called: ");
1506 utf_cat_classname(logtext, m->class->name);
1507 strcat(logtext, ".");
1508 utf_cat(logtext, m->name);
1509 utf_cat(logtext, m->descriptor);
1511 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1512 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1513 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1514 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1515 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1516 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1517 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1518 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1519 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1520 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1521 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1523 strcat(logtext, "(");
1525 if (md->paramcount >= 1) {
1526 logtext = builtin_print_argument(logtext, &logtextlen,
1527 &md->paramtypes[0], a0);
1530 if (md->paramcount >= 2) {
1531 strcat(logtext, ", ");
1533 logtext = builtin_print_argument(logtext, &logtextlen,
1534 &md->paramtypes[1], a1);
1537 #if TRACE_ARGS_NUM >= 4
1538 if (md->paramcount >= 3) {
1539 strcat(logtext, ", ");
1541 logtext = builtin_print_argument(logtext, &logtextlen,
1542 &md->paramtypes[2], a2);
1545 if (md->paramcount >= 4) {
1546 strcat(logtext, ", ");
1548 logtext = builtin_print_argument(logtext, &logtextlen,
1549 &md->paramtypes[3], a3);
1553 #if TRACE_ARGS_NUM >= 6
1554 if (md->paramcount >= 5) {
1555 strcat(logtext, ", ");
1557 logtext = builtin_print_argument(logtext, &logtextlen,
1558 &md->paramtypes[4], a4);
1561 if (md->paramcount >= 6) {
1562 strcat(logtext, ", ");
1564 logtext = builtin_print_argument(logtext, &logtextlen,
1565 &md->paramtypes[5], a5);
1569 #if TRACE_ARGS_NUM == 8
1570 if (md->paramcount >= 7) {
1571 strcat(logtext, ", ");
1573 logtext = builtin_print_argument(logtext, &logtextlen,
1574 &md->paramtypes[6], a6);
1577 if (md->paramcount >= 8) {
1578 strcat(logtext, ", ");
1580 logtext = builtin_print_argument(logtext, &logtextlen,
1581 &md->paramtypes[7], a7);
1585 if (md->paramcount > 8) {
1586 sprintf(logtext + strlen(logtext), ", ...(%d)",
1587 md->paramcount - TRACE_ARGS_NUM);
1590 strcat(logtext, ")");
1594 /* release memory */
1596 dump_release(dumpsize);
1602 #endif /* !defined(NDEBUG) */
1605 /* builtin_verbosecall_exit ****************************************************
1607 Print method exit for -verbose:call.
1609 *******************************************************************************/
1611 #if !defined(NDEBUG)
1612 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1622 #if defined(ENABLE_DEBUG_FILTER)
1623 if (! show_filters_test_verbosecall_exit(m)) return;
1626 #if defined(ENABLE_VMLOG)
1627 vmlog_cacao_leave_method(m);
1633 /* calculate message length */
1636 strlen("4294967295 ") +
1637 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1639 strlen("finished: ") +
1640 utf_bytes(m->class->name) +
1642 utf_bytes(m->name) +
1643 utf_bytes(m->descriptor) +
1644 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1646 /* add maximal argument length */
1648 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1650 /* allocate memory */
1652 dumpsize = dump_size();
1654 logtext = DMNEW(char, logtextlen);
1656 /* outdent the log message */
1661 log_text("WARNING: unmatched methodindent--");
1663 /* generate the message */
1665 sprintf(logtext, " ");
1666 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1668 pos = strlen(logtext);
1670 for (i = 0; i < methodindent; i++)
1671 logtext[pos++] = '\t';
1673 strcpy(logtext + pos, "finished: ");
1674 utf_cat_classname(logtext, m->class->name);
1675 strcat(logtext, ".");
1676 utf_cat(logtext, m->name);
1677 utf_cat(logtext, m->descriptor);
1679 if (!IS_VOID_TYPE(md->returntype.type)) {
1680 strcat(logtext, "->");
1682 switch (md->returntype.type) {
1699 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1704 /* release memory */
1706 dump_release(dumpsize);
1709 #endif /* !defined(NDEBUG) */
1712 #if defined(ENABLE_CYCLES_STATS)
1713 void builtin_print_cycles_stats(FILE *file)
1715 fprintf(file,"builtin cylce count statistics:\n");
1717 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1718 CYCLES_STATS_PRINT(builtin_new ,file);
1722 #endif /* defined(ENABLE_CYCLES_STATS) */
1725 /*****************************************************************************
1726 MISCELLANEOUS HELPER FUNCTIONS
1727 *****************************************************************************/
1731 /*********** Functions for integer divisions *****************************
1733 On some systems (eg. DEC ALPHA), integer division is not supported by the
1734 CPU. These helper functions implement the missing functionality.
1736 ******************************************************************************/
1738 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1739 s4 builtin_idiv(s4 a, s4 b)
1748 s4 builtin_irem(s4 a, s4 b)
1756 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1759 /* functions for long arithmetics **********************************************
1761 On systems where 64 bit Integers are not supported by the CPU,
1762 these functions are needed.
1764 ******************************************************************************/
1766 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1767 s8 builtin_ladd(s8 a, s8 b)
1780 s8 builtin_lsub(s8 a, s8 b)
1793 s8 builtin_lneg(s8 a)
1805 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1808 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1809 s8 builtin_lmul(s8 a, s8 b)
1821 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1824 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1825 s8 builtin_ldiv(s8 a, s8 b)
1838 s8 builtin_lrem(s8 a, s8 b)
1850 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1853 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1854 s8 builtin_lshl(s8 a, s4 b)
1867 s8 builtin_lshr(s8 a, s4 b)
1880 s8 builtin_lushr(s8 a, s4 b)
1885 c = ((u8) a) >> (b & 63);
1892 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1895 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1896 s8 builtin_land(s8 a, s8 b)
1909 s8 builtin_lor(s8 a, s8 b)
1922 s8 builtin_lxor(s8 a, s8 b)
1934 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1937 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1938 s4 builtin_lcmp(s8 a, s8 b)
1952 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1955 /* functions for unsupported floating instructions ****************************/
1957 /* used to convert FLT_xxx defines into float values */
1959 static inline float intBitsToFloat(s4 i)
1968 /* used to convert DBL_xxx defines into double values */
1970 static inline float longBitsToDouble(s8 l)
1980 float builtin_fadd(float a, float b)
1982 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1983 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1994 if (copysignf(1.0, a) == copysignf(1.0, b))
1997 return intBitsToFloat(FLT_NAN);
2003 float builtin_fsub(float a, float b)
2005 return builtin_fadd(a, builtin_fneg(b));
2009 float builtin_fmul(float a, float b)
2011 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2012 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2014 if (finitef(b)) return a * b;
2016 if (a == 0) return intBitsToFloat(FLT_NAN);
2017 else return copysignf(b, copysignf(1.0, b)*a);
2022 if (b == 0) return intBitsToFloat(FLT_NAN);
2023 else return copysignf(a, copysignf(1.0, a)*b);
2026 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2032 /* builtin_ddiv ****************************************************************
2034 Implementation as described in VM Spec.
2036 *******************************************************************************/
2038 float builtin_fdiv(float a, float b)
2042 /* If neither value1' nor value2' is NaN, the sign of the result */
2043 /* is positive if both values have the same sign, negative if the */
2044 /* values have different signs. */
2050 /* If either value1' or value2' is NaN, the result is NaN. */
2052 return intBitsToFloat(FLT_NAN);
2055 /* Division of a finite value by an infinity results in a */
2056 /* signed zero, with the sign-producing rule just given. */
2058 /* is sign equal? */
2060 if (copysignf(1.0, a) == copysignf(1.0, b))
2069 /* If either value1' or value2' is NaN, the result is NaN. */
2071 return intBitsToFloat(FLT_NAN);
2073 } else if (finitef(b)) {
2074 /* Division of an infinity by a finite value results in a signed */
2075 /* infinity, with the sign-producing rule just given. */
2077 /* is sign equal? */
2079 if (copysignf(1.0, a) == copysignf(1.0, b))
2080 return intBitsToFloat(FLT_POSINF);
2082 return intBitsToFloat(FLT_NEGINF);
2085 /* Division of an infinity by an infinity results in NaN. */
2087 return intBitsToFloat(FLT_NAN);
2093 float builtin_fneg(float a)
2095 if (isnanf(a)) return a;
2097 if (finitef(a)) return -a;
2098 else return copysignf(a, -copysignf(1.0, a));
2101 #endif /* !SUPPORT_FLOAT */
2104 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2105 s4 builtin_fcmpl(float a, float b)
2113 if (!finitef(a) || !finitef(b)) {
2114 a = finitef(a) ? 0 : copysignf(1.0, a);
2115 b = finitef(b) ? 0 : copysignf(1.0, b);
2128 s4 builtin_fcmpg(float a, float b)
2130 if (isnanf(a)) return 1;
2131 if (isnanf(b)) return 1;
2132 if (!finitef(a) || !finitef(b)) {
2133 a = finitef(a) ? 0 : copysignf(1.0, a);
2134 b = finitef(b) ? 0 : copysignf(1.0, b);
2136 if (a > b) return 1;
2137 if (a == b) return 0;
2140 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2143 float builtin_frem(float a, float b)
2149 /* functions for unsupported double instructions ******************************/
2152 double builtin_dadd(double a, double b)
2154 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2155 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2157 if (finite(b)) return a + b;
2161 if (finite(b)) return a;
2163 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2164 else return longBitsToDouble(DBL_NAN);
2170 double builtin_dsub(double a, double b)
2172 return builtin_dadd(a, builtin_dneg(b));
2176 double builtin_dmul(double a, double b)
2178 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2179 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2181 if (finite(b)) return a * b;
2183 if (a == 0) return longBitsToDouble(DBL_NAN);
2184 else return copysign(b, copysign(1.0, b) * a);
2189 if (b == 0) return longBitsToDouble(DBL_NAN);
2190 else return copysign(a, copysign(1.0, a) * b);
2193 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2199 /* builtin_ddiv ****************************************************************
2201 Implementation as described in VM Spec.
2203 *******************************************************************************/
2205 double builtin_ddiv(double a, double b)
2209 /* If neither value1' nor value2' is NaN, the sign of the result */
2210 /* is positive if both values have the same sign, negative if the */
2211 /* values have different signs. */
2217 /* If either value1' or value2' is NaN, the result is NaN. */
2219 return longBitsToDouble(DBL_NAN);
2222 /* Division of a finite value by an infinity results in a */
2223 /* signed zero, with the sign-producing rule just given. */
2225 /* is sign equal? */
2227 if (copysign(1.0, a) == copysign(1.0, b))
2236 /* If either value1' or value2' is NaN, the result is NaN. */
2238 return longBitsToDouble(DBL_NAN);
2240 } else if (finite(b)) {
2241 /* Division of an infinity by a finite value results in a signed */
2242 /* infinity, with the sign-producing rule just given. */
2244 /* is sign equal? */
2246 if (copysign(1.0, a) == copysign(1.0, b))
2247 return longBitsToDouble(DBL_POSINF);
2249 return longBitsToDouble(DBL_NEGINF);
2252 /* Division of an infinity by an infinity results in NaN. */
2254 return longBitsToDouble(DBL_NAN);
2260 /* builtin_dneg ****************************************************************
2262 Implemented as described in VM Spec.
2264 *******************************************************************************/
2266 double builtin_dneg(double a)
2269 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2276 /* If the operand is a zero, the result is the zero of opposite */
2282 /* If the operand is an infinity, the result is the infinity of */
2283 /* opposite sign. */
2285 return copysign(a, -copysign(1.0, a));
2289 #endif /* !SUPPORT_DOUBLE */
2292 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2293 s4 builtin_dcmpl(double a, double b)
2301 if (!finite(a) || !finite(b)) {
2302 a = finite(a) ? 0 : copysign(1.0, a);
2303 b = finite(b) ? 0 : copysign(1.0, b);
2316 s4 builtin_dcmpg(double a, double b)
2324 if (!finite(a) || !finite(b)) {
2325 a = finite(a) ? 0 : copysign(1.0, a);
2326 b = finite(b) ? 0 : copysign(1.0, b);
2337 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2340 double builtin_drem(double a, double b)
2346 /* conversion operations ******************************************************/
2349 s8 builtin_i2l(s4 i)
2361 s4 builtin_l2i(s8 l)
2372 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2373 float builtin_i2f(s4 a)
2375 float f = (float) a;
2378 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2381 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2382 double builtin_i2d(s4 a)
2384 double d = (double) a;
2387 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2390 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2391 float builtin_l2f(s8 a)
2394 float f = (float) a;
2400 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2403 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2404 double builtin_l2d(s8 a)
2407 double d = (double) a;
2413 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2416 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2417 s4 builtin_f2i(float a)
2421 i = builtin_d2i((double) a);
2432 if (a < (-2147483648))
2433 return (-2147483648);
2436 f = copysignf((float) 1.0, a);
2439 return (-2147483648); */
2441 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2444 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2445 s8 builtin_f2l(float a)
2449 l = builtin_d2l((double) a);
2456 if (a > 9223372036854775807L)
2457 return 9223372036854775807L;
2458 if (a < (-9223372036854775808L))
2459 return (-9223372036854775808L);
2464 f = copysignf((float) 1.0, a);
2466 return 9223372036854775807L;
2467 return (-9223372036854775808L); */
2469 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2472 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2473 s4 builtin_d2i(double a)
2478 if (a >= 2147483647)
2480 if (a <= (-2147483647-1))
2481 return (-2147483647-1);
2486 d = copysign(1.0, a);
2489 return (-2147483647-1);
2491 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2494 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2495 s8 builtin_d2l(double a)
2500 if (a >= 9223372036854775807LL)
2501 return 9223372036854775807LL;
2502 if (a <= (-9223372036854775807LL-1))
2503 return (-9223372036854775807LL-1);
2508 d = copysign(1.0, a);
2510 return 9223372036854775807LL;
2511 return (-9223372036854775807LL-1);
2513 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2516 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2517 double builtin_f2d(float a)
2519 if (finitef(a)) return (double) a;
2522 return longBitsToDouble(DBL_NAN);
2524 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2528 float builtin_d2f(double a)
2534 return intBitsToFloat(FLT_NAN);
2536 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2539 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2542 /* builtin_arraycopy ***********************************************************
2544 Builtin for java.lang.System.arraycopy.
2546 ATTENTION: This builtin function returns a boolean value to signal
2547 the ICMD_BUILTIN if there was an exception.
2549 *******************************************************************************/
2551 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2552 java_arrayheader *dest, s4 destStart, s4 len)
2554 arraydescriptor *sdesc;
2555 arraydescriptor *ddesc;
2558 if ((src == NULL) || (dest == NULL)) {
2559 exceptions_throw_nullpointerexception();
2563 sdesc = src->objheader.vftbl->arraydesc;
2564 ddesc = dest->objheader.vftbl->arraydesc;
2566 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2567 exceptions_throw_arraystoreexception();
2571 /* we try to throw exception with the same message as SUN does */
2573 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2574 (srcStart + len < 0) || (srcStart + len > src->size) ||
2575 (destStart + len < 0) || (destStart + len > dest->size)) {
2576 exceptions_throw_arrayindexoutofboundsexception();
2580 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2581 /* We copy primitive values or references of exactly the same type */
2583 s4 dataoffset = sdesc->dataoffset;
2584 s4 componentsize = sdesc->componentsize;
2586 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2587 ((u1 *) src) + dataoffset + componentsize * srcStart,
2588 (size_t) len * componentsize);
2591 /* We copy references of different type */
2593 java_objectarray *oas = (java_objectarray *) src;
2594 java_objectarray *oad = (java_objectarray *) dest;
2596 if (destStart <= srcStart) {
2597 for (i = 0; i < len; i++) {
2598 java_objectheader *o = oas->data[srcStart + i];
2600 if (!builtin_canstore(oad, o))
2603 oad->data[destStart + i] = o;
2607 /* XXX this does not completely obey the specification!
2608 If an exception is thrown only the elements above the
2609 current index have been copied. The specification
2610 requires that only the elements *below* the current
2611 index have been copied before the throw. */
2613 for (i = len - 1; i >= 0; i--) {
2614 java_objectheader *o = oas->data[srcStart + i];
2616 if (!builtin_canstore(oad, o))
2619 oad->data[destStart + i] = o;
2628 /* builtin_nanotime ************************************************************
2630 Return the current time in nanoseconds.
2632 *******************************************************************************/
2634 s8 builtin_nanotime(void)
2639 if (gettimeofday(&tv, NULL) == -1)
2640 vm_abort("gettimeofday failed: %s", strerror(errno));
2642 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2644 return usecs * 1000;
2648 /* builtin_currenttimemillis ***************************************************
2650 Return the current time in milliseconds.
2652 *******************************************************************************/
2654 s8 builtin_currenttimemillis(void)
2658 msecs = builtin_nanotime() / 1000 / 1000;
2664 /* builtin_clone ***************************************************************
2666 Function for cloning objects or arrays.
2668 *******************************************************************************/
2670 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2672 arraydescriptor *ad;
2673 java_arrayheader *ah;
2676 java_objectheader *co; /* cloned object header */
2678 /* get the array descriptor */
2680 ad = o->vftbl->arraydesc;
2682 /* we are cloning an array */
2685 ah = (java_arrayheader *) o;
2687 size = ad->dataoffset + ad->componentsize * ah->size;
2689 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2694 MCOPY(co, o, u1, size);
2696 #if defined(ENABLE_GC_CACAO)
2697 heap_init_objectheader(co, size);
2700 #if defined(ENABLE_THREADS)
2701 lock_init_object_lock(co);
2707 /* we are cloning a non-array */
2709 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2710 exceptions_throw_clonenotsupportedexception();
2714 /* get the class of the object */
2716 c = o->vftbl->class;
2718 /* create new object */
2720 co = builtin_new(c);
2725 MCOPY(co, o, u1, c->instancesize);
2727 #if defined(ENABLE_GC_CACAO)
2728 heap_init_objectheader(co, c->instancesize);
2731 #if defined(ENABLE_THREADS)
2732 lock_init_object_lock(co);
2738 #if defined(ENABLE_VMLOG)
2740 #include <vmlog_cacao.c>
2745 * These are local overrides for various environment variables in Emacs.
2746 * Please do not remove this and leave it at the end of the file, where
2747 * Emacs will automagically detect them.
2748 * ---------------------------------------------------------------------
2751 * indent-tabs-mode: t
2755 * vim:noexpandtab:sw=4:ts=4: