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 8046 2007-06-07 22:02:16Z pm $
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);
1320 #if defined(__S390__)
1322 /* The below won't work on S390 */
1326 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1331 #if SIZEOF_VOID_P == 4
1332 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1334 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1339 #if SIZEOF_VOID_P == 4
1340 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1342 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1345 /* cast to java.lang.Object */
1347 o = (java_objectheader *) (ptrint) value;
1349 /* check return argument for java.lang.Class or java.lang.String */
1352 if (o->vftbl->class == class_java_lang_String) {
1353 /* get java.lang.String object and the length of the
1356 u = javastring_toutf(o, false);
1358 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1360 /* realloc memory for string length */
1362 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1365 /* convert to utf8 string and strcat it to the logtext */
1367 strcat(logtext, " (String = \"");
1368 utf_cat(logtext, u);
1369 strcat(logtext, "\")");
1372 if (o->vftbl->class == class_java_lang_Class) {
1373 /* if the object returned is a java.lang.Class
1374 cast it to classinfo structure and get the name
1377 c = (classinfo *) o;
1382 /* if the object returned is not a java.lang.String or
1383 a java.lang.Class just print the name of the class */
1385 u = o->vftbl->class->name;
1388 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1390 /* realloc memory for string length */
1392 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1395 /* strcat to the logtext */
1397 strcat(logtext, " (Class = \"");
1398 utf_cat_classname(logtext, u);
1399 strcat(logtext, "\")");
1406 #endif /* !defined(NDEBUG) */
1408 /* builtin_verbosecall_enter ***************************************************
1410 Print method call with arguments for -verbose:call.
1412 *******************************************************************************/
1414 #if !defined(NDEBUG)
1416 #ifdef TRACE_ARGS_NUM
1417 void builtin_verbosecall_enter(s8 a0, s8 a1,
1418 # if TRACE_ARGS_NUM >= 4
1421 # if TRACE_ARGS_NUM >= 6
1424 # if TRACE_ARGS_NUM == 8
1436 #if defined(ENABLE_DEBUG_FILTER)
1437 if (! show_filters_test_verbosecall_enter(m)) return;
1440 #if defined(ENABLE_VMLOG)
1441 vmlog_cacao_enter_method(m);
1447 /* calculate message length */
1450 strlen("4294967295 ") +
1451 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1453 strlen("called: ") +
1454 utf_bytes(m->class->name) +
1456 utf_bytes(m->name) +
1457 utf_bytes(m->descriptor);
1459 /* Actually it's not possible to have all flags printed, but:
1464 strlen(" PRIVATE") +
1465 strlen(" PROTECTED") +
1468 strlen(" SYNCHRONIZED") +
1469 strlen(" VOLATILE") +
1470 strlen(" TRANSIENT") +
1472 strlen(" INTERFACE") +
1473 strlen(" ABSTRACT");
1475 /* add maximal argument length */
1479 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1480 strlen("...(255)") +
1483 /* allocate memory */
1485 dumpsize = dump_size();
1487 logtext = DMNEW(char, logtextlen);
1491 sprintf(logtext, "%10d ", callcount);
1492 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1494 pos = strlen(logtext);
1496 for (i = 0; i < methodindent; i++)
1497 logtext[pos++] = '\t';
1499 strcpy(logtext + pos, "called: ");
1501 utf_cat_classname(logtext, m->class->name);
1502 strcat(logtext, ".");
1503 utf_cat(logtext, m->name);
1504 utf_cat(logtext, m->descriptor);
1506 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1507 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1508 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1509 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1510 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1511 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1512 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1513 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1514 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1515 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1516 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1518 strcat(logtext, "(");
1520 if (md->paramcount >= 1) {
1521 logtext = builtin_print_argument(logtext, &logtextlen,
1522 &md->paramtypes[0], a0);
1525 if (md->paramcount >= 2) {
1526 strcat(logtext, ", ");
1528 logtext = builtin_print_argument(logtext, &logtextlen,
1529 &md->paramtypes[1], a1);
1532 #if TRACE_ARGS_NUM >= 4
1533 if (md->paramcount >= 3) {
1534 strcat(logtext, ", ");
1536 logtext = builtin_print_argument(logtext, &logtextlen,
1537 &md->paramtypes[2], a2);
1540 if (md->paramcount >= 4) {
1541 strcat(logtext, ", ");
1543 logtext = builtin_print_argument(logtext, &logtextlen,
1544 &md->paramtypes[3], a3);
1548 #if TRACE_ARGS_NUM >= 6
1549 if (md->paramcount >= 5) {
1550 strcat(logtext, ", ");
1552 logtext = builtin_print_argument(logtext, &logtextlen,
1553 &md->paramtypes[4], a4);
1556 if (md->paramcount >= 6) {
1557 strcat(logtext, ", ");
1559 logtext = builtin_print_argument(logtext, &logtextlen,
1560 &md->paramtypes[5], a5);
1564 #if TRACE_ARGS_NUM == 8
1565 if (md->paramcount >= 7) {
1566 strcat(logtext, ", ");
1568 logtext = builtin_print_argument(logtext, &logtextlen,
1569 &md->paramtypes[6], a6);
1572 if (md->paramcount >= 8) {
1573 strcat(logtext, ", ");
1575 logtext = builtin_print_argument(logtext, &logtextlen,
1576 &md->paramtypes[7], a7);
1580 if (md->paramcount > 8) {
1581 sprintf(logtext + strlen(logtext), ", ...(%d)",
1582 md->paramcount - TRACE_ARGS_NUM);
1585 strcat(logtext, ")");
1589 /* release memory */
1591 dump_release(dumpsize);
1597 #endif /* !defined(NDEBUG) */
1600 /* builtin_verbosecall_exit ****************************************************
1602 Print method exit for -verbose:call.
1604 *******************************************************************************/
1606 #if !defined(NDEBUG)
1607 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1617 #if defined(ENABLE_DEBUG_FILTER)
1618 if (! show_filters_test_verbosecall_exit(m)) return;
1621 #if defined(ENABLE_VMLOG)
1622 vmlog_cacao_leave_method(m);
1628 /* calculate message length */
1631 strlen("4294967295 ") +
1632 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1634 strlen("finished: ") +
1635 utf_bytes(m->class->name) +
1637 utf_bytes(m->name) +
1638 utf_bytes(m->descriptor) +
1639 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1641 /* add maximal argument length */
1643 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1645 /* allocate memory */
1647 dumpsize = dump_size();
1649 logtext = DMNEW(char, logtextlen);
1651 /* outdent the log message */
1656 log_text("WARNING: unmatched methodindent--");
1658 /* generate the message */
1660 sprintf(logtext, " ");
1661 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1663 pos = strlen(logtext);
1665 for (i = 0; i < methodindent; i++)
1666 logtext[pos++] = '\t';
1668 strcpy(logtext + pos, "finished: ");
1669 utf_cat_classname(logtext, m->class->name);
1670 strcat(logtext, ".");
1671 utf_cat(logtext, m->name);
1672 utf_cat(logtext, m->descriptor);
1674 if (!IS_VOID_TYPE(md->returntype.type)) {
1675 strcat(logtext, "->");
1677 switch (md->returntype.type) {
1694 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1699 /* release memory */
1701 dump_release(dumpsize);
1704 #endif /* !defined(NDEBUG) */
1707 #if defined(ENABLE_CYCLES_STATS)
1708 void builtin_print_cycles_stats(FILE *file)
1710 fprintf(file,"builtin cylce count statistics:\n");
1712 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1713 CYCLES_STATS_PRINT(builtin_new ,file);
1717 #endif /* defined(ENABLE_CYCLES_STATS) */
1720 /*****************************************************************************
1721 MISCELLANEOUS HELPER FUNCTIONS
1722 *****************************************************************************/
1726 /*********** Functions for integer divisions *****************************
1728 On some systems (eg. DEC ALPHA), integer division is not supported by the
1729 CPU. These helper functions implement the missing functionality.
1731 ******************************************************************************/
1733 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1734 s4 builtin_idiv(s4 a, s4 b)
1743 s4 builtin_irem(s4 a, s4 b)
1751 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1754 /* functions for long arithmetics **********************************************
1756 On systems where 64 bit Integers are not supported by the CPU,
1757 these functions are needed.
1759 ******************************************************************************/
1761 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1762 s8 builtin_ladd(s8 a, s8 b)
1775 s8 builtin_lsub(s8 a, s8 b)
1788 s8 builtin_lneg(s8 a)
1800 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1803 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1804 s8 builtin_lmul(s8 a, s8 b)
1816 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1819 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1820 s8 builtin_ldiv(s8 a, s8 b)
1833 s8 builtin_lrem(s8 a, s8 b)
1845 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1848 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1849 s8 builtin_lshl(s8 a, s4 b)
1862 s8 builtin_lshr(s8 a, s4 b)
1875 s8 builtin_lushr(s8 a, s4 b)
1880 c = ((u8) a) >> (b & 63);
1887 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1890 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1891 s8 builtin_land(s8 a, s8 b)
1904 s8 builtin_lor(s8 a, s8 b)
1917 s8 builtin_lxor(s8 a, s8 b)
1929 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1932 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1933 s4 builtin_lcmp(s8 a, s8 b)
1947 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1950 /* functions for unsupported floating instructions ****************************/
1952 /* used to convert FLT_xxx defines into float values */
1954 static inline float intBitsToFloat(s4 i)
1963 /* used to convert DBL_xxx defines into double values */
1965 static inline float longBitsToDouble(s8 l)
1975 float builtin_fadd(float a, float b)
1977 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1978 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1989 if (copysignf(1.0, a) == copysignf(1.0, b))
1992 return intBitsToFloat(FLT_NAN);
1998 float builtin_fsub(float a, float b)
2000 return builtin_fadd(a, builtin_fneg(b));
2004 float builtin_fmul(float a, float b)
2006 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2007 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2009 if (finitef(b)) return a * b;
2011 if (a == 0) return intBitsToFloat(FLT_NAN);
2012 else return copysignf(b, copysignf(1.0, b)*a);
2017 if (b == 0) return intBitsToFloat(FLT_NAN);
2018 else return copysignf(a, copysignf(1.0, a)*b);
2021 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2027 /* builtin_ddiv ****************************************************************
2029 Implementation as described in VM Spec.
2031 *******************************************************************************/
2033 float builtin_fdiv(float a, float b)
2037 /* If neither value1' nor value2' is NaN, the sign of the result */
2038 /* is positive if both values have the same sign, negative if the */
2039 /* values have different signs. */
2045 /* If either value1' or value2' is NaN, the result is NaN. */
2047 return intBitsToFloat(FLT_NAN);
2050 /* Division of a finite value by an infinity results in a */
2051 /* signed zero, with the sign-producing rule just given. */
2053 /* is sign equal? */
2055 if (copysignf(1.0, a) == copysignf(1.0, b))
2064 /* If either value1' or value2' is NaN, the result is NaN. */
2066 return intBitsToFloat(FLT_NAN);
2068 } else if (finitef(b)) {
2069 /* Division of an infinity by a finite value results in a signed */
2070 /* infinity, with the sign-producing rule just given. */
2072 /* is sign equal? */
2074 if (copysignf(1.0, a) == copysignf(1.0, b))
2075 return intBitsToFloat(FLT_POSINF);
2077 return intBitsToFloat(FLT_NEGINF);
2080 /* Division of an infinity by an infinity results in NaN. */
2082 return intBitsToFloat(FLT_NAN);
2088 float builtin_fneg(float a)
2090 if (isnanf(a)) return a;
2092 if (finitef(a)) return -a;
2093 else return copysignf(a, -copysignf(1.0, a));
2096 #endif /* !SUPPORT_FLOAT */
2099 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2100 s4 builtin_fcmpl(float a, float b)
2108 if (!finitef(a) || !finitef(b)) {
2109 a = finitef(a) ? 0 : copysignf(1.0, a);
2110 b = finitef(b) ? 0 : copysignf(1.0, b);
2123 s4 builtin_fcmpg(float a, float b)
2125 if (isnanf(a)) return 1;
2126 if (isnanf(b)) return 1;
2127 if (!finitef(a) || !finitef(b)) {
2128 a = finitef(a) ? 0 : copysignf(1.0, a);
2129 b = finitef(b) ? 0 : copysignf(1.0, b);
2131 if (a > b) return 1;
2132 if (a == b) return 0;
2135 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2138 float builtin_frem(float a, float b)
2144 /* functions for unsupported double instructions ******************************/
2147 double builtin_dadd(double a, double b)
2149 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2150 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2152 if (finite(b)) return a + b;
2156 if (finite(b)) return a;
2158 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2159 else return longBitsToDouble(DBL_NAN);
2165 double builtin_dsub(double a, double b)
2167 return builtin_dadd(a, builtin_dneg(b));
2171 double builtin_dmul(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;
2178 if (a == 0) return longBitsToDouble(DBL_NAN);
2179 else return copysign(b, copysign(1.0, b) * a);
2184 if (b == 0) return longBitsToDouble(DBL_NAN);
2185 else return copysign(a, copysign(1.0, a) * b);
2188 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2194 /* builtin_ddiv ****************************************************************
2196 Implementation as described in VM Spec.
2198 *******************************************************************************/
2200 double builtin_ddiv(double a, double b)
2204 /* If neither value1' nor value2' is NaN, the sign of the result */
2205 /* is positive if both values have the same sign, negative if the */
2206 /* values have different signs. */
2212 /* If either value1' or value2' is NaN, the result is NaN. */
2214 return longBitsToDouble(DBL_NAN);
2217 /* Division of a finite value by an infinity results in a */
2218 /* signed zero, with the sign-producing rule just given. */
2220 /* is sign equal? */
2222 if (copysign(1.0, a) == copysign(1.0, b))
2231 /* If either value1' or value2' is NaN, the result is NaN. */
2233 return longBitsToDouble(DBL_NAN);
2235 } else if (finite(b)) {
2236 /* Division of an infinity by a finite value results in a signed */
2237 /* infinity, with the sign-producing rule just given. */
2239 /* is sign equal? */
2241 if (copysign(1.0, a) == copysign(1.0, b))
2242 return longBitsToDouble(DBL_POSINF);
2244 return longBitsToDouble(DBL_NEGINF);
2247 /* Division of an infinity by an infinity results in NaN. */
2249 return longBitsToDouble(DBL_NAN);
2255 /* builtin_dneg ****************************************************************
2257 Implemented as described in VM Spec.
2259 *******************************************************************************/
2261 double builtin_dneg(double a)
2264 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2271 /* If the operand is a zero, the result is the zero of opposite */
2277 /* If the operand is an infinity, the result is the infinity of */
2278 /* opposite sign. */
2280 return copysign(a, -copysign(1.0, a));
2284 #endif /* !SUPPORT_DOUBLE */
2287 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2288 s4 builtin_dcmpl(double a, double b)
2296 if (!finite(a) || !finite(b)) {
2297 a = finite(a) ? 0 : copysign(1.0, a);
2298 b = finite(b) ? 0 : copysign(1.0, b);
2311 s4 builtin_dcmpg(double a, double b)
2319 if (!finite(a) || !finite(b)) {
2320 a = finite(a) ? 0 : copysign(1.0, a);
2321 b = finite(b) ? 0 : copysign(1.0, b);
2332 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2335 double builtin_drem(double a, double b)
2341 /* conversion operations ******************************************************/
2344 s8 builtin_i2l(s4 i)
2356 s4 builtin_l2i(s8 l)
2367 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2368 float builtin_i2f(s4 a)
2370 float f = (float) a;
2373 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2376 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2377 double builtin_i2d(s4 a)
2379 double d = (double) a;
2382 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2385 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2386 float builtin_l2f(s8 a)
2389 float f = (float) a;
2395 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2398 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2399 double builtin_l2d(s8 a)
2402 double d = (double) a;
2408 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2411 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2412 s4 builtin_f2i(float a)
2416 i = builtin_d2i((double) a);
2427 if (a < (-2147483648))
2428 return (-2147483648);
2431 f = copysignf((float) 1.0, a);
2434 return (-2147483648); */
2436 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2439 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2440 s8 builtin_f2l(float a)
2444 l = builtin_d2l((double) a);
2451 if (a > 9223372036854775807L)
2452 return 9223372036854775807L;
2453 if (a < (-9223372036854775808L))
2454 return (-9223372036854775808L);
2459 f = copysignf((float) 1.0, a);
2461 return 9223372036854775807L;
2462 return (-9223372036854775808L); */
2464 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2467 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2468 s4 builtin_d2i(double a)
2473 if (a >= 2147483647)
2475 if (a <= (-2147483647-1))
2476 return (-2147483647-1);
2481 d = copysign(1.0, a);
2484 return (-2147483647-1);
2486 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2489 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2490 s8 builtin_d2l(double a)
2495 if (a >= 9223372036854775807LL)
2496 return 9223372036854775807LL;
2497 if (a <= (-9223372036854775807LL-1))
2498 return (-9223372036854775807LL-1);
2503 d = copysign(1.0, a);
2505 return 9223372036854775807LL;
2506 return (-9223372036854775807LL-1);
2508 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2511 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2512 double builtin_f2d(float a)
2514 if (finitef(a)) return (double) a;
2517 return longBitsToDouble(DBL_NAN);
2519 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2523 float builtin_d2f(double a)
2529 return intBitsToFloat(FLT_NAN);
2531 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2534 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2537 /* builtin_arraycopy ***********************************************************
2539 Builtin for java.lang.System.arraycopy.
2541 ATTENTION: This builtin function returns a boolean value to signal
2542 the ICMD_BUILTIN if there was an exception.
2544 *******************************************************************************/
2546 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2547 java_arrayheader *dest, s4 destStart, s4 len)
2549 arraydescriptor *sdesc;
2550 arraydescriptor *ddesc;
2553 if ((src == NULL) || (dest == NULL)) {
2554 exceptions_throw_nullpointerexception();
2558 sdesc = src->objheader.vftbl->arraydesc;
2559 ddesc = dest->objheader.vftbl->arraydesc;
2561 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2562 exceptions_throw_arraystoreexception();
2566 /* we try to throw exception with the same message as SUN does */
2568 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2569 (srcStart + len < 0) || (srcStart + len > src->size) ||
2570 (destStart + len < 0) || (destStart + len > dest->size)) {
2571 exceptions_throw_arrayindexoutofboundsexception();
2575 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2576 /* We copy primitive values or references of exactly the same type */
2578 s4 dataoffset = sdesc->dataoffset;
2579 s4 componentsize = sdesc->componentsize;
2581 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2582 ((u1 *) src) + dataoffset + componentsize * srcStart,
2583 (size_t) len * componentsize);
2586 /* We copy references of different type */
2588 java_objectarray *oas = (java_objectarray *) src;
2589 java_objectarray *oad = (java_objectarray *) dest;
2591 if (destStart <= srcStart) {
2592 for (i = 0; i < len; i++) {
2593 java_objectheader *o = oas->data[srcStart + i];
2595 if (!builtin_canstore(oad, o))
2598 oad->data[destStart + i] = o;
2602 /* XXX this does not completely obey the specification!
2603 If an exception is thrown only the elements above the
2604 current index have been copied. The specification
2605 requires that only the elements *below* the current
2606 index have been copied before the throw. */
2608 for (i = len - 1; i >= 0; i--) {
2609 java_objectheader *o = oas->data[srcStart + i];
2611 if (!builtin_canstore(oad, o))
2614 oad->data[destStart + i] = o;
2623 /* builtin_nanotime ************************************************************
2625 Return the current time in nanoseconds.
2627 *******************************************************************************/
2629 s8 builtin_nanotime(void)
2634 if (gettimeofday(&tv, NULL) == -1)
2635 vm_abort("gettimeofday failed: %s", strerror(errno));
2637 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2639 return usecs * 1000;
2643 /* builtin_currenttimemillis ***************************************************
2645 Return the current time in milliseconds.
2647 *******************************************************************************/
2649 s8 builtin_currenttimemillis(void)
2653 msecs = builtin_nanotime() / 1000 / 1000;
2659 /* builtin_clone ***************************************************************
2661 Function for cloning objects or arrays.
2663 *******************************************************************************/
2665 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2667 arraydescriptor *ad;
2668 java_arrayheader *ah;
2671 java_objectheader *co; /* cloned object header */
2673 /* get the array descriptor */
2675 ad = o->vftbl->arraydesc;
2677 /* we are cloning an array */
2680 ah = (java_arrayheader *) o;
2682 size = ad->dataoffset + ad->componentsize * ah->size;
2684 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2689 MCOPY(co, o, u1, size);
2691 #if defined(ENABLE_GC_CACAO)
2692 heap_init_objectheader(co, size);
2695 #if defined(ENABLE_THREADS)
2696 lock_init_object_lock(co);
2702 /* we are cloning a non-array */
2704 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2705 exceptions_throw_clonenotsupportedexception();
2709 /* get the class of the object */
2711 c = o->vftbl->class;
2713 /* create new object */
2715 co = builtin_new(c);
2720 MCOPY(co, o, u1, c->instancesize);
2722 #if defined(ENABLE_GC_CACAO)
2723 heap_init_objectheader(co, c->instancesize);
2726 #if defined(ENABLE_THREADS)
2727 lock_init_object_lock(co);
2733 #if defined(ENABLE_VMLOG)
2735 #include <vmlog_cacao.c>
2740 * These are local overrides for various environment variables in Emacs.
2741 * Please do not remove this and leave it at the end of the file, where
2742 * Emacs will automagically detect them.
2743 * ---------------------------------------------------------------------
2746 * indent-tabs-mode: t
2750 * vim:noexpandtab:sw=4:ts=4: