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 8288 2007-08-10 15:12: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/llni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
62 #include "threads/lock-common.h"
64 #include "toolbox/logging.h"
65 #include "toolbox/util.h"
67 #include "vm/builtin.h"
68 #include "vm/cycles-stats.h"
69 #include "vm/exceptions.h"
70 #include "vm/global.h"
71 #include "vm/initialize.h"
72 #include "vm/primitive.h"
73 #include "vm/stringlocal.h"
75 #include "vm/jit/asmpart.h"
77 #include "vmcore/class.h"
78 #include "vmcore/linker.h"
79 #include "vmcore/loader.h"
80 #include "vmcore/options.h"
81 #include "vmcore/rt-timing.h"
83 #if defined(ENABLE_VMLOG)
84 #include <vmlog_cacao.h>
87 #if defined(ENABLE_DEBUG_FILTER)
88 # include "vm/jit/show.h"
91 /* include builtin tables *****************************************************/
93 #include "vm/builtintable.inc"
96 CYCLES_STATS_DECLARE(builtin_new ,100,5)
97 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
99 /* builtintable_init ***********************************************************
101 Parse the descriptors of builtin functions and create the parsed
104 *******************************************************************************/
106 static bool builtintable_init(void)
108 descriptor_pool *descpool;
110 builtintable_entry *bte;
112 /* mark start of dump memory area */
114 dumpsize = dump_size();
116 /* create a new descriptor pool */
118 descpool = descriptor_pool_new(class_java_lang_Object);
120 /* add some entries we need */
122 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
125 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
128 /* first add all descriptors to the pool */
130 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
131 /* create a utf8 string from descriptor */
133 bte->descriptor = utf_new_char(bte->cdescriptor);
135 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
136 /* release dump area */
138 dump_release(dumpsize);
144 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
145 bte->descriptor = utf_new_char(bte->cdescriptor);
147 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
148 dump_release(dumpsize);
153 for (bte = builtintable_function; bte->fp != NULL; bte++) {
154 bte->classname = utf_new_char(bte->cclassname);
155 bte->name = utf_new_char(bte->cname);
156 bte->descriptor = utf_new_char(bte->cdescriptor);
158 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
159 dump_release(dumpsize);
164 /* create the class reference table */
166 (void) descriptor_pool_create_classrefs(descpool, NULL);
168 /* allocate space for the parsed descriptors */
170 descriptor_pool_alloc_parsed_descriptors(descpool);
172 /* Now parse all descriptors. NOTE: builtin-functions are treated
173 like static methods (no `this' pointer). */
175 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
177 descriptor_pool_parse_method_descriptor(descpool,
179 ACC_STATIC | ACC_METHOD_BUILTIN,
183 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
185 descriptor_pool_parse_method_descriptor(descpool,
187 ACC_STATIC | ACC_METHOD_BUILTIN,
191 for (bte = builtintable_function; bte->fp != NULL; bte++) {
193 descriptor_pool_parse_method_descriptor(descpool,
195 ACC_STATIC | ACC_METHOD_BUILTIN,
199 /* release dump area */
201 dump_release(dumpsize);
207 /* builtintable_comparator *****************************************************
209 qsort comparator for the automatic builtin table.
211 *******************************************************************************/
213 static int builtintable_comparator(const void *a, const void *b)
215 builtintable_entry *bte1;
216 builtintable_entry *bte2;
218 bte1 = (builtintable_entry *) a;
219 bte2 = (builtintable_entry *) b;
221 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
225 /* builtintable_sort_automatic *************************************************
227 Sorts the automatic builtin table.
229 *******************************************************************************/
231 static void builtintable_sort_automatic(void)
235 /* calculate table size statically (`- 1' comment see builtintable.inc) */
237 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
239 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
240 builtintable_comparator);
244 /* builtin_init ****************************************************************
246 Initialize the global table of builtin functions.
248 *******************************************************************************/
250 bool builtin_init(void)
252 /* initialize the builtin tables */
254 if (!builtintable_init())
257 /* sort builtin tables */
259 builtintable_sort_automatic();
265 /* builtintable_get_internal ***************************************************
267 Finds an entry in the builtintable for internal functions and
268 returns the a pointer to the structure.
270 *******************************************************************************/
272 builtintable_entry *builtintable_get_internal(functionptr fp)
274 builtintable_entry *bte;
276 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
285 /* builtintable_get_automatic **************************************************
287 Finds an entry in the builtintable for functions which are replaced
288 automatically and returns the a pointer to the structure.
290 *******************************************************************************/
292 builtintable_entry *builtintable_get_automatic(s4 opcode)
294 builtintable_entry *first;
295 builtintable_entry *last;
296 builtintable_entry *middle;
300 /* calculate table size statically (`- 1' comment see builtintable.inc) */
302 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
304 first = builtintable_automatic;
305 last = builtintable_automatic + entries;
307 while (entries > 0) {
309 middle = first + half;
311 if (middle->opcode < opcode) {
318 return (first != last ? first : NULL);
322 /* builtintable_replace_function ***********************************************
326 *******************************************************************************/
328 #if defined(ENABLE_JIT)
329 bool builtintable_replace_function(void *iptr_)
332 builtintable_entry *bte;
335 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
337 /* get name and descriptor of the function */
340 case ICMD_INVOKESTATIC:
341 /* The instruction MUST be resolved, otherwise we run into
342 lazy loading troubles. Anyway, we should/can only replace
343 very VM-close functions. */
345 if (INSTRUCTION_IS_UNRESOLVED(iptr))
348 mr = iptr->sx.s23.s3.fmiref;
355 /* search the function table */
357 for (bte = builtintable_function; bte->fp != NULL; bte++) {
358 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
359 (mr->name == bte->name) &&
360 (mr->descriptor == bte->descriptor)) {
362 /* set the values in the instruction */
364 iptr->opc = bte->opcode;
365 iptr->sx.s23.s3.bte = bte;
366 if (bte->checkexception)
367 iptr->flags.bits |= INS_FLAG_CHECK;
369 iptr->flags.bits &= ~INS_FLAG_CHECK;
377 #endif /* defined(ENABLE_JIT) */
380 /*****************************************************************************
382 *****************************************************************************/
384 /* builtin_instanceof **********************************************************
386 Checks if an object is an instance of some given class (or subclass
387 of that class). If class is an interface, checks if the interface
390 Return value: 1 ... o is an instance of class or implements the interface
391 0 ... otherwise or if o == NULL
393 *******************************************************************************/
395 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
400 return class_isanysubclass(o->vftbl->class, class);
405 /* builtin_checkcast ***********************************************************
407 The same as builtin_instanceof except that 1 is returned when o ==
410 *******************************************************************************/
412 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
417 if (class_isanysubclass(o->vftbl->class, class))
424 /* builtin_descriptorscompatible ***********************************************
426 Checks if two array type descriptors are assignment compatible
428 Return value: 1 ... target = desc is possible
431 *******************************************************************************/
433 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
434 arraydescriptor *target)
439 if (desc->arraytype != target->arraytype)
442 if (desc->arraytype != ARRAYTYPE_OBJECT)
445 /* {both arrays are arrays of references} */
447 if (desc->dimension == target->dimension) {
448 /* an array which contains elements of interface types is
449 allowed to be casted to Object (JOWENN)*/
451 if ((desc->elementvftbl->baseval < 0) &&
452 (target->elementvftbl->baseval == 1))
455 return class_isanysubclass(desc->elementvftbl->class,
456 target->elementvftbl->class);
459 if (desc->dimension < target->dimension)
462 /* {desc has higher dimension than target} */
464 return class_isanysubclass(pseudo_class_Arraystub,
465 target->elementvftbl->class);
469 /* builtin_arraycheckcast ******************************************************
471 Checks if an object is really a subtype of the requested array
472 type. The object has to be an array to begin with. For simple
473 arrays (int, short, double, etc.) the types have to match exactly.
474 For arrays of objects, the type of elements in the array has to be
475 a subtype (or the same type) of the requested element type. For
476 arrays of arrays (which in turn can again be arrays of arrays), the
477 types at the lowest level have to satisfy the corresponding sub
480 *******************************************************************************/
482 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
484 arraydescriptor *desc;
489 desc = o->vftbl->arraydesc;
494 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
498 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
503 return builtin_arraycheckcast(o, targetclass);
507 /* builtin_throw_exception *****************************************************
509 Sets the exceptionptr with the thrown exception and prints some
510 debugging information. Called from asm_vm_call_method.
512 *******************************************************************************/
514 void *builtin_throw_exception(java_objectheader *xptr)
517 java_lang_Throwable *t;
524 t = (java_lang_Throwable *) xptr;
526 /* get detail message */
528 LLNI_field_get_ref(t, detailMessage, s);
530 /* calculate message length */
532 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
536 utf_bytes(xptr->vftbl->class->name);
538 logtextlen += strlen(": ") +
539 u2_utflength(LLNI_field_direct(s, value)->data
540 + LLNI_field_direct(s, offset),
541 LLNI_field_direct(s,count));
545 logtextlen += strlen("(nil)");
548 /* allocate memory */
550 dumpsize = dump_size();
552 logtext = DMNEW(char, logtextlen);
554 strcpy(logtext, "Builtin exception thrown: ");
557 utf_cat_classname(logtext, xptr->vftbl->class->name);
562 buf = javastring_tochar((java_objectheader *) s);
563 strcat(logtext, ": ");
564 strcat(logtext, buf);
565 MFREE(buf, char, strlen(buf) + 1);
569 strcat(logtext, "(nil)");
576 dump_release(dumpsize);
578 #endif /* !defined(NDEBUG) */
580 /* actually set the exception */
582 exceptions_set_exception(xptr);
584 /* Return a NULL pointer. This is required for vm_call_method to
585 check for an exception. This is for convenience. */
591 /* builtin_canstore ************************************************************
593 Checks, if an object can be stored in an array.
595 Return value: 1 ... possible
596 0 ... otherwise (throws an ArrayStoreException)
598 *******************************************************************************/
600 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
602 arraydescriptor *desc;
603 arraydescriptor *valuedesc;
604 vftbl_t *componentvftbl;
613 /* The following is guaranteed (by verifier checks):
615 * *) oa->...vftbl->arraydesc != NULL
616 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
617 * *) o->vftbl is not an interface vftbl
620 desc = oa->header.objheader.vftbl->arraydesc;
621 componentvftbl = desc->componentvftbl;
622 valuevftbl = o->vftbl;
623 valuedesc = valuevftbl->arraydesc;
625 if ((desc->dimension - 1) == 0) {
626 /* {oa is a one-dimensional array} */
627 /* {oa is an array of references} */
629 if (valuevftbl == componentvftbl)
632 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
634 baseval = componentvftbl->baseval;
637 /* an array of interface references */
639 result = ((valuevftbl->interfacetablelength > -baseval) &&
640 (valuevftbl->interfacetable[baseval] != NULL));
643 diffval = valuevftbl->baseval - componentvftbl->baseval;
644 result = diffval <= (uint32_t) componentvftbl->diffval;
647 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
649 else if (valuedesc == NULL) {
650 /* {oa has dimension > 1} */
651 /* {componentvftbl->arraydesc != NULL} */
653 /* check if o is an array */
658 /* {o is an array} */
660 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
663 /* if not possible, throw an exception */
666 exceptions_throw_arraystoreexception();
674 /* This is an optimized version where a is guaranteed to be one-dimensional */
675 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
677 arraydescriptor *desc;
678 vftbl_t *elementvftbl;
687 /* The following is guaranteed (by verifier checks):
689 * *) a->...vftbl->arraydesc != NULL
690 * *) a->...vftbl->arraydesc->elementvftbl != NULL
691 * *) a->...vftbl->arraydesc->dimension == 1
692 * *) o->vftbl is not an interface vftbl
695 desc = a->header.objheader.vftbl->arraydesc;
696 elementvftbl = desc->elementvftbl;
697 valuevftbl = o->vftbl;
699 /* {a is a one-dimensional array} */
701 if (valuevftbl == elementvftbl)
704 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
706 baseval = elementvftbl->baseval;
709 /* an array of interface references */
710 result = ((valuevftbl->interfacetablelength > -baseval) &&
711 (valuevftbl->interfacetable[baseval] != NULL));
714 diffval = valuevftbl->baseval - elementvftbl->baseval;
715 result = diffval <= (uint32_t) elementvftbl->diffval;
718 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
724 /* This is an optimized version where a is guaranteed to be a
725 * one-dimensional array of a class type */
726 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
728 vftbl_t *elementvftbl;
736 /* The following is guaranteed (by verifier checks):
738 * *) a->...vftbl->arraydesc != NULL
739 * *) a->...vftbl->arraydesc->elementvftbl != NULL
740 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
741 * *) a->...vftbl->arraydesc->dimension == 1
742 * *) o->vftbl is not an interface vftbl
745 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
746 valuevftbl = o->vftbl;
748 /* {a is a one-dimensional array} */
750 if (valuevftbl == elementvftbl)
753 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
755 diffval = valuevftbl->baseval - elementvftbl->baseval;
756 result = diffval <= (uint32_t) elementvftbl->diffval;
758 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
764 /* builtin_new *****************************************************************
766 Creates a new instance of class c on the heap.
768 Return value: pointer to the object or NULL if no memory is
771 *******************************************************************************/
773 java_objectheader *builtin_new(classinfo *c)
775 java_objectheader *o;
776 #if defined(ENABLE_RT_TIMING)
777 struct timespec time_start, time_end;
779 #if defined(ENABLE_CYCLES_STATS)
780 u8 cycles_start, cycles_end;
783 RT_TIMING_GET_TIME(time_start);
784 CYCLES_STATS_GET(cycles_start);
786 /* is the class loaded */
788 assert(c->state & CLASS_LOADED);
790 /* check if we can instantiate this class */
792 if (c->flags & ACC_ABSTRACT) {
793 exceptions_throw_instantiationerror(c);
797 /* is the class linked */
799 if (!(c->state & CLASS_LINKED))
803 if (!(c->state & CLASS_INITIALIZED)) {
806 log_message_class("Initialize class (from builtin_new): ", c);
809 if (!initialize_class(c))
813 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
821 #if defined(ENABLE_THREADS)
822 lock_init_object_lock(o);
825 CYCLES_STATS_GET(cycles_end);
826 RT_TIMING_GET_TIME(time_end);
828 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
829 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
835 /* builtin_newarray ************************************************************
837 Creates an array with the given vftbl on the heap. This function
838 takes as class argument an array class.
840 Return value: pointer to the array or NULL if no memory is available
842 *******************************************************************************/
844 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
846 arraydescriptor *desc;
851 #if defined(ENABLE_RT_TIMING)
852 struct timespec time_start, time_end;
855 RT_TIMING_GET_TIME(time_start);
857 desc = arrayclass->vftbl->arraydesc;
858 dataoffset = desc->dataoffset;
859 componentsize = desc->componentsize;
862 exceptions_throw_negativearraysizeexception();
866 actualsize = dataoffset + size * componentsize;
868 /* check for overflow */
870 if (((u4) actualsize) < ((u4) size)) {
871 exceptions_throw_outofmemoryerror();
875 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
880 a->objheader.vftbl = arrayclass->vftbl;
882 #if defined(ENABLE_THREADS)
883 lock_init_object_lock(&a->objheader);
888 RT_TIMING_GET_TIME(time_end);
889 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
895 /* builtin_anewarray ***********************************************************
897 Creates an array of references to the given class type on the heap.
899 Return value: pointer to the array or NULL if no memory is
902 *******************************************************************************/
904 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
906 classinfo *arrayclass;
908 /* is class loaded */
910 assert(componentclass->state & CLASS_LOADED);
912 /* is class linked */
914 if (!(componentclass->state & CLASS_LINKED))
915 if (!link_class(componentclass))
918 arrayclass = class_array_of(componentclass, true);
923 return (java_objectarray *) builtin_newarray(size, arrayclass);
927 /* builtin_newarray_boolean ****************************************************
929 Creates an array of bytes on the heap. The array is designated as
930 an array of booleans (important for casts)
932 Return value: pointer to the array or NULL if no memory is
935 *******************************************************************************/
937 java_booleanarray *builtin_newarray_boolean(s4 size)
939 return (java_booleanarray *)
940 builtin_newarray(size,
941 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
945 /* builtin_newarray_byte *******************************************************
947 Creates an array of 8 bit Integers on the heap.
949 Return value: pointer to the array or NULL if no memory is
952 *******************************************************************************/
954 java_bytearray *builtin_newarray_byte(s4 size)
956 return (java_bytearray *)
957 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
961 /* builtin_newarray_char *******************************************************
963 Creates an array of characters on the heap.
965 Return value: pointer to the array or NULL if no memory is
968 *******************************************************************************/
970 java_chararray *builtin_newarray_char(s4 size)
972 return (java_chararray *)
973 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
977 /* builtin_newarray_short ******************************************************
979 Creates an array of 16 bit Integers on the heap.
981 Return value: pointer to the array or NULL if no memory is
984 *******************************************************************************/
986 java_shortarray *builtin_newarray_short(s4 size)
988 return (java_shortarray *)
989 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
993 /* builtin_newarray_int ********************************************************
995 Creates an array of 32 bit Integers on the heap.
997 Return value: pointer to the array or NULL if no memory is
1000 *******************************************************************************/
1002 java_intarray *builtin_newarray_int(s4 size)
1004 return (java_intarray *)
1005 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1009 /* builtin_newarray_long *******************************************************
1011 Creates an array of 64 bit Integers on the heap.
1013 Return value: pointer to the array or NULL if no memory is
1016 *******************************************************************************/
1018 java_longarray *builtin_newarray_long(s4 size)
1020 return (java_longarray *)
1021 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1025 /* builtin_newarray_float ******************************************************
1027 Creates an array of 32 bit IEEE floats on the heap.
1029 Return value: pointer to the array or NULL if no memory is
1032 *******************************************************************************/
1034 java_floatarray *builtin_newarray_float(s4 size)
1036 return (java_floatarray *)
1037 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1041 /* builtin_newarray_double *****************************************************
1043 Creates an array of 64 bit IEEE floats on the heap.
1045 Return value: pointer to the array or NULL if no memory is
1048 *******************************************************************************/
1050 java_doublearray *builtin_newarray_double(s4 size)
1052 return (java_doublearray *)
1053 builtin_newarray(size,
1054 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1058 /* builtin_multianewarray_intern ***********************************************
1060 Creates a multi-dimensional array on the heap. The dimensions are
1061 passed in an array of longs.
1064 n.............number of dimensions to create
1065 arrayclass....the array class
1066 dims..........array containing the size of each dimension to create
1068 Return value: pointer to the array or NULL if no memory is
1071 ******************************************************************************/
1073 static java_arrayheader *builtin_multianewarray_intern(int n,
1074 classinfo *arrayclass,
1078 java_arrayheader *a;
1079 classinfo *componentclass;
1082 /* create this dimension */
1084 size = (s4) dims[0];
1085 a = builtin_newarray(size, arrayclass);
1090 /* if this is the last dimension return */
1095 /* get the class of the components to create */
1097 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1099 /* The verifier guarantees that the dimension count is in the range. */
1101 /* create the component arrays */
1103 for (i = 0; i < size; i++) {
1104 java_arrayheader *ea =
1105 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1106 /* we save an s4 to a s8 slot, 8-byte aligned */
1108 builtin_multianewarray_intern(n, componentclass, dims + 2);
1110 builtin_multianewarray_intern(n, componentclass, dims + 1);
1116 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1123 /* builtin_multianewarray ******************************************************
1125 Wrapper for builtin_multianewarray_intern which checks all
1126 dimensions before we start allocating.
1128 ******************************************************************************/
1130 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1136 /* check all dimensions before doing anything */
1138 for (i = 0; i < n; i++) {
1139 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1140 /* we save an s4 to a s8 slot, 8-byte aligned */
1141 size = (s4) dims[i * 2];
1143 size = (s4) dims[i];
1147 exceptions_throw_negativearraysizeexception();
1152 /* now call the real function */
1154 return builtin_multianewarray_intern(n, arrayclass, dims);
1158 /*****************************************************************************
1161 Various functions for printing a message at method entry or exit (for
1164 *****************************************************************************/
1166 #if !defined(NDEBUG)
1167 static s4 methodindent = 0;
1168 static u4 callcount = 0;
1170 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1180 #if defined(ENABLE_DEBUG_FILTER)
1181 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1184 #if defined(ENABLE_VMLOG)
1188 if (opt_verbosecall && indent)
1191 /* calculate message length */
1195 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1198 logtextlen = strlen("Some Throwable");
1201 logtextlen += strlen(" thrown in ");
1205 utf_bytes(m->class->name) +
1207 utf_bytes(m->name) +
1208 utf_bytes(m->descriptor) +
1209 strlen("(NOSYNC,NATIVE");
1211 #if SIZEOF_VOID_P == 8
1213 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1215 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1218 if (m->class->sourcefile == NULL)
1219 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1221 logtextlen += utf_bytes(m->class->sourcefile);
1223 logtextlen += strlen(":65536)");
1227 logtextlen += strlen("call_java_method");
1230 logtextlen += strlen("0");
1232 /* allocate memory */
1234 dumpsize = dump_size();
1236 logtext = DMNEW(char, logtextlen);
1239 strcpy(logtext, "Exception ");
1240 utf_cat_classname(logtext, xptr->vftbl->class->name);
1243 strcpy(logtext, "Some Throwable");
1246 strcat(logtext, " thrown in ");
1249 utf_cat_classname(logtext, m->class->name);
1250 strcat(logtext, ".");
1251 utf_cat(logtext, m->name);
1252 utf_cat(logtext, m->descriptor);
1254 if (m->flags & ACC_SYNCHRONIZED)
1255 strcat(logtext, "(SYNC");
1257 strcat(logtext, "(NOSYNC");
1259 if (m->flags & ACC_NATIVE) {
1260 strcat(logtext, ",NATIVE");
1264 #if SIZEOF_VOID_P == 8
1265 sprintf(logtext + strlen(logtext),
1266 ")(0x%016lx) at position 0x%016lx",
1267 (ptrint) code->entrypoint, (ptrint) pos);
1269 sprintf(logtext + strlen(logtext),
1270 ")(0x%08x) at position 0x%08x",
1271 (ptrint) code->entrypoint, (ptrint) pos);
1276 /* XXX preliminary: This should get the actual codeinfo */
1277 /* in which the exception happened. */
1280 #if SIZEOF_VOID_P == 8
1281 sprintf(logtext + strlen(logtext),
1282 ")(0x%016lx) at position 0x%016lx (",
1283 (ptrint) code->entrypoint, (ptrint) pos);
1285 sprintf(logtext + strlen(logtext),
1286 ")(0x%08x) at position 0x%08x (",
1287 (ptrint) code->entrypoint, (ptrint) pos);
1290 if (m->class->sourcefile == NULL)
1291 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1293 utf_cat(logtext, m->class->sourcefile);
1295 sprintf(logtext + strlen(logtext), ":%d)", 0);
1299 strcat(logtext, "call_java_method");
1303 /* release memory */
1305 dump_release(dumpsize);
1309 #endif /* !defined(NDEBUG) */
1312 /* builtin_print_argument ******************************************************
1314 Prints arguments and return values for the call trace.
1316 *******************************************************************************/
1318 #if !defined(NDEBUG)
1319 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1320 typedesc *paramtype, s8 value)
1323 java_objectheader *o;
1328 switch (paramtype->type) {
1331 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1336 #if SIZEOF_VOID_P == 4
1337 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1339 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1344 #if defined(__S390__)
1346 /* The below won't work on S390 */
1350 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1355 #if SIZEOF_VOID_P == 4
1356 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1358 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1363 #if SIZEOF_VOID_P == 4
1364 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1366 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1369 /* cast to java.lang.Object */
1371 o = (java_objectheader *) (ptrint) value;
1373 /* check return argument for java.lang.Class or java.lang.String */
1376 if (o->vftbl->class == class_java_lang_String) {
1377 /* get java.lang.String object and the length of the
1380 u = javastring_toutf(o, false);
1382 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1384 /* realloc memory for string length */
1386 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1389 /* convert to utf8 string and strcat it to the logtext */
1391 strcat(logtext, " (String = \"");
1392 utf_cat(logtext, u);
1393 strcat(logtext, "\")");
1396 if (o->vftbl->class == class_java_lang_Class) {
1397 /* if the object returned is a java.lang.Class
1398 cast it to classinfo structure and get the name
1401 c = (classinfo *) o;
1406 /* if the object returned is not a java.lang.String or
1407 a java.lang.Class just print the name of the class */
1409 u = o->vftbl->class->name;
1412 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1414 /* realloc memory for string length */
1416 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1419 /* strcat to the logtext */
1421 strcat(logtext, " (Class = \"");
1422 utf_cat_classname(logtext, u);
1423 strcat(logtext, "\")");
1430 #endif /* !defined(NDEBUG) */
1432 /* builtin_verbosecall_enter ***************************************************
1434 Print method call with arguments for -verbose:call.
1436 *******************************************************************************/
1438 #if !defined(NDEBUG)
1440 #ifdef TRACE_ARGS_NUM
1441 void builtin_verbosecall_enter(s8 a0, s8 a1,
1442 # if TRACE_ARGS_NUM >= 4
1445 # if TRACE_ARGS_NUM >= 6
1448 # if TRACE_ARGS_NUM == 8
1460 #if defined(ENABLE_DEBUG_FILTER)
1461 if (! show_filters_test_verbosecall_enter(m)) return;
1464 #if defined(ENABLE_VMLOG)
1465 vmlog_cacao_enter_method(m);
1471 /* calculate message length */
1474 strlen("4294967295 ") +
1475 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1477 strlen("called: ") +
1478 utf_bytes(m->class->name) +
1480 utf_bytes(m->name) +
1481 utf_bytes(m->descriptor);
1483 /* Actually it's not possible to have all flags printed, but:
1488 strlen(" PRIVATE") +
1489 strlen(" PROTECTED") +
1492 strlen(" SYNCHRONIZED") +
1493 strlen(" VOLATILE") +
1494 strlen(" TRANSIENT") +
1496 strlen(" INTERFACE") +
1497 strlen(" ABSTRACT");
1499 /* add maximal argument length */
1503 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1504 strlen("...(255)") +
1507 /* allocate memory */
1509 dumpsize = dump_size();
1511 logtext = DMNEW(char, logtextlen);
1515 sprintf(logtext, "%10d ", callcount);
1516 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1518 pos = strlen(logtext);
1520 for (i = 0; i < methodindent; i++)
1521 logtext[pos++] = '\t';
1523 strcpy(logtext + pos, "called: ");
1525 utf_cat_classname(logtext, m->class->name);
1526 strcat(logtext, ".");
1527 utf_cat(logtext, m->name);
1528 utf_cat(logtext, m->descriptor);
1530 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1531 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1532 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1533 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1534 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1535 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1536 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1537 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1538 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1539 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1540 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1542 strcat(logtext, "(");
1544 if (md->paramcount >= 1) {
1545 logtext = builtin_print_argument(logtext, &logtextlen,
1546 &md->paramtypes[0], a0);
1549 if (md->paramcount >= 2) {
1550 strcat(logtext, ", ");
1552 logtext = builtin_print_argument(logtext, &logtextlen,
1553 &md->paramtypes[1], a1);
1556 #if TRACE_ARGS_NUM >= 4
1557 if (md->paramcount >= 3) {
1558 strcat(logtext, ", ");
1560 logtext = builtin_print_argument(logtext, &logtextlen,
1561 &md->paramtypes[2], a2);
1564 if (md->paramcount >= 4) {
1565 strcat(logtext, ", ");
1567 logtext = builtin_print_argument(logtext, &logtextlen,
1568 &md->paramtypes[3], a3);
1572 #if TRACE_ARGS_NUM >= 6
1573 if (md->paramcount >= 5) {
1574 strcat(logtext, ", ");
1576 logtext = builtin_print_argument(logtext, &logtextlen,
1577 &md->paramtypes[4], a4);
1580 if (md->paramcount >= 6) {
1581 strcat(logtext, ", ");
1583 logtext = builtin_print_argument(logtext, &logtextlen,
1584 &md->paramtypes[5], a5);
1588 #if TRACE_ARGS_NUM == 8
1589 if (md->paramcount >= 7) {
1590 strcat(logtext, ", ");
1592 logtext = builtin_print_argument(logtext, &logtextlen,
1593 &md->paramtypes[6], a6);
1596 if (md->paramcount >= 8) {
1597 strcat(logtext, ", ");
1599 logtext = builtin_print_argument(logtext, &logtextlen,
1600 &md->paramtypes[7], a7);
1604 if (md->paramcount > 8) {
1605 sprintf(logtext + strlen(logtext), ", ...(%d)",
1606 md->paramcount - TRACE_ARGS_NUM);
1609 strcat(logtext, ")");
1613 /* release memory */
1615 dump_release(dumpsize);
1621 #endif /* !defined(NDEBUG) */
1624 /* builtin_verbosecall_exit ****************************************************
1626 Print method exit for -verbose:call.
1628 *******************************************************************************/
1630 #if !defined(NDEBUG)
1631 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1641 #if defined(ENABLE_DEBUG_FILTER)
1642 if (! show_filters_test_verbosecall_exit(m)) return;
1645 #if defined(ENABLE_VMLOG)
1646 vmlog_cacao_leave_method(m);
1652 /* calculate message length */
1655 strlen("4294967295 ") +
1656 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1658 strlen("finished: ") +
1659 utf_bytes(m->class->name) +
1661 utf_bytes(m->name) +
1662 utf_bytes(m->descriptor) +
1663 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1665 /* add maximal argument length */
1667 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1669 /* allocate memory */
1671 dumpsize = dump_size();
1673 logtext = DMNEW(char, logtextlen);
1675 /* outdent the log message */
1680 log_text("WARNING: unmatched methodindent--");
1682 /* generate the message */
1684 sprintf(logtext, " ");
1685 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1687 pos = strlen(logtext);
1689 for (i = 0; i < methodindent; i++)
1690 logtext[pos++] = '\t';
1692 strcpy(logtext + pos, "finished: ");
1693 utf_cat_classname(logtext, m->class->name);
1694 strcat(logtext, ".");
1695 utf_cat(logtext, m->name);
1696 utf_cat(logtext, m->descriptor);
1698 if (!IS_VOID_TYPE(md->returntype.type)) {
1699 strcat(logtext, "->");
1701 switch (md->returntype.type) {
1718 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1723 /* release memory */
1725 dump_release(dumpsize);
1728 #endif /* !defined(NDEBUG) */
1731 #if defined(ENABLE_CYCLES_STATS)
1732 void builtin_print_cycles_stats(FILE *file)
1734 fprintf(file,"builtin cylce count statistics:\n");
1736 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1737 CYCLES_STATS_PRINT(builtin_new ,file);
1741 #endif /* defined(ENABLE_CYCLES_STATS) */
1744 /*****************************************************************************
1745 MISCELLANEOUS HELPER FUNCTIONS
1746 *****************************************************************************/
1750 /*********** Functions for integer divisions *****************************
1752 On some systems (eg. DEC ALPHA), integer division is not supported by the
1753 CPU. These helper functions implement the missing functionality.
1755 ******************************************************************************/
1757 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1758 s4 builtin_idiv(s4 a, s4 b)
1767 s4 builtin_irem(s4 a, s4 b)
1775 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1778 /* functions for long arithmetics **********************************************
1780 On systems where 64 bit Integers are not supported by the CPU,
1781 these functions are needed.
1783 ******************************************************************************/
1785 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1786 s8 builtin_ladd(s8 a, s8 b)
1799 s8 builtin_lsub(s8 a, s8 b)
1812 s8 builtin_lneg(s8 a)
1824 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1827 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1828 s8 builtin_lmul(s8 a, s8 b)
1840 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1843 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1844 s8 builtin_ldiv(s8 a, s8 b)
1857 s8 builtin_lrem(s8 a, s8 b)
1869 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1872 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1873 s8 builtin_lshl(s8 a, s4 b)
1886 s8 builtin_lshr(s8 a, s4 b)
1899 s8 builtin_lushr(s8 a, s4 b)
1904 c = ((u8) a) >> (b & 63);
1911 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1914 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1915 s8 builtin_land(s8 a, s8 b)
1928 s8 builtin_lor(s8 a, s8 b)
1941 s8 builtin_lxor(s8 a, s8 b)
1953 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1956 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1957 s4 builtin_lcmp(s8 a, s8 b)
1971 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1974 /* functions for unsupported floating instructions ****************************/
1976 /* used to convert FLT_xxx defines into float values */
1978 static inline float intBitsToFloat(s4 i)
1987 /* used to convert DBL_xxx defines into double values */
1989 static inline float longBitsToDouble(s8 l)
1999 float builtin_fadd(float a, float b)
2001 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2002 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2013 if (copysignf(1.0, a) == copysignf(1.0, b))
2016 return intBitsToFloat(FLT_NAN);
2022 float builtin_fsub(float a, float b)
2024 return builtin_fadd(a, builtin_fneg(b));
2028 float builtin_fmul(float a, float b)
2030 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2031 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2033 if (finitef(b)) return a * b;
2035 if (a == 0) return intBitsToFloat(FLT_NAN);
2036 else return copysignf(b, copysignf(1.0, b)*a);
2041 if (b == 0) return intBitsToFloat(FLT_NAN);
2042 else return copysignf(a, copysignf(1.0, a)*b);
2045 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2051 /* builtin_ddiv ****************************************************************
2053 Implementation as described in VM Spec.
2055 *******************************************************************************/
2057 float builtin_fdiv(float a, float b)
2061 /* If neither value1' nor value2' is NaN, the sign of the result */
2062 /* is positive if both values have the same sign, negative if the */
2063 /* values have different signs. */
2069 /* If either value1' or value2' is NaN, the result is NaN. */
2071 return intBitsToFloat(FLT_NAN);
2074 /* Division of a finite value by an infinity results in a */
2075 /* signed zero, with the sign-producing rule just given. */
2077 /* is sign equal? */
2079 if (copysignf(1.0, a) == copysignf(1.0, b))
2088 /* If either value1' or value2' is NaN, the result is NaN. */
2090 return intBitsToFloat(FLT_NAN);
2092 } else if (finitef(b)) {
2093 /* Division of an infinity by a finite value results in a signed */
2094 /* infinity, with the sign-producing rule just given. */
2096 /* is sign equal? */
2098 if (copysignf(1.0, a) == copysignf(1.0, b))
2099 return intBitsToFloat(FLT_POSINF);
2101 return intBitsToFloat(FLT_NEGINF);
2104 /* Division of an infinity by an infinity results in NaN. */
2106 return intBitsToFloat(FLT_NAN);
2112 float builtin_fneg(float a)
2114 if (isnanf(a)) return a;
2116 if (finitef(a)) return -a;
2117 else return copysignf(a, -copysignf(1.0, a));
2120 #endif /* !SUPPORT_FLOAT */
2123 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2124 s4 builtin_fcmpl(float a, float b)
2132 if (!finitef(a) || !finitef(b)) {
2133 a = finitef(a) ? 0 : copysignf(1.0, a);
2134 b = finitef(b) ? 0 : copysignf(1.0, b);
2147 s4 builtin_fcmpg(float a, float b)
2149 if (isnanf(a)) return 1;
2150 if (isnanf(b)) return 1;
2151 if (!finitef(a) || !finitef(b)) {
2152 a = finitef(a) ? 0 : copysignf(1.0, a);
2153 b = finitef(b) ? 0 : copysignf(1.0, b);
2155 if (a > b) return 1;
2156 if (a == b) return 0;
2159 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2162 float builtin_frem(float a, float b)
2168 /* functions for unsupported double instructions ******************************/
2171 double builtin_dadd(double a, double b)
2173 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2174 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2176 if (finite(b)) return a + b;
2180 if (finite(b)) return a;
2182 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2183 else return longBitsToDouble(DBL_NAN);
2189 double builtin_dsub(double a, double b)
2191 return builtin_dadd(a, builtin_dneg(b));
2195 double builtin_dmul(double a, double b)
2197 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2198 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2200 if (finite(b)) return a * b;
2202 if (a == 0) return longBitsToDouble(DBL_NAN);
2203 else return copysign(b, copysign(1.0, b) * a);
2208 if (b == 0) return longBitsToDouble(DBL_NAN);
2209 else return copysign(a, copysign(1.0, a) * b);
2212 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2218 /* builtin_ddiv ****************************************************************
2220 Implementation as described in VM Spec.
2222 *******************************************************************************/
2224 double builtin_ddiv(double a, double b)
2228 /* If neither value1' nor value2' is NaN, the sign of the result */
2229 /* is positive if both values have the same sign, negative if the */
2230 /* values have different signs. */
2236 /* If either value1' or value2' is NaN, the result is NaN. */
2238 return longBitsToDouble(DBL_NAN);
2241 /* Division of a finite value by an infinity results in a */
2242 /* signed zero, with the sign-producing rule just given. */
2244 /* is sign equal? */
2246 if (copysign(1.0, a) == copysign(1.0, b))
2255 /* If either value1' or value2' is NaN, the result is NaN. */
2257 return longBitsToDouble(DBL_NAN);
2259 } else if (finite(b)) {
2260 /* Division of an infinity by a finite value results in a signed */
2261 /* infinity, with the sign-producing rule just given. */
2263 /* is sign equal? */
2265 if (copysign(1.0, a) == copysign(1.0, b))
2266 return longBitsToDouble(DBL_POSINF);
2268 return longBitsToDouble(DBL_NEGINF);
2271 /* Division of an infinity by an infinity results in NaN. */
2273 return longBitsToDouble(DBL_NAN);
2279 /* builtin_dneg ****************************************************************
2281 Implemented as described in VM Spec.
2283 *******************************************************************************/
2285 double builtin_dneg(double a)
2288 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2295 /* If the operand is a zero, the result is the zero of opposite */
2301 /* If the operand is an infinity, the result is the infinity of */
2302 /* opposite sign. */
2304 return copysign(a, -copysign(1.0, a));
2308 #endif /* !SUPPORT_DOUBLE */
2311 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2312 s4 builtin_dcmpl(double a, double b)
2320 if (!finite(a) || !finite(b)) {
2321 a = finite(a) ? 0 : copysign(1.0, a);
2322 b = finite(b) ? 0 : copysign(1.0, b);
2335 s4 builtin_dcmpg(double a, double b)
2343 if (!finite(a) || !finite(b)) {
2344 a = finite(a) ? 0 : copysign(1.0, a);
2345 b = finite(b) ? 0 : copysign(1.0, b);
2356 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2359 double builtin_drem(double a, double b)
2365 /* conversion operations ******************************************************/
2368 s8 builtin_i2l(s4 i)
2380 s4 builtin_l2i(s8 l)
2391 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2392 float builtin_i2f(s4 a)
2394 float f = (float) a;
2397 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2400 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2401 double builtin_i2d(s4 a)
2403 double d = (double) a;
2406 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2409 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2410 float builtin_l2f(s8 a)
2413 float f = (float) a;
2419 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2422 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2423 double builtin_l2d(s8 a)
2426 double d = (double) a;
2432 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2435 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2436 s4 builtin_f2i(float a)
2440 i = builtin_d2i((double) a);
2451 if (a < (-2147483648))
2452 return (-2147483648);
2455 f = copysignf((float) 1.0, a);
2458 return (-2147483648); */
2460 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2463 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2464 s8 builtin_f2l(float a)
2468 l = builtin_d2l((double) a);
2475 if (a > 9223372036854775807L)
2476 return 9223372036854775807L;
2477 if (a < (-9223372036854775808L))
2478 return (-9223372036854775808L);
2483 f = copysignf((float) 1.0, a);
2485 return 9223372036854775807L;
2486 return (-9223372036854775808L); */
2488 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2491 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2492 s4 builtin_d2i(double a)
2497 if (a >= 2147483647)
2499 if (a <= (-2147483647-1))
2500 return (-2147483647-1);
2505 d = copysign(1.0, a);
2508 return (-2147483647-1);
2510 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2513 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2514 s8 builtin_d2l(double a)
2519 if (a >= 9223372036854775807LL)
2520 return 9223372036854775807LL;
2521 if (a <= (-9223372036854775807LL-1))
2522 return (-9223372036854775807LL-1);
2527 d = copysign(1.0, a);
2529 return 9223372036854775807LL;
2530 return (-9223372036854775807LL-1);
2532 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2535 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2536 double builtin_f2d(float a)
2538 if (finitef(a)) return (double) a;
2541 return longBitsToDouble(DBL_NAN);
2543 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2547 float builtin_d2f(double a)
2553 return intBitsToFloat(FLT_NAN);
2555 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2558 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2561 /* builtin_arraycopy ***********************************************************
2563 Builtin for java.lang.System.arraycopy.
2565 ATTENTION: This builtin function returns a boolean value to signal
2566 the ICMD_BUILTIN if there was an exception.
2568 *******************************************************************************/
2570 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2571 java_arrayheader *dest, s4 destStart, s4 len)
2573 arraydescriptor *sdesc;
2574 arraydescriptor *ddesc;
2577 if ((src == NULL) || (dest == NULL)) {
2578 exceptions_throw_nullpointerexception();
2582 sdesc = src->objheader.vftbl->arraydesc;
2583 ddesc = dest->objheader.vftbl->arraydesc;
2585 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2586 exceptions_throw_arraystoreexception();
2590 /* we try to throw exception with the same message as SUN does */
2592 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2593 (srcStart + len < 0) || (srcStart + len > src->size) ||
2594 (destStart + len < 0) || (destStart + len > dest->size)) {
2595 exceptions_throw_arrayindexoutofboundsexception();
2599 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2600 /* We copy primitive values or references of exactly the same type */
2602 s4 dataoffset = sdesc->dataoffset;
2603 s4 componentsize = sdesc->componentsize;
2605 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2606 ((u1 *) src) + dataoffset + componentsize * srcStart,
2607 (size_t) len * componentsize);
2610 /* We copy references of different type */
2612 java_objectarray *oas = (java_objectarray *) src;
2613 java_objectarray *oad = (java_objectarray *) dest;
2615 if (destStart <= srcStart) {
2616 for (i = 0; i < len; i++) {
2617 java_objectheader *o = oas->data[srcStart + i];
2619 if (!builtin_canstore(oad, o))
2622 oad->data[destStart + i] = o;
2626 /* XXX this does not completely obey the specification!
2627 If an exception is thrown only the elements above the
2628 current index have been copied. The specification
2629 requires that only the elements *below* the current
2630 index have been copied before the throw. */
2632 for (i = len - 1; i >= 0; i--) {
2633 java_objectheader *o = oas->data[srcStart + i];
2635 if (!builtin_canstore(oad, o))
2638 oad->data[destStart + i] = o;
2647 /* builtin_nanotime ************************************************************
2649 Return the current time in nanoseconds.
2651 *******************************************************************************/
2653 s8 builtin_nanotime(void)
2658 if (gettimeofday(&tv, NULL) == -1)
2659 vm_abort("gettimeofday failed: %s", strerror(errno));
2661 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2663 return usecs * 1000;
2667 /* builtin_currenttimemillis ***************************************************
2669 Return the current time in milliseconds.
2671 *******************************************************************************/
2673 s8 builtin_currenttimemillis(void)
2677 msecs = builtin_nanotime() / 1000 / 1000;
2683 /* builtin_clone ***************************************************************
2685 Function for cloning objects or arrays.
2687 *******************************************************************************/
2689 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2691 arraydescriptor *ad;
2692 java_arrayheader *ah;
2695 java_objectheader *co; /* cloned object header */
2697 /* get the array descriptor */
2699 ad = o->vftbl->arraydesc;
2701 /* we are cloning an array */
2704 ah = (java_arrayheader *) o;
2706 size = ad->dataoffset + ad->componentsize * ah->size;
2708 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2713 MCOPY(co, o, u1, size);
2715 #if defined(ENABLE_GC_CACAO)
2716 heap_init_objectheader(co, size);
2719 #if defined(ENABLE_THREADS)
2720 lock_init_object_lock(co);
2726 /* we are cloning a non-array */
2728 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2729 exceptions_throw_clonenotsupportedexception();
2733 /* get the class of the object */
2735 c = o->vftbl->class;
2737 /* create new object */
2739 co = builtin_new(c);
2744 MCOPY(co, o, u1, c->instancesize);
2746 #if defined(ENABLE_GC_CACAO)
2747 heap_init_objectheader(co, c->instancesize);
2750 #if defined(ENABLE_THREADS)
2751 lock_init_object_lock(co);
2757 #if defined(ENABLE_VMLOG)
2759 #include <vmlog_cacao.c>
2764 * These are local overrides for various environment variables in Emacs.
2765 * Please do not remove this and leave it at the end of the file, where
2766 * Emacs will automagically detect them.
2767 * ---------------------------------------------------------------------
2770 * indent-tabs-mode: t
2774 * vim:noexpandtab:sw=4:ts=4: