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 7918 2007-05-20 20:42:18Z michi $
50 #include "fdlibm/fdlibm.h"
51 #if defined(__CYGWIN__) && defined(Bias)
55 #include "mm/gc-common.h"
56 #include "mm/memory.h"
58 #include "native/jni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
62 #include "threads/lock-common.h"
64 #include "toolbox/logging.h"
65 #include "toolbox/util.h"
67 #include "vm/builtin.h"
68 #include "vm/cycles-stats.h"
69 #include "vm/exceptions.h"
70 #include "vm/global.h"
71 #include "vm/initialize.h"
72 #include "vm/stringlocal.h"
74 #include "vm/jit/asmpart.h"
75 #include "vm/jit/patcher.h"
77 #include "vmcore/class.h"
78 #include "vmcore/loader.h"
79 #include "vmcore/options.h"
80 #include "vmcore/rt-timing.h"
82 #if defined(ENABLE_VMLOG)
83 #include <vmlog_cacao.h>
87 /* include builtin tables *****************************************************/
89 #include "vm/builtintable.inc"
92 CYCLES_STATS_DECLARE(builtin_new ,100,5)
93 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
95 /* builtintable_init ***********************************************************
97 Parse the descriptors of builtin functions and create the parsed
100 *******************************************************************************/
102 static bool builtintable_init(void)
104 descriptor_pool *descpool;
106 builtintable_entry *bte;
108 /* mark start of dump memory area */
110 dumpsize = dump_size();
112 /* create a new descriptor pool */
114 descpool = descriptor_pool_new(class_java_lang_Object);
116 /* add some entries we need */
118 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
124 /* first add all descriptors to the pool */
126 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
127 /* create a utf8 string from descriptor */
129 bte->descriptor = utf_new_char(bte->cdescriptor);
131 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
132 /* release dump area */
134 dump_release(dumpsize);
140 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
141 bte->descriptor = utf_new_char(bte->cdescriptor);
143 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
144 dump_release(dumpsize);
149 for (bte = builtintable_function; bte->fp != NULL; bte++) {
150 bte->classname = utf_new_char(bte->cclassname);
151 bte->name = utf_new_char(bte->cname);
152 bte->descriptor = utf_new_char(bte->cdescriptor);
154 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
155 dump_release(dumpsize);
160 /* create the class reference table */
162 (void) descriptor_pool_create_classrefs(descpool, NULL);
164 /* allocate space for the parsed descriptors */
166 descriptor_pool_alloc_parsed_descriptors(descpool);
168 /* now parse all descriptors */
170 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
171 /* parse the descriptor, builtin is always static (no `this' pointer) */
173 bte->md = descriptor_pool_parse_method_descriptor(descpool,
177 /* generate a builtin stub if we need one */
179 if (bte->flags & BUILTINTABLE_FLAG_STUB)
180 codegen_generate_stub_builtin(bte);
183 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
184 bte->md = descriptor_pool_parse_method_descriptor(descpool,
189 for (bte = builtintable_function; bte->fp != NULL; bte++) {
190 bte->md = descriptor_pool_parse_method_descriptor(descpool,
195 /* release dump area */
197 dump_release(dumpsize);
203 /* builtintable_comparator *****************************************************
205 qsort comparator for the automatic builtin table.
207 *******************************************************************************/
209 static int builtintable_comparator(const void *a, const void *b)
211 builtintable_entry *bte1;
212 builtintable_entry *bte2;
214 bte1 = (builtintable_entry *) a;
215 bte2 = (builtintable_entry *) b;
217 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
221 /* builtintable_sort_automatic *************************************************
223 Sorts the automatic builtin table.
225 *******************************************************************************/
227 static void builtintable_sort_automatic(void)
231 /* calculate table size statically (`- 1' comment see builtintable.inc) */
233 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
235 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
236 builtintable_comparator);
240 /* builtin_init ****************************************************************
242 Initialize the global table of builtin functions.
244 *******************************************************************************/
246 bool builtin_init(void)
248 /* initialize the builtin tables */
250 if (!builtintable_init())
253 /* sort builtin tables */
255 builtintable_sort_automatic();
261 /* builtintable_get_internal ***************************************************
263 Finds an entry in the builtintable for internal functions and
264 returns the a pointer to the structure.
266 *******************************************************************************/
268 builtintable_entry *builtintable_get_internal(functionptr fp)
270 builtintable_entry *bte;
272 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
281 /* builtintable_get_automatic **************************************************
283 Finds an entry in the builtintable for functions which are replaced
284 automatically and returns the a pointer to the structure.
286 *******************************************************************************/
288 builtintable_entry *builtintable_get_automatic(s4 opcode)
290 builtintable_entry *first;
291 builtintable_entry *last;
292 builtintable_entry *middle;
296 /* calculate table size statically (`- 1' comment see builtintable.inc) */
298 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
300 first = builtintable_automatic;
301 last = builtintable_automatic + entries;
303 while (entries > 0) {
305 middle = first + half;
307 if (middle->opcode < opcode) {
315 return (first != last ? first : NULL);
319 /* builtintable_replace_function ***********************************************
323 *******************************************************************************/
325 #if defined(ENABLE_JIT)
326 bool builtintable_replace_function(void *iptr_)
329 builtintable_entry *bte;
332 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
334 /* get name and descriptor of the function */
337 case ICMD_INVOKESTATIC:
338 /* The instruction MUST be resolved, otherwise we run into
339 lazy loading troubles. Anyway, we should/can only replace
340 very VM-close functions. */
342 if (INSTRUCTION_IS_UNRESOLVED(iptr))
345 mr = iptr->sx.s23.s3.fmiref;
352 /* search the function table */
354 for (bte = builtintable_function; bte->fp != NULL; bte++) {
355 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
356 (mr->name == bte->name) &&
357 (mr->descriptor == bte->descriptor)) {
359 /* set the values in the instruction */
361 iptr->opc = bte->opcode;
362 iptr->sx.s23.s3.bte = bte;
364 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
365 iptr->flags.bits |= INS_FLAG_CHECK;
367 iptr->flags.bits &= ~INS_FLAG_CHECK;
375 #endif /* defined(ENABLE_JIT) */
378 /*****************************************************************************
380 *****************************************************************************/
382 /* builtin_instanceof **********************************************************
384 Checks if an object is an instance of some given class (or subclass
385 of that class). If class is an interface, checks if the interface
388 Return value: 1 ... o is an instance of class or implements the interface
389 0 ... otherwise or if o == NULL
391 *******************************************************************************/
393 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
398 return class_isanysubclass(o->vftbl->class, class);
403 /* builtin_checkcast ***********************************************************
405 The same as builtin_instanceof except that 1 is returned when o ==
408 *******************************************************************************/
410 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
415 if (class_isanysubclass(o->vftbl->class, class))
422 /* builtin_descriptorscompatible ***********************************************
424 Checks if two array type descriptors are assignment compatible
426 Return value: 1 ... target = desc is possible
429 *******************************************************************************/
431 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
432 arraydescriptor *target)
437 if (desc->arraytype != target->arraytype)
440 if (desc->arraytype != ARRAYTYPE_OBJECT)
443 /* {both arrays are arrays of references} */
445 if (desc->dimension == target->dimension) {
446 /* an array which contains elements of interface types is
447 allowed to be casted to Object (JOWENN)*/
449 if ((desc->elementvftbl->baseval < 0) &&
450 (target->elementvftbl->baseval == 1))
453 return class_isanysubclass(desc->elementvftbl->class,
454 target->elementvftbl->class);
457 if (desc->dimension < target->dimension)
460 /* {desc has higher dimension than target} */
462 return class_isanysubclass(pseudo_class_Arraystub,
463 target->elementvftbl->class);
467 /* builtin_arraycheckcast ******************************************************
469 Checks if an object is really a subtype of the requested array
470 type. The object has to be an array to begin with. For simple
471 arrays (int, short, double, etc.) the types have to match exactly.
472 For arrays of objects, the type of elements in the array has to be
473 a subtype (or the same type) of the requested element type. For
474 arrays of arrays (which in turn can again be arrays of arrays), the
475 types at the lowest level have to satisfy the corresponding sub
478 *******************************************************************************/
480 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
482 arraydescriptor *desc;
487 desc = o->vftbl->arraydesc;
492 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
496 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
501 return builtin_arraycheckcast(o, targetclass);
505 /* builtin_throw_exception *****************************************************
507 Sets the exceptionptr with the thrown exception and prints some
508 debugging information. Called from asm_vm_call_method.
510 *******************************************************************************/
512 void *builtin_throw_exception(java_objectheader *xptr)
515 java_lang_Throwable *t;
521 t = (java_lang_Throwable *) xptr;
523 /* calculate message length */
525 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
529 utf_bytes(xptr->vftbl->class->name);
530 if (t->detailMessage) {
531 logtextlen += strlen(": ") +
532 u2_utflength(t->detailMessage->value->data
533 + t->detailMessage->offset,
534 t->detailMessage->count);
538 logtextlen += strlen("(nil)");
541 /* allocate memory */
543 dumpsize = dump_size();
545 logtext = DMNEW(char, logtextlen);
547 strcpy(logtext, "Builtin exception thrown: ");
550 utf_cat_classname(logtext, xptr->vftbl->class->name);
552 if (t->detailMessage) {
555 buf = javastring_tochar((java_objectheader *) t->detailMessage);
556 strcat(logtext, ": ");
557 strcat(logtext, buf);
558 MFREE(buf, char, strlen(buf) + 1);
562 strcat(logtext, "(nil)");
569 dump_release(dumpsize);
571 #endif /* !defined(NDEBUG) */
573 /* actually set the exception */
575 exceptions_set_exception(xptr);
577 /* Return a NULL pointer. This is required for vm_call_method to
578 check for an exception. This is for convenience. */
584 /* builtin_canstore ************************************************************
586 Checks, if an object can be stored in an array.
588 Return value: 1 ... possible
589 0 ... otherwise (throws an ArrayStoreException)
591 *******************************************************************************/
593 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
595 arraydescriptor *desc;
596 arraydescriptor *valuedesc;
597 vftbl_t *componentvftbl;
600 castinfo classvalues;
606 /* The following is guaranteed (by verifier checks):
608 * *) oa->...vftbl->arraydesc != NULL
609 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
610 * *) o->vftbl is not an interface vftbl
613 desc = oa->header.objheader.vftbl->arraydesc;
614 componentvftbl = desc->componentvftbl;
615 valuevftbl = o->vftbl;
616 valuedesc = valuevftbl->arraydesc;
618 if ((desc->dimension - 1) == 0) {
619 /* {oa is a one-dimensional array} */
620 /* {oa is an array of references} */
622 if (valuevftbl == componentvftbl)
625 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
627 base = classvalues.super_baseval;
630 /* an array of interface references */
632 result = ((valuevftbl->interfacetablelength > -base) &&
633 (valuevftbl->interfacetable[base] != NULL));
636 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
637 <= (unsigned) classvalues.super_diffval);
640 else if (valuedesc == NULL) {
641 /* {oa has dimension > 1} */
642 /* {componentvftbl->arraydesc != NULL} */
644 /* check if o is an array */
649 /* {o is an array} */
651 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
654 /* if not possible, throw an exception */
657 exceptions_throw_arraystoreexception();
665 /* This is an optimized version where a is guaranteed to be one-dimensional */
666 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
668 arraydescriptor *desc;
669 vftbl_t *elementvftbl;
673 castinfo classvalues;
677 /* The following is guaranteed (by verifier checks):
679 * *) a->...vftbl->arraydesc != NULL
680 * *) a->...vftbl->arraydesc->elementvftbl != NULL
681 * *) a->...vftbl->arraydesc->dimension == 1
682 * *) o->vftbl is not an interface vftbl
685 desc = a->header.objheader.vftbl->arraydesc;
686 elementvftbl = desc->elementvftbl;
687 valuevftbl = o->vftbl;
689 /* {a is a one-dimensional array} */
691 if (valuevftbl == elementvftbl)
694 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
696 if ((base = classvalues.super_baseval) <= 0)
697 /* an array of interface references */
698 return (valuevftbl->interfacetablelength > -base &&
699 valuevftbl->interfacetable[base] != NULL);
701 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
702 <= (unsigned) classvalues.super_diffval;
708 /* This is an optimized version where a is guaranteed to be a
709 * one-dimensional array of a class type */
710 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
712 vftbl_t *elementvftbl;
715 castinfo classvalues;
719 /* The following is guaranteed (by verifier checks):
721 * *) a->...vftbl->arraydesc != NULL
722 * *) a->...vftbl->arraydesc->elementvftbl != NULL
723 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
724 * *) a->...vftbl->arraydesc->dimension == 1
725 * *) o->vftbl is not an interface vftbl
728 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
729 valuevftbl = o->vftbl;
731 /* {a is a one-dimensional array} */
733 if (valuevftbl == elementvftbl)
736 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
738 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
739 <= (unsigned) classvalues.super_diffval;
745 /* builtin_new *****************************************************************
747 Creates a new instance of class c on the heap.
749 Return value: pointer to the object or NULL if no memory is
752 *******************************************************************************/
754 java_objectheader *builtin_new(classinfo *c)
756 java_objectheader *o;
757 #if defined(ENABLE_RT_TIMING)
758 struct timespec time_start, time_end;
760 #if defined(ENABLE_CYCLES_STATS)
761 u8 cycles_start, cycles_end;
764 RT_TIMING_GET_TIME(time_start);
765 CYCLES_STATS_GET(cycles_start);
767 /* is the class loaded */
769 assert(c->state & CLASS_LOADED);
771 /* check if we can instantiate this class */
773 if (c->flags & ACC_ABSTRACT) {
774 exceptions_throw_instantiationerror(c);
778 /* is the class linked */
780 if (!(c->state & CLASS_LINKED))
784 if (!(c->state & CLASS_INITIALIZED)) {
787 log_message_class("Initialize class (from builtin_new): ", c);
790 if (!initialize_class(c))
794 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
802 #if defined(ENABLE_THREADS)
803 lock_init_object_lock(o);
806 CYCLES_STATS_GET(cycles_end);
807 RT_TIMING_GET_TIME(time_end);
809 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
810 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
816 /* builtin_fast_new ************************************************************
818 Creates a new instance of class c on the heap.
820 Return value: pointer to the object or NULL if no fast return
821 is possible for any reason.
823 *******************************************************************************/
825 java_objectheader *builtin_fast_new(classinfo *c)
827 java_objectheader *o;
828 #if defined(ENABLE_RT_TIMING)
829 struct timespec time_start, time_end;
831 #if defined(ENABLE_CYCLES_STATS)
832 u8 cycles_start, cycles_end;
835 RT_TIMING_GET_TIME(time_start);
836 CYCLES_STATS_GET(cycles_start);
838 /* is the class loaded */
840 assert(c->state & CLASS_LOADED);
842 /* check if we can instantiate this class */
844 if (c->flags & ACC_ABSTRACT)
847 /* is the class linked */
849 if (!(c->state & CLASS_LINKED))
852 if (!(c->state & CLASS_INITIALIZED))
855 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
856 c->finalizer, false);
863 #if defined(ENABLE_THREADS)
864 lock_init_object_lock(o);
867 CYCLES_STATS_GET(cycles_end);
868 RT_TIMING_GET_TIME(time_end);
870 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
871 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
877 /* builtin_newarray ************************************************************
879 Creates an array with the given vftbl on the heap. This function
880 takes as class argument an array class.
882 Return value: pointer to the array or NULL if no memory is available
884 *******************************************************************************/
886 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
888 arraydescriptor *desc;
893 #if defined(ENABLE_RT_TIMING)
894 struct timespec time_start, time_end;
897 RT_TIMING_GET_TIME(time_start);
899 desc = arrayclass->vftbl->arraydesc;
900 dataoffset = desc->dataoffset;
901 componentsize = desc->componentsize;
904 exceptions_throw_negativearraysizeexception();
908 actualsize = dataoffset + size * componentsize;
910 /* check for overflow */
912 if (((u4) actualsize) < ((u4) size)) {
913 exceptions_throw_outofmemoryerror();
917 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
922 a->objheader.vftbl = arrayclass->vftbl;
924 #if defined(ENABLE_THREADS)
925 lock_init_object_lock(&a->objheader);
930 RT_TIMING_GET_TIME(time_end);
931 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
937 /* builtin_anewarray ***********************************************************
939 Creates an array of references to the given class type on the heap.
941 Return value: pointer to the array or NULL if no memory is
944 *******************************************************************************/
946 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
948 classinfo *arrayclass;
950 /* is class loaded */
952 assert(componentclass->state & CLASS_LOADED);
954 /* is class linked */
956 if (!(componentclass->state & CLASS_LINKED))
957 if (!link_class(componentclass))
960 arrayclass = class_array_of(componentclass, true);
965 return (java_objectarray *) builtin_newarray(size, arrayclass);
969 /* builtin_newarray_boolean ****************************************************
971 Creates an array of bytes on the heap. The array is designated as
972 an array of booleans (important for casts)
974 Return value: pointer to the array or NULL if no memory is
977 *******************************************************************************/
979 java_booleanarray *builtin_newarray_boolean(s4 size)
981 return (java_booleanarray *)
982 builtin_newarray(size,
983 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
987 /* builtin_newarray_byte *******************************************************
989 Creates an array of 8 bit Integers on the heap.
991 Return value: pointer to the array or NULL if no memory is
994 *******************************************************************************/
996 java_bytearray *builtin_newarray_byte(s4 size)
998 return (java_bytearray *)
999 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
1003 /* builtin_newarray_char *******************************************************
1005 Creates an array of characters on the heap.
1007 Return value: pointer to the array or NULL if no memory is
1010 *******************************************************************************/
1012 java_chararray *builtin_newarray_char(s4 size)
1014 return (java_chararray *)
1015 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1019 /* builtin_newarray_short ******************************************************
1021 Creates an array of 16 bit Integers on the heap.
1023 Return value: pointer to the array or NULL if no memory is
1026 *******************************************************************************/
1028 java_shortarray *builtin_newarray_short(s4 size)
1030 return (java_shortarray *)
1031 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1035 /* builtin_newarray_int ********************************************************
1037 Creates an array of 32 bit Integers on the heap.
1039 Return value: pointer to the array or NULL if no memory is
1042 *******************************************************************************/
1044 java_intarray *builtin_newarray_int(s4 size)
1046 return (java_intarray *)
1047 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1051 /* builtin_newarray_long *******************************************************
1053 Creates an array of 64 bit Integers on the heap.
1055 Return value: pointer to the array or NULL if no memory is
1058 *******************************************************************************/
1060 java_longarray *builtin_newarray_long(s4 size)
1062 return (java_longarray *)
1063 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1067 /* builtin_newarray_float ******************************************************
1069 Creates an array of 32 bit IEEE floats on the heap.
1071 Return value: pointer to the array or NULL if no memory is
1074 *******************************************************************************/
1076 java_floatarray *builtin_newarray_float(s4 size)
1078 return (java_floatarray *)
1079 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1083 /* builtin_newarray_double *****************************************************
1085 Creates an array of 64 bit IEEE floats on the heap.
1087 Return value: pointer to the array or NULL if no memory is
1090 *******************************************************************************/
1092 java_doublearray *builtin_newarray_double(s4 size)
1094 return (java_doublearray *)
1095 builtin_newarray(size,
1096 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1100 /* builtin_multianewarray_intern ***********************************************
1102 Creates a multi-dimensional array on the heap. The dimensions are
1103 passed in an array of longs.
1106 n............number of dimensions to create
1107 arrayvftbl...vftbl of the array class
1108 dims.........array containing the size of each dimension to create
1110 Return value: pointer to the array or NULL if no memory is
1113 ******************************************************************************/
1115 static java_arrayheader *builtin_multianewarray_intern(int n,
1116 classinfo *arrayclass,
1120 java_arrayheader *a;
1121 classinfo *componentclass;
1124 /* create this dimension */
1126 size = (s4) dims[0];
1127 a = builtin_newarray(size, arrayclass);
1132 /* if this is the last dimension return */
1137 /* get the class of the components to create */
1139 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1141 /* The verifier guarantees that the dimension count is in the range. */
1143 /* create the component arrays */
1145 for (i = 0; i < size; i++) {
1146 java_arrayheader *ea =
1147 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1148 /* we save an s4 to a s8 slot, 8-byte aligned */
1150 builtin_multianewarray_intern(n, componentclass, dims + 2);
1152 builtin_multianewarray_intern(n, componentclass, dims + 1);
1158 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1165 /* builtin_multianewarray ******************************************************
1167 Wrapper for builtin_multianewarray_intern which checks all
1168 dimensions before we start allocating.
1170 ******************************************************************************/
1172 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1178 /* check all dimensions before doing anything */
1180 for (i = 0; i < n; i++) {
1181 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1182 /* we save an s4 to a s8 slot, 8-byte aligned */
1183 size = (s4) dims[i * 2];
1185 size = (s4) dims[i];
1189 exceptions_throw_negativearraysizeexception();
1194 /* now call the real function */
1196 return builtin_multianewarray_intern(n, arrayclass, dims);
1200 /*****************************************************************************
1203 Various functions for printing a message at method entry or exit (for
1206 *****************************************************************************/
1208 #if !defined(NDEBUG)
1209 static s4 methodindent = 0;
1210 static u4 callcount = 0;
1212 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1222 #if defined(ENABLE_VMLOG)
1226 if (opt_verbosecall && indent)
1229 /* calculate message length */
1233 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1236 logtextlen = strlen("Some Throwable");
1239 logtextlen += strlen(" thrown in ");
1243 utf_bytes(m->class->name) +
1245 utf_bytes(m->name) +
1246 utf_bytes(m->descriptor) +
1247 strlen("(NOSYNC,NATIVE");
1249 #if SIZEOF_VOID_P == 8
1251 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1253 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1256 if (m->class->sourcefile == NULL)
1257 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1259 logtextlen += utf_bytes(m->class->sourcefile);
1261 logtextlen += strlen(":65536)");
1265 logtextlen += strlen("call_java_method");
1268 logtextlen += strlen("0");
1270 /* allocate memory */
1272 dumpsize = dump_size();
1274 logtext = DMNEW(char, logtextlen);
1277 strcpy(logtext, "Exception ");
1278 utf_cat_classname(logtext, xptr->vftbl->class->name);
1281 strcpy(logtext, "Some Throwable");
1284 strcat(logtext, " thrown in ");
1287 utf_cat_classname(logtext, m->class->name);
1288 strcat(logtext, ".");
1289 utf_cat(logtext, m->name);
1290 utf_cat(logtext, m->descriptor);
1292 if (m->flags & ACC_SYNCHRONIZED)
1293 strcat(logtext, "(SYNC");
1295 strcat(logtext, "(NOSYNC");
1297 if (m->flags & ACC_NATIVE) {
1298 strcat(logtext, ",NATIVE");
1302 #if SIZEOF_VOID_P == 8
1303 sprintf(logtext + strlen(logtext),
1304 ")(0x%016lx) at position 0x%016lx",
1305 (ptrint) code->entrypoint, (ptrint) pos);
1307 sprintf(logtext + strlen(logtext),
1308 ")(0x%08x) at position 0x%08x",
1309 (ptrint) code->entrypoint, (ptrint) pos);
1314 /* XXX preliminary: This should get the actual codeinfo */
1315 /* in which the exception happened. */
1318 #if SIZEOF_VOID_P == 8
1319 sprintf(logtext + strlen(logtext),
1320 ")(0x%016lx) at position 0x%016lx (",
1321 (ptrint) code->entrypoint, (ptrint) pos);
1323 sprintf(logtext + strlen(logtext),
1324 ")(0x%08x) at position 0x%08x (",
1325 (ptrint) code->entrypoint, (ptrint) pos);
1328 if (m->class->sourcefile == NULL)
1329 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1331 utf_cat(logtext, m->class->sourcefile);
1333 sprintf(logtext + strlen(logtext), ":%d)", 0);
1337 strcat(logtext, "call_java_method");
1341 /* release memory */
1343 dump_release(dumpsize);
1347 #endif /* !defined(NDEBUG) */
1350 /* builtin_print_argument ******************************************************
1352 Prints arguments and return values for the call trace.
1354 *******************************************************************************/
1356 #if !defined(NDEBUG)
1357 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1358 typedesc *paramtype, s8 value)
1361 java_objectheader *o;
1366 switch (paramtype->type) {
1369 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1374 #if SIZEOF_VOID_P == 4
1375 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1377 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1383 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1388 #if SIZEOF_VOID_P == 4
1389 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1391 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1396 #if SIZEOF_VOID_P == 4
1397 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1399 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1402 /* cast to java.lang.Object */
1404 o = (java_objectheader *) (ptrint) value;
1406 /* check return argument for java.lang.Class or java.lang.String */
1409 if (o->vftbl->class == class_java_lang_String) {
1410 /* get java.lang.String object and the length of the
1413 u = javastring_toutf(o, false);
1415 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1417 /* realloc memory for string length */
1419 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1422 /* convert to utf8 string and strcat it to the logtext */
1424 strcat(logtext, " (String = \"");
1425 utf_cat(logtext, u);
1426 strcat(logtext, "\")");
1429 if (o->vftbl->class == class_java_lang_Class) {
1430 /* if the object returned is a java.lang.Class
1431 cast it to classinfo structure and get the name
1434 c = (classinfo *) o;
1439 /* if the object returned is not a java.lang.String or
1440 a java.lang.Class just print the name of the class */
1442 u = o->vftbl->class->name;
1445 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1447 /* realloc memory for string length */
1449 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1452 /* strcat to the logtext */
1454 strcat(logtext, " (Class = \"");
1455 utf_cat_classname(logtext, u);
1456 strcat(logtext, "\")");
1463 #endif /* !defined(NDEBUG) */
1466 /* builtin_verbosecall_enter ***************************************************
1468 Print method call with arguments for -verbose:call.
1470 *******************************************************************************/
1472 #if !defined(NDEBUG)
1474 #ifdef TRACE_ARGS_NUM
1475 void builtin_verbosecall_enter(s8 a0, s8 a1,
1476 # if TRACE_ARGS_NUM >= 4
1479 # if TRACE_ARGS_NUM >= 6
1482 # if TRACE_ARGS_NUM == 8
1494 #if defined(ENABLE_VMLOG)
1495 vmlog_cacao_enter_method(m);
1501 /* calculate message length */
1504 strlen("4294967295 ") +
1505 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1507 strlen("called: ") +
1508 utf_bytes(m->class->name) +
1510 utf_bytes(m->name) +
1511 utf_bytes(m->descriptor);
1513 /* Actually it's not possible to have all flags printed, but:
1518 strlen(" PRIVATE") +
1519 strlen(" PROTECTED") +
1522 strlen(" SYNCHRONIZED") +
1523 strlen(" VOLATILE") +
1524 strlen(" TRANSIENT") +
1526 strlen(" INTERFACE") +
1527 strlen(" ABSTRACT");
1529 /* add maximal argument length */
1533 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1534 strlen("...(255)") +
1537 /* allocate memory */
1539 dumpsize = dump_size();
1541 logtext = DMNEW(char, logtextlen);
1545 sprintf(logtext, "%10d ", callcount);
1546 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1548 pos = strlen(logtext);
1550 for (i = 0; i < methodindent; i++)
1551 logtext[pos++] = '\t';
1553 strcpy(logtext + pos, "called: ");
1555 utf_cat_classname(logtext, m->class->name);
1556 strcat(logtext, ".");
1557 utf_cat(logtext, m->name);
1558 utf_cat(logtext, m->descriptor);
1560 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1561 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1562 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1563 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1564 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1565 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1566 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1567 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1568 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1569 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1570 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1572 strcat(logtext, "(");
1574 if (md->paramcount >= 1) {
1575 logtext = builtin_print_argument(logtext, &logtextlen,
1576 &md->paramtypes[0], a0);
1579 if (md->paramcount >= 2) {
1580 strcat(logtext, ", ");
1582 logtext = builtin_print_argument(logtext, &logtextlen,
1583 &md->paramtypes[1], a1);
1586 #if TRACE_ARGS_NUM >= 4
1587 if (md->paramcount >= 3) {
1588 strcat(logtext, ", ");
1590 logtext = builtin_print_argument(logtext, &logtextlen,
1591 &md->paramtypes[2], a2);
1594 if (md->paramcount >= 4) {
1595 strcat(logtext, ", ");
1597 logtext = builtin_print_argument(logtext, &logtextlen,
1598 &md->paramtypes[3], a3);
1602 #if TRACE_ARGS_NUM >= 6
1603 if (md->paramcount >= 5) {
1604 strcat(logtext, ", ");
1606 logtext = builtin_print_argument(logtext, &logtextlen,
1607 &md->paramtypes[4], a4);
1610 if (md->paramcount >= 6) {
1611 strcat(logtext, ", ");
1613 logtext = builtin_print_argument(logtext, &logtextlen,
1614 &md->paramtypes[5], a5);
1618 #if TRACE_ARGS_NUM == 8
1619 if (md->paramcount >= 7) {
1620 strcat(logtext, ", ");
1622 logtext = builtin_print_argument(logtext, &logtextlen,
1623 &md->paramtypes[6], a6);
1626 if (md->paramcount >= 8) {
1627 strcat(logtext, ", ");
1629 logtext = builtin_print_argument(logtext, &logtextlen,
1630 &md->paramtypes[7], a7);
1634 if (md->paramcount > 8) {
1635 sprintf(logtext + strlen(logtext), ", ...(%d)",
1636 md->paramcount - TRACE_ARGS_NUM);
1639 strcat(logtext, ")");
1643 /* release memory */
1645 dump_release(dumpsize);
1650 #endif /* !defined(NDEBUG) */
1653 /* builtin_verbosecall_exit ****************************************************
1655 Print method exit for -verbose:call.
1657 *******************************************************************************/
1659 #if !defined(NDEBUG)
1660 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1670 #if defined(ENABLE_VMLOG)
1671 vmlog_cacao_leave_method(m);
1677 /* calculate message length */
1680 strlen("4294967295 ") +
1681 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1683 strlen("finished: ") +
1684 utf_bytes(m->class->name) +
1686 utf_bytes(m->name) +
1687 utf_bytes(m->descriptor) +
1688 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1690 /* add maximal argument length */
1692 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1694 /* allocate memory */
1696 dumpsize = dump_size();
1698 logtext = DMNEW(char, logtextlen);
1700 /* outdent the log message */
1705 log_text("WARNING: unmatched methodindent--");
1707 /* generate the message */
1709 sprintf(logtext, " ");
1710 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1712 pos = strlen(logtext);
1714 for (i = 0; i < methodindent; i++)
1715 logtext[pos++] = '\t';
1717 strcpy(logtext + pos, "finished: ");
1718 utf_cat_classname(logtext, m->class->name);
1719 strcat(logtext, ".");
1720 utf_cat(logtext, m->name);
1721 utf_cat(logtext, m->descriptor);
1723 if (!IS_VOID_TYPE(md->returntype.type)) {
1724 strcat(logtext, "->");
1726 switch (md->returntype.type) {
1743 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1748 /* release memory */
1750 dump_release(dumpsize);
1752 #endif /* !defined(NDEBUG) */
1755 #if defined(ENABLE_CYCLES_STATS)
1756 void builtin_print_cycles_stats(FILE *file)
1758 fprintf(file,"builtin cylce count statistics:\n");
1760 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1761 CYCLES_STATS_PRINT(builtin_new ,file);
1765 #endif /* defined(ENABLE_CYCLES_STATS) */
1768 /*****************************************************************************
1769 MISCELLANEOUS HELPER FUNCTIONS
1770 *****************************************************************************/
1774 /*********** Functions for integer divisions *****************************
1776 On some systems (eg. DEC ALPHA), integer division is not supported by the
1777 CPU. These helper functions implement the missing functionality.
1779 ******************************************************************************/
1781 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1782 s4 builtin_idiv(s4 a, s4 b)
1791 s4 builtin_irem(s4 a, s4 b)
1799 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1802 /* functions for long arithmetics **********************************************
1804 On systems where 64 bit Integers are not supported by the CPU,
1805 these functions are needed.
1807 ******************************************************************************/
1809 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1810 s8 builtin_ladd(s8 a, s8 b)
1823 s8 builtin_lsub(s8 a, s8 b)
1836 s8 builtin_lneg(s8 a)
1848 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1851 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1852 s8 builtin_lmul(s8 a, s8 b)
1864 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1867 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1868 s8 builtin_ldiv(s8 a, s8 b)
1881 s8 builtin_lrem(s8 a, s8 b)
1893 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1896 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1897 s8 builtin_lshl(s8 a, s4 b)
1910 s8 builtin_lshr(s8 a, s4 b)
1923 s8 builtin_lushr(s8 a, s4 b)
1928 c = ((u8) a) >> (b & 63);
1935 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1938 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1939 s8 builtin_land(s8 a, s8 b)
1952 s8 builtin_lor(s8 a, s8 b)
1965 s8 builtin_lxor(s8 a, s8 b)
1977 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1980 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1981 s4 builtin_lcmp(s8 a, s8 b)
1995 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1998 /* functions for unsupported floating instructions ****************************/
2000 /* used to convert FLT_xxx defines into float values */
2002 static inline float intBitsToFloat(s4 i)
2011 /* used to convert DBL_xxx defines into double values */
2013 static inline float longBitsToDouble(s8 l)
2023 float builtin_fadd(float a, float b)
2025 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2026 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2037 if (copysignf(1.0, a) == copysignf(1.0, b))
2040 return intBitsToFloat(FLT_NAN);
2046 float builtin_fsub(float a, float b)
2048 return builtin_fadd(a, builtin_fneg(b));
2052 float builtin_fmul(float a, float b)
2054 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2055 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2057 if (finitef(b)) return a * b;
2059 if (a == 0) return intBitsToFloat(FLT_NAN);
2060 else return copysignf(b, copysignf(1.0, b)*a);
2065 if (b == 0) return intBitsToFloat(FLT_NAN);
2066 else return copysignf(a, copysignf(1.0, a)*b);
2069 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2075 /* builtin_ddiv ****************************************************************
2077 Implementation as described in VM Spec.
2079 *******************************************************************************/
2081 float builtin_fdiv(float a, float b)
2085 /* If neither value1' nor value2' is NaN, the sign of the result */
2086 /* is positive if both values have the same sign, negative if the */
2087 /* values have different signs. */
2093 /* If either value1' or value2' is NaN, the result is NaN. */
2095 return intBitsToFloat(FLT_NAN);
2098 /* Division of a finite value by an infinity results in a */
2099 /* signed zero, with the sign-producing rule just given. */
2101 /* is sign equal? */
2103 if (copysignf(1.0, a) == copysignf(1.0, b))
2112 /* If either value1' or value2' is NaN, the result is NaN. */
2114 return intBitsToFloat(FLT_NAN);
2116 } else if (finitef(b)) {
2117 /* Division of an infinity by a finite value results in a signed */
2118 /* infinity, with the sign-producing rule just given. */
2120 /* is sign equal? */
2122 if (copysignf(1.0, a) == copysignf(1.0, b))
2123 return intBitsToFloat(FLT_POSINF);
2125 return intBitsToFloat(FLT_NEGINF);
2128 /* Division of an infinity by an infinity results in NaN. */
2130 return intBitsToFloat(FLT_NAN);
2136 float builtin_fneg(float a)
2138 if (isnanf(a)) return a;
2140 if (finitef(a)) return -a;
2141 else return copysignf(a, -copysignf(1.0, a));
2144 #endif /* !SUPPORT_FLOAT */
2147 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2148 s4 builtin_fcmpl(float a, float b)
2156 if (!finitef(a) || !finitef(b)) {
2157 a = finitef(a) ? 0 : copysignf(1.0, a);
2158 b = finitef(b) ? 0 : copysignf(1.0, b);
2171 s4 builtin_fcmpg(float a, float b)
2173 if (isnanf(a)) return 1;
2174 if (isnanf(b)) return 1;
2175 if (!finitef(a) || !finitef(b)) {
2176 a = finitef(a) ? 0 : copysignf(1.0, a);
2177 b = finitef(b) ? 0 : copysignf(1.0, b);
2179 if (a > b) return 1;
2180 if (a == b) return 0;
2183 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2186 float builtin_frem(float a, float b)
2192 /* functions for unsupported double instructions ******************************/
2195 double builtin_dadd(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;
2204 if (finite(b)) return a;
2206 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2207 else return longBitsToDouble(DBL_NAN);
2213 double builtin_dsub(double a, double b)
2215 return builtin_dadd(a, builtin_dneg(b));
2219 double builtin_dmul(double a, double b)
2221 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2222 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2224 if (finite(b)) return a * b;
2226 if (a == 0) return longBitsToDouble(DBL_NAN);
2227 else return copysign(b, copysign(1.0, b) * a);
2232 if (b == 0) return longBitsToDouble(DBL_NAN);
2233 else return copysign(a, copysign(1.0, a) * b);
2236 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2242 /* builtin_ddiv ****************************************************************
2244 Implementation as described in VM Spec.
2246 *******************************************************************************/
2248 double builtin_ddiv(double a, double b)
2252 /* If neither value1' nor value2' is NaN, the sign of the result */
2253 /* is positive if both values have the same sign, negative if the */
2254 /* values have different signs. */
2260 /* If either value1' or value2' is NaN, the result is NaN. */
2262 return longBitsToDouble(DBL_NAN);
2265 /* Division of a finite value by an infinity results in a */
2266 /* signed zero, with the sign-producing rule just given. */
2268 /* is sign equal? */
2270 if (copysign(1.0, a) == copysign(1.0, b))
2279 /* If either value1' or value2' is NaN, the result is NaN. */
2281 return longBitsToDouble(DBL_NAN);
2283 } else if (finite(b)) {
2284 /* Division of an infinity by a finite value results in a signed */
2285 /* infinity, with the sign-producing rule just given. */
2287 /* is sign equal? */
2289 if (copysign(1.0, a) == copysign(1.0, b))
2290 return longBitsToDouble(DBL_POSINF);
2292 return longBitsToDouble(DBL_NEGINF);
2295 /* Division of an infinity by an infinity results in NaN. */
2297 return longBitsToDouble(DBL_NAN);
2303 /* builtin_dneg ****************************************************************
2305 Implemented as described in VM Spec.
2307 *******************************************************************************/
2309 double builtin_dneg(double a)
2312 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2319 /* If the operand is a zero, the result is the zero of opposite */
2325 /* If the operand is an infinity, the result is the infinity of */
2326 /* opposite sign. */
2328 return copysign(a, -copysign(1.0, a));
2332 #endif /* !SUPPORT_DOUBLE */
2335 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2336 s4 builtin_dcmpl(double a, double b)
2344 if (!finite(a) || !finite(b)) {
2345 a = finite(a) ? 0 : copysign(1.0, a);
2346 b = finite(b) ? 0 : copysign(1.0, b);
2359 s4 builtin_dcmpg(double a, double b)
2367 if (!finite(a) || !finite(b)) {
2368 a = finite(a) ? 0 : copysign(1.0, a);
2369 b = finite(b) ? 0 : copysign(1.0, b);
2380 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2383 double builtin_drem(double a, double b)
2389 /* conversion operations ******************************************************/
2392 s8 builtin_i2l(s4 i)
2404 s4 builtin_l2i(s8 l)
2415 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2416 float builtin_i2f(s4 a)
2418 float f = (float) a;
2421 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2424 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2425 double builtin_i2d(s4 a)
2427 double d = (double) a;
2430 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2433 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2434 float builtin_l2f(s8 a)
2437 float f = (float) a;
2443 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2446 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2447 double builtin_l2d(s8 a)
2450 double d = (double) a;
2456 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2459 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2460 s4 builtin_f2i(float a)
2464 i = builtin_d2i((double) a);
2475 if (a < (-2147483648))
2476 return (-2147483648);
2479 f = copysignf((float) 1.0, a);
2482 return (-2147483648); */
2484 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2487 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2488 s8 builtin_f2l(float a)
2492 l = builtin_d2l((double) a);
2499 if (a > 9223372036854775807L)
2500 return 9223372036854775807L;
2501 if (a < (-9223372036854775808L))
2502 return (-9223372036854775808L);
2507 f = copysignf((float) 1.0, a);
2509 return 9223372036854775807L;
2510 return (-9223372036854775808L); */
2512 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2515 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2516 s4 builtin_d2i(double a)
2521 if (a >= 2147483647)
2523 if (a <= (-2147483647-1))
2524 return (-2147483647-1);
2529 d = copysign(1.0, a);
2532 return (-2147483647-1);
2534 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2537 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2538 s8 builtin_d2l(double a)
2543 if (a >= 9223372036854775807LL)
2544 return 9223372036854775807LL;
2545 if (a <= (-9223372036854775807LL-1))
2546 return (-9223372036854775807LL-1);
2551 d = copysign(1.0, a);
2553 return 9223372036854775807LL;
2554 return (-9223372036854775807LL-1);
2556 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2559 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2560 double builtin_f2d(float a)
2562 if (finitef(a)) return (double) a;
2565 return longBitsToDouble(DBL_NAN);
2567 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2571 float builtin_d2f(double a)
2577 return intBitsToFloat(FLT_NAN);
2579 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2582 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2585 /* builtin_arraycopy ***********************************************************
2587 Builtin for java.lang.System.arraycopy.
2589 ATTENTION: This builtin function returns a boolean value to signal
2590 the ICMD_BUILTIN if there was an exception.
2592 *******************************************************************************/
2594 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2595 java_arrayheader *dest, s4 destStart, s4 len)
2597 arraydescriptor *sdesc;
2598 arraydescriptor *ddesc;
2601 if ((src == NULL) || (dest == NULL)) {
2602 exceptions_throw_nullpointerexception();
2606 sdesc = src->objheader.vftbl->arraydesc;
2607 ddesc = dest->objheader.vftbl->arraydesc;
2609 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2610 exceptions_throw_arraystoreexception();
2614 /* we try to throw exception with the same message as SUN does */
2616 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2617 (srcStart + len < 0) || (srcStart + len > src->size) ||
2618 (destStart + len < 0) || (destStart + len > dest->size)) {
2619 exceptions_throw_arrayindexoutofboundsexception();
2623 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2624 /* We copy primitive values or references of exactly the same type */
2626 s4 dataoffset = sdesc->dataoffset;
2627 s4 componentsize = sdesc->componentsize;
2629 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2630 ((u1 *) src) + dataoffset + componentsize * srcStart,
2631 (size_t) len * componentsize);
2634 /* We copy references of different type */
2636 java_objectarray *oas = (java_objectarray *) src;
2637 java_objectarray *oad = (java_objectarray *) dest;
2639 if (destStart <= srcStart) {
2640 for (i = 0; i < len; i++) {
2641 java_objectheader *o = oas->data[srcStart + i];
2643 if (!builtin_canstore(oad, o))
2646 oad->data[destStart + i] = o;
2650 /* XXX this does not completely obey the specification!
2651 If an exception is thrown only the elements above the
2652 current index have been copied. The specification
2653 requires that only the elements *below* the current
2654 index have been copied before the throw. */
2656 for (i = len - 1; i >= 0; i--) {
2657 java_objectheader *o = oas->data[srcStart + i];
2659 if (!builtin_canstore(oad, o))
2662 oad->data[destStart + i] = o;
2671 /* builtin_currenttimemillis ***************************************************
2673 Return the current time in milliseconds.
2675 *******************************************************************************/
2677 s8 builtin_currenttimemillis(void)
2682 if (gettimeofday(&tv, NULL) == -1)
2683 vm_abort("gettimeofday failed: %s", strerror(errno));
2685 result = (s8) tv.tv_sec;
2687 result += (tv.tv_usec / 1000);
2693 /* builtin_clone ***************************************************************
2695 Function for cloning objects or arrays.
2697 *******************************************************************************/
2699 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2701 arraydescriptor *ad;
2702 java_arrayheader *ah;
2705 java_objectheader *co; /* cloned object header */
2707 /* get the array descriptor */
2709 ad = o->vftbl->arraydesc;
2711 /* we are cloning an array */
2714 ah = (java_arrayheader *) o;
2716 size = ad->dataoffset + ad->componentsize * ah->size;
2718 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2723 MCOPY(co, o, u1, size);
2725 #if defined(ENABLE_GC_CACAO)
2726 heap_init_objectheader(co, size);
2729 #if defined(ENABLE_THREADS)
2730 lock_init_object_lock(co);
2736 /* we are cloning a non-array */
2738 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2739 exceptions_throw_clonenotsupportedexception();
2743 /* get the class of the object */
2745 c = o->vftbl->class;
2747 /* create new object */
2749 co = builtin_new(c);
2754 MCOPY(co, o, u1, c->instancesize);
2756 #if defined(ENABLE_GC_CACAO)
2757 heap_init_objectheader(co, c->instancesize);
2760 #if defined(ENABLE_THREADS)
2761 lock_init_object_lock(co);
2767 #if defined(ENABLE_VMLOG)
2769 #include <vmlog_cacao.c>
2774 * These are local overrides for various environment variables in Emacs.
2775 * Please do not remove this and leave it at the end of the file, where
2776 * Emacs will automagically detect them.
2777 * ---------------------------------------------------------------------
2780 * indent-tabs-mode: t
2784 * vim:noexpandtab:sw=4:ts=4: