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 8044 2007-06-07 19:24:35Z 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"
74 #include "vm/jit/patcher.h"
76 #include "vmcore/class.h"
77 #include "vmcore/loader.h"
78 #include "vmcore/options.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 */
172 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
173 /* parse the descriptor, builtin is always static (no `this' pointer) */
175 bte->md = descriptor_pool_parse_method_descriptor(descpool,
180 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
181 bte->md = descriptor_pool_parse_method_descriptor(descpool,
186 for (bte = builtintable_function; bte->fp != NULL; bte++) {
187 bte->md = descriptor_pool_parse_method_descriptor(descpool,
192 /* release dump area */
194 dump_release(dumpsize);
200 /* builtintable_comparator *****************************************************
202 qsort comparator for the automatic builtin table.
204 *******************************************************************************/
206 static int builtintable_comparator(const void *a, const void *b)
208 builtintable_entry *bte1;
209 builtintable_entry *bte2;
211 bte1 = (builtintable_entry *) a;
212 bte2 = (builtintable_entry *) b;
214 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
218 /* builtintable_sort_automatic *************************************************
220 Sorts the automatic builtin table.
222 *******************************************************************************/
224 static void builtintable_sort_automatic(void)
228 /* calculate table size statically (`- 1' comment see builtintable.inc) */
230 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
232 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
233 builtintable_comparator);
237 /* builtin_init ****************************************************************
239 Initialize the global table of builtin functions.
241 *******************************************************************************/
243 bool builtin_init(void)
245 /* initialize the builtin tables */
247 if (!builtintable_init())
250 /* sort builtin tables */
252 builtintable_sort_automatic();
258 /* builtintable_get_internal ***************************************************
260 Finds an entry in the builtintable for internal functions and
261 returns the a pointer to the structure.
263 *******************************************************************************/
265 builtintable_entry *builtintable_get_internal(functionptr fp)
267 builtintable_entry *bte;
269 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
278 /* builtintable_get_automatic **************************************************
280 Finds an entry in the builtintable for functions which are replaced
281 automatically and returns the a pointer to the structure.
283 *******************************************************************************/
285 builtintable_entry *builtintable_get_automatic(s4 opcode)
287 builtintable_entry *first;
288 builtintable_entry *last;
289 builtintable_entry *middle;
293 /* calculate table size statically (`- 1' comment see builtintable.inc) */
295 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
297 first = builtintable_automatic;
298 last = builtintable_automatic + entries;
300 while (entries > 0) {
302 middle = first + half;
304 if (middle->opcode < opcode) {
311 return (first != last ? first : NULL);
315 /* builtintable_replace_function ***********************************************
319 *******************************************************************************/
321 #if defined(ENABLE_JIT)
322 bool builtintable_replace_function(void *iptr_)
325 builtintable_entry *bte;
328 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
330 /* get name and descriptor of the function */
333 case ICMD_INVOKESTATIC:
334 /* The instruction MUST be resolved, otherwise we run into
335 lazy loading troubles. Anyway, we should/can only replace
336 very VM-close functions. */
338 if (INSTRUCTION_IS_UNRESOLVED(iptr))
341 mr = iptr->sx.s23.s3.fmiref;
348 /* search the function table */
350 for (bte = builtintable_function; bte->fp != NULL; bte++) {
351 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
352 (mr->name == bte->name) &&
353 (mr->descriptor == bte->descriptor)) {
355 /* set the values in the instruction */
357 iptr->opc = bte->opcode;
358 iptr->sx.s23.s3.bte = bte;
359 if (bte->checkexception)
360 iptr->flags.bits |= INS_FLAG_CHECK;
362 iptr->flags.bits &= ~INS_FLAG_CHECK;
370 #endif /* defined(ENABLE_JIT) */
373 /*****************************************************************************
375 *****************************************************************************/
377 /* builtin_instanceof **********************************************************
379 Checks if an object is an instance of some given class (or subclass
380 of that class). If class is an interface, checks if the interface
383 Return value: 1 ... o is an instance of class or implements the interface
384 0 ... otherwise or if o == NULL
386 *******************************************************************************/
388 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
393 return class_isanysubclass(o->vftbl->class, class);
398 /* builtin_checkcast ***********************************************************
400 The same as builtin_instanceof except that 1 is returned when o ==
403 *******************************************************************************/
405 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
410 if (class_isanysubclass(o->vftbl->class, class))
417 /* builtin_descriptorscompatible ***********************************************
419 Checks if two array type descriptors are assignment compatible
421 Return value: 1 ... target = desc is possible
424 *******************************************************************************/
426 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
427 arraydescriptor *target)
432 if (desc->arraytype != target->arraytype)
435 if (desc->arraytype != ARRAYTYPE_OBJECT)
438 /* {both arrays are arrays of references} */
440 if (desc->dimension == target->dimension) {
441 /* an array which contains elements of interface types is
442 allowed to be casted to Object (JOWENN)*/
444 if ((desc->elementvftbl->baseval < 0) &&
445 (target->elementvftbl->baseval == 1))
448 return class_isanysubclass(desc->elementvftbl->class,
449 target->elementvftbl->class);
452 if (desc->dimension < target->dimension)
455 /* {desc has higher dimension than target} */
457 return class_isanysubclass(pseudo_class_Arraystub,
458 target->elementvftbl->class);
462 /* builtin_arraycheckcast ******************************************************
464 Checks if an object is really a subtype of the requested array
465 type. The object has to be an array to begin with. For simple
466 arrays (int, short, double, etc.) the types have to match exactly.
467 For arrays of objects, the type of elements in the array has to be
468 a subtype (or the same type) of the requested element type. For
469 arrays of arrays (which in turn can again be arrays of arrays), the
470 types at the lowest level have to satisfy the corresponding sub
473 *******************************************************************************/
475 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
477 arraydescriptor *desc;
482 desc = o->vftbl->arraydesc;
487 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
491 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
496 return builtin_arraycheckcast(o, targetclass);
500 /* builtin_throw_exception *****************************************************
502 Sets the exceptionptr with the thrown exception and prints some
503 debugging information. Called from asm_vm_call_method.
505 *******************************************************************************/
507 void *builtin_throw_exception(java_objectheader *xptr)
510 java_lang_Throwable *t;
516 t = (java_lang_Throwable *) xptr;
518 /* calculate message length */
520 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
524 utf_bytes(xptr->vftbl->class->name);
525 if (t->detailMessage) {
526 logtextlen += strlen(": ") +
527 u2_utflength(t->detailMessage->value->data
528 + t->detailMessage->offset,
529 t->detailMessage->count);
533 logtextlen += strlen("(nil)");
536 /* allocate memory */
538 dumpsize = dump_size();
540 logtext = DMNEW(char, logtextlen);
542 strcpy(logtext, "Builtin exception thrown: ");
545 utf_cat_classname(logtext, xptr->vftbl->class->name);
547 if (t->detailMessage) {
550 buf = javastring_tochar((java_objectheader *) t->detailMessage);
551 strcat(logtext, ": ");
552 strcat(logtext, buf);
553 MFREE(buf, char, strlen(buf) + 1);
557 strcat(logtext, "(nil)");
564 dump_release(dumpsize);
566 #endif /* !defined(NDEBUG) */
568 /* actually set the exception */
570 exceptions_set_exception(xptr);
572 /* Return a NULL pointer. This is required for vm_call_method to
573 check for an exception. This is for convenience. */
579 /* builtin_canstore ************************************************************
581 Checks, if an object can be stored in an array.
583 Return value: 1 ... possible
584 0 ... otherwise (throws an ArrayStoreException)
586 *******************************************************************************/
588 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
590 arraydescriptor *desc;
591 arraydescriptor *valuedesc;
592 vftbl_t *componentvftbl;
595 castinfo classvalues;
601 /* The following is guaranteed (by verifier checks):
603 * *) oa->...vftbl->arraydesc != NULL
604 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
605 * *) o->vftbl is not an interface vftbl
608 desc = oa->header.objheader.vftbl->arraydesc;
609 componentvftbl = desc->componentvftbl;
610 valuevftbl = o->vftbl;
611 valuedesc = valuevftbl->arraydesc;
613 if ((desc->dimension - 1) == 0) {
614 /* {oa is a one-dimensional array} */
615 /* {oa is an array of references} */
617 if (valuevftbl == componentvftbl)
620 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
622 base = classvalues.super_baseval;
625 /* an array of interface references */
627 result = ((valuevftbl->interfacetablelength > -base) &&
628 (valuevftbl->interfacetable[base] != NULL));
631 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
632 <= (unsigned) classvalues.super_diffval);
635 else if (valuedesc == NULL) {
636 /* {oa has dimension > 1} */
637 /* {componentvftbl->arraydesc != NULL} */
639 /* check if o is an array */
644 /* {o is an array} */
646 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
649 /* if not possible, throw an exception */
652 exceptions_throw_arraystoreexception();
660 /* This is an optimized version where a is guaranteed to be one-dimensional */
661 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
663 arraydescriptor *desc;
664 vftbl_t *elementvftbl;
668 castinfo classvalues;
672 /* The following is guaranteed (by verifier checks):
674 * *) a->...vftbl->arraydesc != NULL
675 * *) a->...vftbl->arraydesc->elementvftbl != NULL
676 * *) a->...vftbl->arraydesc->dimension == 1
677 * *) o->vftbl is not an interface vftbl
680 desc = a->header.objheader.vftbl->arraydesc;
681 elementvftbl = desc->elementvftbl;
682 valuevftbl = o->vftbl;
684 /* {a is a one-dimensional array} */
686 if (valuevftbl == elementvftbl)
689 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
691 if ((base = classvalues.super_baseval) <= 0)
692 /* an array of interface references */
693 return (valuevftbl->interfacetablelength > -base &&
694 valuevftbl->interfacetable[base] != NULL);
696 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
697 <= (unsigned) classvalues.super_diffval;
703 /* This is an optimized version where a is guaranteed to be a
704 * one-dimensional array of a class type */
705 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
707 vftbl_t *elementvftbl;
710 castinfo classvalues;
714 /* The following is guaranteed (by verifier checks):
716 * *) a->...vftbl->arraydesc != NULL
717 * *) a->...vftbl->arraydesc->elementvftbl != NULL
718 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
719 * *) a->...vftbl->arraydesc->dimension == 1
720 * *) o->vftbl is not an interface vftbl
723 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
724 valuevftbl = o->vftbl;
726 /* {a is a one-dimensional array} */
728 if (valuevftbl == elementvftbl)
731 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
733 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
734 <= (unsigned) classvalues.super_diffval;
740 /* builtin_new *****************************************************************
742 Creates a new instance of class c on the heap.
744 Return value: pointer to the object or NULL if no memory is
747 *******************************************************************************/
749 java_objectheader *builtin_new(classinfo *c)
751 java_objectheader *o;
752 #if defined(ENABLE_RT_TIMING)
753 struct timespec time_start, time_end;
755 #if defined(ENABLE_CYCLES_STATS)
756 u8 cycles_start, cycles_end;
759 RT_TIMING_GET_TIME(time_start);
760 CYCLES_STATS_GET(cycles_start);
762 /* is the class loaded */
764 assert(c->state & CLASS_LOADED);
766 /* check if we can instantiate this class */
768 if (c->flags & ACC_ABSTRACT) {
769 exceptions_throw_instantiationerror(c);
773 /* is the class linked */
775 if (!(c->state & CLASS_LINKED))
779 if (!(c->state & CLASS_INITIALIZED)) {
782 log_message_class("Initialize class (from builtin_new): ", c);
785 if (!initialize_class(c))
789 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
797 #if defined(ENABLE_THREADS)
798 lock_init_object_lock(o);
801 CYCLES_STATS_GET(cycles_end);
802 RT_TIMING_GET_TIME(time_end);
804 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
805 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
811 /* builtin_newarray ************************************************************
813 Creates an array with the given vftbl on the heap. This function
814 takes as class argument an array class.
816 Return value: pointer to the array or NULL if no memory is available
818 *******************************************************************************/
820 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
822 arraydescriptor *desc;
827 #if defined(ENABLE_RT_TIMING)
828 struct timespec time_start, time_end;
831 RT_TIMING_GET_TIME(time_start);
833 desc = arrayclass->vftbl->arraydesc;
834 dataoffset = desc->dataoffset;
835 componentsize = desc->componentsize;
838 exceptions_throw_negativearraysizeexception();
842 actualsize = dataoffset + size * componentsize;
844 /* check for overflow */
846 if (((u4) actualsize) < ((u4) size)) {
847 exceptions_throw_outofmemoryerror();
851 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
856 a->objheader.vftbl = arrayclass->vftbl;
858 #if defined(ENABLE_THREADS)
859 lock_init_object_lock(&a->objheader);
864 RT_TIMING_GET_TIME(time_end);
865 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
871 /* builtin_anewarray ***********************************************************
873 Creates an array of references to the given class type on the heap.
875 Return value: pointer to the array or NULL if no memory is
878 *******************************************************************************/
880 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
882 classinfo *arrayclass;
884 /* is class loaded */
886 assert(componentclass->state & CLASS_LOADED);
888 /* is class linked */
890 if (!(componentclass->state & CLASS_LINKED))
891 if (!link_class(componentclass))
894 arrayclass = class_array_of(componentclass, true);
899 return (java_objectarray *) builtin_newarray(size, arrayclass);
903 /* builtin_newarray_boolean ****************************************************
905 Creates an array of bytes on the heap. The array is designated as
906 an array of booleans (important for casts)
908 Return value: pointer to the array or NULL if no memory is
911 *******************************************************************************/
913 java_booleanarray *builtin_newarray_boolean(s4 size)
915 return (java_booleanarray *)
916 builtin_newarray(size,
917 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
921 /* builtin_newarray_byte *******************************************************
923 Creates an array of 8 bit Integers on the heap.
925 Return value: pointer to the array or NULL if no memory is
928 *******************************************************************************/
930 java_bytearray *builtin_newarray_byte(s4 size)
932 return (java_bytearray *)
933 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
937 /* builtin_newarray_char *******************************************************
939 Creates an array of characters on the heap.
941 Return value: pointer to the array or NULL if no memory is
944 *******************************************************************************/
946 java_chararray *builtin_newarray_char(s4 size)
948 return (java_chararray *)
949 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
953 /* builtin_newarray_short ******************************************************
955 Creates an array of 16 bit Integers on the heap.
957 Return value: pointer to the array or NULL if no memory is
960 *******************************************************************************/
962 java_shortarray *builtin_newarray_short(s4 size)
964 return (java_shortarray *)
965 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
969 /* builtin_newarray_int ********************************************************
971 Creates an array of 32 bit Integers on the heap.
973 Return value: pointer to the array or NULL if no memory is
976 *******************************************************************************/
978 java_intarray *builtin_newarray_int(s4 size)
980 return (java_intarray *)
981 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
985 /* builtin_newarray_long *******************************************************
987 Creates an array of 64 bit Integers on the heap.
989 Return value: pointer to the array or NULL if no memory is
992 *******************************************************************************/
994 java_longarray *builtin_newarray_long(s4 size)
996 return (java_longarray *)
997 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1001 /* builtin_newarray_float ******************************************************
1003 Creates an array of 32 bit IEEE floats on the heap.
1005 Return value: pointer to the array or NULL if no memory is
1008 *******************************************************************************/
1010 java_floatarray *builtin_newarray_float(s4 size)
1012 return (java_floatarray *)
1013 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1017 /* builtin_newarray_double *****************************************************
1019 Creates an array of 64 bit IEEE floats on the heap.
1021 Return value: pointer to the array or NULL if no memory is
1024 *******************************************************************************/
1026 java_doublearray *builtin_newarray_double(s4 size)
1028 return (java_doublearray *)
1029 builtin_newarray(size,
1030 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1034 /* builtin_multianewarray_intern ***********************************************
1036 Creates a multi-dimensional array on the heap. The dimensions are
1037 passed in an array of longs.
1040 n............number of dimensions to create
1041 arrayvftbl...vftbl of the array class
1042 dims.........array containing the size of each dimension to create
1044 Return value: pointer to the array or NULL if no memory is
1047 ******************************************************************************/
1049 static java_arrayheader *builtin_multianewarray_intern(int n,
1050 classinfo *arrayclass,
1054 java_arrayheader *a;
1055 classinfo *componentclass;
1058 /* create this dimension */
1060 size = (s4) dims[0];
1061 a = builtin_newarray(size, arrayclass);
1066 /* if this is the last dimension return */
1071 /* get the class of the components to create */
1073 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1075 /* The verifier guarantees that the dimension count is in the range. */
1077 /* create the component arrays */
1079 for (i = 0; i < size; i++) {
1080 java_arrayheader *ea =
1081 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1082 /* we save an s4 to a s8 slot, 8-byte aligned */
1084 builtin_multianewarray_intern(n, componentclass, dims + 2);
1086 builtin_multianewarray_intern(n, componentclass, dims + 1);
1092 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1099 /* builtin_multianewarray ******************************************************
1101 Wrapper for builtin_multianewarray_intern which checks all
1102 dimensions before we start allocating.
1104 ******************************************************************************/
1106 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1112 /* check all dimensions before doing anything */
1114 for (i = 0; i < n; i++) {
1115 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1116 /* we save an s4 to a s8 slot, 8-byte aligned */
1117 size = (s4) dims[i * 2];
1119 size = (s4) dims[i];
1123 exceptions_throw_negativearraysizeexception();
1128 /* now call the real function */
1130 return builtin_multianewarray_intern(n, arrayclass, dims);
1134 /*****************************************************************************
1137 Various functions for printing a message at method entry or exit (for
1140 *****************************************************************************/
1142 #if !defined(NDEBUG)
1143 static s4 methodindent = 0;
1144 static u4 callcount = 0;
1146 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1156 #if defined(ENABLE_DEBUG_FILTER)
1157 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1160 #if defined(ENABLE_VMLOG)
1164 if (opt_verbosecall && indent)
1167 /* calculate message length */
1171 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1174 logtextlen = strlen("Some Throwable");
1177 logtextlen += strlen(" thrown in ");
1181 utf_bytes(m->class->name) +
1183 utf_bytes(m->name) +
1184 utf_bytes(m->descriptor) +
1185 strlen("(NOSYNC,NATIVE");
1187 #if SIZEOF_VOID_P == 8
1189 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1191 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1194 if (m->class->sourcefile == NULL)
1195 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1197 logtextlen += utf_bytes(m->class->sourcefile);
1199 logtextlen += strlen(":65536)");
1203 logtextlen += strlen("call_java_method");
1206 logtextlen += strlen("0");
1208 /* allocate memory */
1210 dumpsize = dump_size();
1212 logtext = DMNEW(char, logtextlen);
1215 strcpy(logtext, "Exception ");
1216 utf_cat_classname(logtext, xptr->vftbl->class->name);
1219 strcpy(logtext, "Some Throwable");
1222 strcat(logtext, " thrown in ");
1225 utf_cat_classname(logtext, m->class->name);
1226 strcat(logtext, ".");
1227 utf_cat(logtext, m->name);
1228 utf_cat(logtext, m->descriptor);
1230 if (m->flags & ACC_SYNCHRONIZED)
1231 strcat(logtext, "(SYNC");
1233 strcat(logtext, "(NOSYNC");
1235 if (m->flags & ACC_NATIVE) {
1236 strcat(logtext, ",NATIVE");
1240 #if SIZEOF_VOID_P == 8
1241 sprintf(logtext + strlen(logtext),
1242 ")(0x%016lx) at position 0x%016lx",
1243 (ptrint) code->entrypoint, (ptrint) pos);
1245 sprintf(logtext + strlen(logtext),
1246 ")(0x%08x) at position 0x%08x",
1247 (ptrint) code->entrypoint, (ptrint) pos);
1252 /* XXX preliminary: This should get the actual codeinfo */
1253 /* in which the exception happened. */
1256 #if SIZEOF_VOID_P == 8
1257 sprintf(logtext + strlen(logtext),
1258 ")(0x%016lx) at position 0x%016lx (",
1259 (ptrint) code->entrypoint, (ptrint) pos);
1261 sprintf(logtext + strlen(logtext),
1262 ")(0x%08x) at position 0x%08x (",
1263 (ptrint) code->entrypoint, (ptrint) pos);
1266 if (m->class->sourcefile == NULL)
1267 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1269 utf_cat(logtext, m->class->sourcefile);
1271 sprintf(logtext + strlen(logtext), ":%d)", 0);
1275 strcat(logtext, "call_java_method");
1279 /* release memory */
1281 dump_release(dumpsize);
1285 #endif /* !defined(NDEBUG) */
1288 /* builtin_print_argument ******************************************************
1290 Prints arguments and return values for the call trace.
1292 *******************************************************************************/
1294 #if !defined(NDEBUG)
1295 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1296 typedesc *paramtype, s8 value)
1299 java_objectheader *o;
1304 switch (paramtype->type) {
1307 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1312 #if SIZEOF_VOID_P == 4
1313 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1315 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1321 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1326 #if SIZEOF_VOID_P == 4
1327 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1329 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1334 #if SIZEOF_VOID_P == 4
1335 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1337 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1340 /* cast to java.lang.Object */
1342 o = (java_objectheader *) (ptrint) value;
1344 /* check return argument for java.lang.Class or java.lang.String */
1347 if (o->vftbl->class == class_java_lang_String) {
1348 /* get java.lang.String object and the length of the
1351 u = javastring_toutf(o, false);
1353 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1355 /* realloc memory for string length */
1357 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1360 /* convert to utf8 string and strcat it to the logtext */
1362 strcat(logtext, " (String = \"");
1363 utf_cat(logtext, u);
1364 strcat(logtext, "\")");
1367 if (o->vftbl->class == class_java_lang_Class) {
1368 /* if the object returned is a java.lang.Class
1369 cast it to classinfo structure and get the name
1372 c = (classinfo *) o;
1377 /* if the object returned is not a java.lang.String or
1378 a java.lang.Class just print the name of the class */
1380 u = o->vftbl->class->name;
1383 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1385 /* realloc memory for string length */
1387 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1390 /* strcat to the logtext */
1392 strcat(logtext, " (Class = \"");
1393 utf_cat_classname(logtext, u);
1394 strcat(logtext, "\")");
1401 #endif /* !defined(NDEBUG) */
1403 /* builtin_verbosecall_enter ***************************************************
1405 Print method call with arguments for -verbose:call.
1407 *******************************************************************************/
1409 #if !defined(NDEBUG)
1411 #ifdef TRACE_ARGS_NUM
1412 void builtin_verbosecall_enter(s8 a0, s8 a1,
1413 # if TRACE_ARGS_NUM >= 4
1416 # if TRACE_ARGS_NUM >= 6
1419 # if TRACE_ARGS_NUM == 8
1431 #if defined(ENABLE_DEBUG_FILTER)
1432 if (! show_filters_test_verbosecall_enter(m)) return;
1435 #if defined(ENABLE_VMLOG)
1436 vmlog_cacao_enter_method(m);
1442 /* calculate message length */
1445 strlen("4294967295 ") +
1446 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1448 strlen("called: ") +
1449 utf_bytes(m->class->name) +
1451 utf_bytes(m->name) +
1452 utf_bytes(m->descriptor);
1454 /* Actually it's not possible to have all flags printed, but:
1459 strlen(" PRIVATE") +
1460 strlen(" PROTECTED") +
1463 strlen(" SYNCHRONIZED") +
1464 strlen(" VOLATILE") +
1465 strlen(" TRANSIENT") +
1467 strlen(" INTERFACE") +
1468 strlen(" ABSTRACT");
1470 /* add maximal argument length */
1474 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1475 strlen("...(255)") +
1478 /* allocate memory */
1480 dumpsize = dump_size();
1482 logtext = DMNEW(char, logtextlen);
1486 sprintf(logtext, "%10d ", callcount);
1487 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1489 pos = strlen(logtext);
1491 for (i = 0; i < methodindent; i++)
1492 logtext[pos++] = '\t';
1494 strcpy(logtext + pos, "called: ");
1496 utf_cat_classname(logtext, m->class->name);
1497 strcat(logtext, ".");
1498 utf_cat(logtext, m->name);
1499 utf_cat(logtext, m->descriptor);
1501 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1502 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1503 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1504 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1505 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1506 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1507 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1508 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1509 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1510 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1511 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1513 strcat(logtext, "(");
1515 if (md->paramcount >= 1) {
1516 logtext = builtin_print_argument(logtext, &logtextlen,
1517 &md->paramtypes[0], a0);
1520 if (md->paramcount >= 2) {
1521 strcat(logtext, ", ");
1523 logtext = builtin_print_argument(logtext, &logtextlen,
1524 &md->paramtypes[1], a1);
1527 #if TRACE_ARGS_NUM >= 4
1528 if (md->paramcount >= 3) {
1529 strcat(logtext, ", ");
1531 logtext = builtin_print_argument(logtext, &logtextlen,
1532 &md->paramtypes[2], a2);
1535 if (md->paramcount >= 4) {
1536 strcat(logtext, ", ");
1538 logtext = builtin_print_argument(logtext, &logtextlen,
1539 &md->paramtypes[3], a3);
1543 #if TRACE_ARGS_NUM >= 6
1544 if (md->paramcount >= 5) {
1545 strcat(logtext, ", ");
1547 logtext = builtin_print_argument(logtext, &logtextlen,
1548 &md->paramtypes[4], a4);
1551 if (md->paramcount >= 6) {
1552 strcat(logtext, ", ");
1554 logtext = builtin_print_argument(logtext, &logtextlen,
1555 &md->paramtypes[5], a5);
1559 #if TRACE_ARGS_NUM == 8
1560 if (md->paramcount >= 7) {
1561 strcat(logtext, ", ");
1563 logtext = builtin_print_argument(logtext, &logtextlen,
1564 &md->paramtypes[6], a6);
1567 if (md->paramcount >= 8) {
1568 strcat(logtext, ", ");
1570 logtext = builtin_print_argument(logtext, &logtextlen,
1571 &md->paramtypes[7], a7);
1575 if (md->paramcount > 8) {
1576 sprintf(logtext + strlen(logtext), ", ...(%d)",
1577 md->paramcount - TRACE_ARGS_NUM);
1580 strcat(logtext, ")");
1584 /* release memory */
1586 dump_release(dumpsize);
1592 #endif /* !defined(NDEBUG) */
1595 /* builtin_verbosecall_exit ****************************************************
1597 Print method exit for -verbose:call.
1599 *******************************************************************************/
1601 #if !defined(NDEBUG)
1602 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1612 #if defined(ENABLE_DEBUG_FILTER)
1613 if (! show_filters_test_verbosecall_exit(m)) return;
1616 #if defined(ENABLE_VMLOG)
1617 vmlog_cacao_leave_method(m);
1623 /* calculate message length */
1626 strlen("4294967295 ") +
1627 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1629 strlen("finished: ") +
1630 utf_bytes(m->class->name) +
1632 utf_bytes(m->name) +
1633 utf_bytes(m->descriptor) +
1634 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1636 /* add maximal argument length */
1638 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1640 /* allocate memory */
1642 dumpsize = dump_size();
1644 logtext = DMNEW(char, logtextlen);
1646 /* outdent the log message */
1651 log_text("WARNING: unmatched methodindent--");
1653 /* generate the message */
1655 sprintf(logtext, " ");
1656 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1658 pos = strlen(logtext);
1660 for (i = 0; i < methodindent; i++)
1661 logtext[pos++] = '\t';
1663 strcpy(logtext + pos, "finished: ");
1664 utf_cat_classname(logtext, m->class->name);
1665 strcat(logtext, ".");
1666 utf_cat(logtext, m->name);
1667 utf_cat(logtext, m->descriptor);
1669 if (!IS_VOID_TYPE(md->returntype.type)) {
1670 strcat(logtext, "->");
1672 switch (md->returntype.type) {
1689 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1694 /* release memory */
1696 dump_release(dumpsize);
1699 #endif /* !defined(NDEBUG) */
1702 #if defined(ENABLE_CYCLES_STATS)
1703 void builtin_print_cycles_stats(FILE *file)
1705 fprintf(file,"builtin cylce count statistics:\n");
1707 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1708 CYCLES_STATS_PRINT(builtin_new ,file);
1712 #endif /* defined(ENABLE_CYCLES_STATS) */
1715 /*****************************************************************************
1716 MISCELLANEOUS HELPER FUNCTIONS
1717 *****************************************************************************/
1721 /*********** Functions for integer divisions *****************************
1723 On some systems (eg. DEC ALPHA), integer division is not supported by the
1724 CPU. These helper functions implement the missing functionality.
1726 ******************************************************************************/
1728 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1729 s4 builtin_idiv(s4 a, s4 b)
1738 s4 builtin_irem(s4 a, s4 b)
1746 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1749 /* functions for long arithmetics **********************************************
1751 On systems where 64 bit Integers are not supported by the CPU,
1752 these functions are needed.
1754 ******************************************************************************/
1756 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1757 s8 builtin_ladd(s8 a, s8 b)
1770 s8 builtin_lsub(s8 a, s8 b)
1783 s8 builtin_lneg(s8 a)
1795 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1798 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1799 s8 builtin_lmul(s8 a, s8 b)
1811 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1814 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1815 s8 builtin_ldiv(s8 a, s8 b)
1828 s8 builtin_lrem(s8 a, s8 b)
1840 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1843 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1844 s8 builtin_lshl(s8 a, s4 b)
1857 s8 builtin_lshr(s8 a, s4 b)
1870 s8 builtin_lushr(s8 a, s4 b)
1875 c = ((u8) a) >> (b & 63);
1882 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1885 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1886 s8 builtin_land(s8 a, s8 b)
1899 s8 builtin_lor(s8 a, s8 b)
1912 s8 builtin_lxor(s8 a, s8 b)
1924 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1927 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1928 s4 builtin_lcmp(s8 a, s8 b)
1942 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1945 /* functions for unsupported floating instructions ****************************/
1947 /* used to convert FLT_xxx defines into float values */
1949 static inline float intBitsToFloat(s4 i)
1958 /* used to convert DBL_xxx defines into double values */
1960 static inline float longBitsToDouble(s8 l)
1970 float builtin_fadd(float a, float b)
1972 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1973 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1984 if (copysignf(1.0, a) == copysignf(1.0, b))
1987 return intBitsToFloat(FLT_NAN);
1993 float builtin_fsub(float a, float b)
1995 return builtin_fadd(a, builtin_fneg(b));
1999 float builtin_fmul(float a, float b)
2001 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2002 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2004 if (finitef(b)) return a * b;
2006 if (a == 0) return intBitsToFloat(FLT_NAN);
2007 else return copysignf(b, copysignf(1.0, b)*a);
2012 if (b == 0) return intBitsToFloat(FLT_NAN);
2013 else return copysignf(a, copysignf(1.0, a)*b);
2016 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2022 /* builtin_ddiv ****************************************************************
2024 Implementation as described in VM Spec.
2026 *******************************************************************************/
2028 float builtin_fdiv(float a, float b)
2032 /* If neither value1' nor value2' is NaN, the sign of the result */
2033 /* is positive if both values have the same sign, negative if the */
2034 /* values have different signs. */
2040 /* If either value1' or value2' is NaN, the result is NaN. */
2042 return intBitsToFloat(FLT_NAN);
2045 /* Division of a finite value by an infinity results in a */
2046 /* signed zero, with the sign-producing rule just given. */
2048 /* is sign equal? */
2050 if (copysignf(1.0, a) == copysignf(1.0, b))
2059 /* If either value1' or value2' is NaN, the result is NaN. */
2061 return intBitsToFloat(FLT_NAN);
2063 } else if (finitef(b)) {
2064 /* Division of an infinity by a finite value results in a signed */
2065 /* infinity, with the sign-producing rule just given. */
2067 /* is sign equal? */
2069 if (copysignf(1.0, a) == copysignf(1.0, b))
2070 return intBitsToFloat(FLT_POSINF);
2072 return intBitsToFloat(FLT_NEGINF);
2075 /* Division of an infinity by an infinity results in NaN. */
2077 return intBitsToFloat(FLT_NAN);
2083 float builtin_fneg(float a)
2085 if (isnanf(a)) return a;
2087 if (finitef(a)) return -a;
2088 else return copysignf(a, -copysignf(1.0, a));
2091 #endif /* !SUPPORT_FLOAT */
2094 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2095 s4 builtin_fcmpl(float a, float b)
2103 if (!finitef(a) || !finitef(b)) {
2104 a = finitef(a) ? 0 : copysignf(1.0, a);
2105 b = finitef(b) ? 0 : copysignf(1.0, b);
2118 s4 builtin_fcmpg(float a, float b)
2120 if (isnanf(a)) return 1;
2121 if (isnanf(b)) return 1;
2122 if (!finitef(a) || !finitef(b)) {
2123 a = finitef(a) ? 0 : copysignf(1.0, a);
2124 b = finitef(b) ? 0 : copysignf(1.0, b);
2126 if (a > b) return 1;
2127 if (a == b) return 0;
2130 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2133 float builtin_frem(float a, float b)
2139 /* functions for unsupported double instructions ******************************/
2142 double builtin_dadd(double a, double b)
2144 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2145 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2147 if (finite(b)) return a + b;
2151 if (finite(b)) return a;
2153 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2154 else return longBitsToDouble(DBL_NAN);
2160 double builtin_dsub(double a, double b)
2162 return builtin_dadd(a, builtin_dneg(b));
2166 double builtin_dmul(double a, double b)
2168 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2169 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2171 if (finite(b)) return a * b;
2173 if (a == 0) return longBitsToDouble(DBL_NAN);
2174 else return copysign(b, copysign(1.0, b) * a);
2179 if (b == 0) return longBitsToDouble(DBL_NAN);
2180 else return copysign(a, copysign(1.0, a) * b);
2183 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2189 /* builtin_ddiv ****************************************************************
2191 Implementation as described in VM Spec.
2193 *******************************************************************************/
2195 double builtin_ddiv(double a, double b)
2199 /* If neither value1' nor value2' is NaN, the sign of the result */
2200 /* is positive if both values have the same sign, negative if the */
2201 /* values have different signs. */
2207 /* If either value1' or value2' is NaN, the result is NaN. */
2209 return longBitsToDouble(DBL_NAN);
2212 /* Division of a finite value by an infinity results in a */
2213 /* signed zero, with the sign-producing rule just given. */
2215 /* is sign equal? */
2217 if (copysign(1.0, a) == copysign(1.0, b))
2226 /* If either value1' or value2' is NaN, the result is NaN. */
2228 return longBitsToDouble(DBL_NAN);
2230 } else if (finite(b)) {
2231 /* Division of an infinity by a finite value results in a signed */
2232 /* infinity, with the sign-producing rule just given. */
2234 /* is sign equal? */
2236 if (copysign(1.0, a) == copysign(1.0, b))
2237 return longBitsToDouble(DBL_POSINF);
2239 return longBitsToDouble(DBL_NEGINF);
2242 /* Division of an infinity by an infinity results in NaN. */
2244 return longBitsToDouble(DBL_NAN);
2250 /* builtin_dneg ****************************************************************
2252 Implemented as described in VM Spec.
2254 *******************************************************************************/
2256 double builtin_dneg(double a)
2259 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2266 /* If the operand is a zero, the result is the zero of opposite */
2272 /* If the operand is an infinity, the result is the infinity of */
2273 /* opposite sign. */
2275 return copysign(a, -copysign(1.0, a));
2279 #endif /* !SUPPORT_DOUBLE */
2282 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2283 s4 builtin_dcmpl(double a, double b)
2291 if (!finite(a) || !finite(b)) {
2292 a = finite(a) ? 0 : copysign(1.0, a);
2293 b = finite(b) ? 0 : copysign(1.0, b);
2306 s4 builtin_dcmpg(double a, double b)
2314 if (!finite(a) || !finite(b)) {
2315 a = finite(a) ? 0 : copysign(1.0, a);
2316 b = finite(b) ? 0 : copysign(1.0, b);
2327 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2330 double builtin_drem(double a, double b)
2336 /* conversion operations ******************************************************/
2339 s8 builtin_i2l(s4 i)
2351 s4 builtin_l2i(s8 l)
2362 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2363 float builtin_i2f(s4 a)
2365 float f = (float) a;
2368 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2371 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2372 double builtin_i2d(s4 a)
2374 double d = (double) a;
2377 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2380 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2381 float builtin_l2f(s8 a)
2384 float f = (float) a;
2390 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2393 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2394 double builtin_l2d(s8 a)
2397 double d = (double) a;
2403 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2406 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2407 s4 builtin_f2i(float a)
2411 i = builtin_d2i((double) a);
2422 if (a < (-2147483648))
2423 return (-2147483648);
2426 f = copysignf((float) 1.0, a);
2429 return (-2147483648); */
2431 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2434 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2435 s8 builtin_f2l(float a)
2439 l = builtin_d2l((double) a);
2446 if (a > 9223372036854775807L)
2447 return 9223372036854775807L;
2448 if (a < (-9223372036854775808L))
2449 return (-9223372036854775808L);
2454 f = copysignf((float) 1.0, a);
2456 return 9223372036854775807L;
2457 return (-9223372036854775808L); */
2459 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2462 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2463 s4 builtin_d2i(double a)
2468 if (a >= 2147483647)
2470 if (a <= (-2147483647-1))
2471 return (-2147483647-1);
2476 d = copysign(1.0, a);
2479 return (-2147483647-1);
2481 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2484 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2485 s8 builtin_d2l(double a)
2490 if (a >= 9223372036854775807LL)
2491 return 9223372036854775807LL;
2492 if (a <= (-9223372036854775807LL-1))
2493 return (-9223372036854775807LL-1);
2498 d = copysign(1.0, a);
2500 return 9223372036854775807LL;
2501 return (-9223372036854775807LL-1);
2503 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2506 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2507 double builtin_f2d(float a)
2509 if (finitef(a)) return (double) a;
2512 return longBitsToDouble(DBL_NAN);
2514 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2518 float builtin_d2f(double a)
2524 return intBitsToFloat(FLT_NAN);
2526 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2529 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2532 /* builtin_arraycopy ***********************************************************
2534 Builtin for java.lang.System.arraycopy.
2536 ATTENTION: This builtin function returns a boolean value to signal
2537 the ICMD_BUILTIN if there was an exception.
2539 *******************************************************************************/
2541 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2542 java_arrayheader *dest, s4 destStart, s4 len)
2544 arraydescriptor *sdesc;
2545 arraydescriptor *ddesc;
2548 if ((src == NULL) || (dest == NULL)) {
2549 exceptions_throw_nullpointerexception();
2553 sdesc = src->objheader.vftbl->arraydesc;
2554 ddesc = dest->objheader.vftbl->arraydesc;
2556 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2557 exceptions_throw_arraystoreexception();
2561 /* we try to throw exception with the same message as SUN does */
2563 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2564 (srcStart + len < 0) || (srcStart + len > src->size) ||
2565 (destStart + len < 0) || (destStart + len > dest->size)) {
2566 exceptions_throw_arrayindexoutofboundsexception();
2570 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2571 /* We copy primitive values or references of exactly the same type */
2573 s4 dataoffset = sdesc->dataoffset;
2574 s4 componentsize = sdesc->componentsize;
2576 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2577 ((u1 *) src) + dataoffset + componentsize * srcStart,
2578 (size_t) len * componentsize);
2581 /* We copy references of different type */
2583 java_objectarray *oas = (java_objectarray *) src;
2584 java_objectarray *oad = (java_objectarray *) dest;
2586 if (destStart <= srcStart) {
2587 for (i = 0; i < len; i++) {
2588 java_objectheader *o = oas->data[srcStart + i];
2590 if (!builtin_canstore(oad, o))
2593 oad->data[destStart + i] = o;
2597 /* XXX this does not completely obey the specification!
2598 If an exception is thrown only the elements above the
2599 current index have been copied. The specification
2600 requires that only the elements *below* the current
2601 index have been copied before the throw. */
2603 for (i = len - 1; i >= 0; i--) {
2604 java_objectheader *o = oas->data[srcStart + i];
2606 if (!builtin_canstore(oad, o))
2609 oad->data[destStart + i] = o;
2618 /* builtin_nanotime ************************************************************
2620 Return the current time in nanoseconds.
2622 *******************************************************************************/
2624 s8 builtin_nanotime(void)
2629 if (gettimeofday(&tv, NULL) == -1)
2630 vm_abort("gettimeofday failed: %s", strerror(errno));
2632 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2634 return usecs * 1000;
2638 /* builtin_currenttimemillis ***************************************************
2640 Return the current time in milliseconds.
2642 *******************************************************************************/
2644 s8 builtin_currenttimemillis(void)
2648 msecs = builtin_nanotime() / 1000 / 1000;
2654 /* builtin_clone ***************************************************************
2656 Function for cloning objects or arrays.
2658 *******************************************************************************/
2660 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2662 arraydescriptor *ad;
2663 java_arrayheader *ah;
2666 java_objectheader *co; /* cloned object header */
2668 /* get the array descriptor */
2670 ad = o->vftbl->arraydesc;
2672 /* we are cloning an array */
2675 ah = (java_arrayheader *) o;
2677 size = ad->dataoffset + ad->componentsize * ah->size;
2679 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2684 MCOPY(co, o, u1, size);
2686 #if defined(ENABLE_GC_CACAO)
2687 heap_init_objectheader(co, size);
2690 #if defined(ENABLE_THREADS)
2691 lock_init_object_lock(co);
2697 /* we are cloning a non-array */
2699 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2700 exceptions_throw_clonenotsupportedexception();
2704 /* get the class of the object */
2706 c = o->vftbl->class;
2708 /* create new object */
2710 co = builtin_new(c);
2715 MCOPY(co, o, u1, c->instancesize);
2717 #if defined(ENABLE_GC_CACAO)
2718 heap_init_objectheader(co, c->instancesize);
2721 #if defined(ENABLE_THREADS)
2722 lock_init_object_lock(co);
2728 #if defined(ENABLE_VMLOG)
2730 #include <vmlog_cacao.c>
2735 * These are local overrides for various environment variables in Emacs.
2736 * Please do not remove this and leave it at the end of the file, where
2737 * Emacs will automagically detect them.
2738 * ---------------------------------------------------------------------
2741 * indent-tabs-mode: t
2745 * vim:noexpandtab:sw=4:ts=4: