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 8245 2007-07-31 09:55:04Z michi $
49 #include "fdlibm/fdlibm.h"
50 #if defined(__CYGWIN__) && defined(Bias)
54 #include "mm/gc-common.h"
55 #include "mm/memory.h"
57 #include "native/jni.h"
58 #include "native/include/java_lang_String.h"
59 #include "native/include/java_lang_Throwable.h"
61 #include "threads/lock-common.h"
63 #include "toolbox/logging.h"
64 #include "toolbox/util.h"
66 #include "vm/builtin.h"
67 #include "vm/cycles-stats.h"
68 #include "vm/exceptions.h"
69 #include "vm/global.h"
70 #include "vm/initialize.h"
71 #include "vm/stringlocal.h"
73 #include "vm/jit/asmpart.h"
75 #include "vmcore/class.h"
76 #include "vmcore/loader.h"
77 #include "vmcore/options.h"
78 #include "vmcore/primitive.h"
79 #include "vmcore/rt-timing.h"
81 #if defined(ENABLE_VMLOG)
82 #include <vmlog_cacao.h>
85 #if defined(ENABLE_DEBUG_FILTER)
86 # include "vm/jit/show.h"
89 /* include builtin tables *****************************************************/
91 #include "vm/builtintable.inc"
94 CYCLES_STATS_DECLARE(builtin_new ,100,5)
95 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
97 /* builtintable_init ***********************************************************
99 Parse the descriptors of builtin functions and create the parsed
102 *******************************************************************************/
104 static bool builtintable_init(void)
106 descriptor_pool *descpool;
108 builtintable_entry *bte;
110 /* mark start of dump memory area */
112 dumpsize = dump_size();
114 /* create a new descriptor pool */
116 descpool = descriptor_pool_new(class_java_lang_Object);
118 /* add some entries we need */
120 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
123 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
126 /* first add all descriptors to the pool */
128 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
129 /* create a utf8 string from descriptor */
131 bte->descriptor = utf_new_char(bte->cdescriptor);
133 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
134 /* release dump area */
136 dump_release(dumpsize);
142 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
143 bte->descriptor = utf_new_char(bte->cdescriptor);
145 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
146 dump_release(dumpsize);
151 for (bte = builtintable_function; bte->fp != NULL; bte++) {
152 bte->classname = utf_new_char(bte->cclassname);
153 bte->name = utf_new_char(bte->cname);
154 bte->descriptor = utf_new_char(bte->cdescriptor);
156 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
157 dump_release(dumpsize);
162 /* create the class reference table */
164 (void) descriptor_pool_create_classrefs(descpool, NULL);
166 /* allocate space for the parsed descriptors */
168 descriptor_pool_alloc_parsed_descriptors(descpool);
170 /* Now parse all descriptors. NOTE: builtin-functions are treated
171 like static methods (no `this' pointer). */
173 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
175 descriptor_pool_parse_method_descriptor(descpool,
177 ACC_STATIC | ACC_METHOD_BUILTIN,
180 /* generate a builtin stub if we need one */
182 if (bte->flags & BUILTINTABLE_FLAG_STUB)
183 codegen_generate_stub_builtin(bte);
186 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
188 descriptor_pool_parse_method_descriptor(descpool,
190 ACC_STATIC | ACC_METHOD_BUILTIN,
194 for (bte = builtintable_function; bte->fp != NULL; bte++) {
196 descriptor_pool_parse_method_descriptor(descpool,
198 ACC_STATIC | ACC_METHOD_BUILTIN,
202 /* release dump area */
204 dump_release(dumpsize);
210 /* builtintable_comparator *****************************************************
212 qsort comparator for the automatic builtin table.
214 *******************************************************************************/
216 static int builtintable_comparator(const void *a, const void *b)
218 builtintable_entry *bte1;
219 builtintable_entry *bte2;
221 bte1 = (builtintable_entry *) a;
222 bte2 = (builtintable_entry *) b;
224 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
228 /* builtintable_sort_automatic *************************************************
230 Sorts the automatic builtin table.
232 *******************************************************************************/
234 static void builtintable_sort_automatic(void)
238 /* calculate table size statically (`- 1' comment see builtintable.inc) */
240 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
242 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
243 builtintable_comparator);
247 /* builtin_init ****************************************************************
249 Initialize the global table of builtin functions.
251 *******************************************************************************/
253 bool builtin_init(void)
255 /* initialize the builtin tables */
257 if (!builtintable_init())
260 /* sort builtin tables */
262 builtintable_sort_automatic();
268 /* builtintable_get_internal ***************************************************
270 Finds an entry in the builtintable for internal functions and
271 returns the a pointer to the structure.
273 *******************************************************************************/
275 builtintable_entry *builtintable_get_internal(functionptr fp)
277 builtintable_entry *bte;
279 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
288 /* builtintable_get_automatic **************************************************
290 Finds an entry in the builtintable for functions which are replaced
291 automatically and returns the a pointer to the structure.
293 *******************************************************************************/
295 builtintable_entry *builtintable_get_automatic(s4 opcode)
297 builtintable_entry *first;
298 builtintable_entry *last;
299 builtintable_entry *middle;
303 /* calculate table size statically (`- 1' comment see builtintable.inc) */
305 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
307 first = builtintable_automatic;
308 last = builtintable_automatic + entries;
310 while (entries > 0) {
312 middle = first + half;
314 if (middle->opcode < opcode) {
322 return (first != last ? first : NULL);
326 /* builtintable_replace_function ***********************************************
330 *******************************************************************************/
332 #if defined(ENABLE_JIT)
333 bool builtintable_replace_function(void *iptr_)
336 builtintable_entry *bte;
339 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
341 /* get name and descriptor of the function */
344 case ICMD_INVOKESTATIC:
345 /* The instruction MUST be resolved, otherwise we run into
346 lazy loading troubles. Anyway, we should/can only replace
347 very VM-close functions. */
349 if (INSTRUCTION_IS_UNRESOLVED(iptr))
352 mr = iptr->sx.s23.s3.fmiref;
359 /* search the function table */
361 for (bte = builtintable_function; bte->fp != NULL; bte++) {
362 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
363 (mr->name == bte->name) &&
364 (mr->descriptor == bte->descriptor)) {
366 /* set the values in the instruction */
368 iptr->opc = bte->opcode;
369 iptr->sx.s23.s3.bte = bte;
371 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
372 iptr->flags.bits |= INS_FLAG_CHECK;
374 iptr->flags.bits &= ~INS_FLAG_CHECK;
382 #endif /* defined(ENABLE_JIT) */
385 /*****************************************************************************
387 *****************************************************************************/
389 /* builtin_instanceof **********************************************************
391 Checks if an object is an instance of some given class (or subclass
392 of that class). If class is an interface, checks if the interface
395 Return value: 1 ... o is an instance of class or implements the interface
396 0 ... otherwise or if o == NULL
398 *******************************************************************************/
400 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
405 return class_isanysubclass(o->vftbl->class, class);
410 /* builtin_checkcast ***********************************************************
412 The same as builtin_instanceof except that 1 is returned when o ==
415 *******************************************************************************/
417 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
422 if (class_isanysubclass(o->vftbl->class, class))
429 /* builtin_descriptorscompatible ***********************************************
431 Checks if two array type descriptors are assignment compatible
433 Return value: 1 ... target = desc is possible
436 *******************************************************************************/
438 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
439 arraydescriptor *target)
444 if (desc->arraytype != target->arraytype)
447 if (desc->arraytype != ARRAYTYPE_OBJECT)
450 /* {both arrays are arrays of references} */
452 if (desc->dimension == target->dimension) {
453 /* an array which contains elements of interface types is
454 allowed to be casted to Object (JOWENN)*/
456 if ((desc->elementvftbl->baseval < 0) &&
457 (target->elementvftbl->baseval == 1))
460 return class_isanysubclass(desc->elementvftbl->class,
461 target->elementvftbl->class);
464 if (desc->dimension < target->dimension)
467 /* {desc has higher dimension than target} */
469 return class_isanysubclass(pseudo_class_Arraystub,
470 target->elementvftbl->class);
474 /* builtin_arraycheckcast ******************************************************
476 Checks if an object is really a subtype of the requested array
477 type. The object has to be an array to begin with. For simple
478 arrays (int, short, double, etc.) the types have to match exactly.
479 For arrays of objects, the type of elements in the array has to be
480 a subtype (or the same type) of the requested element type. For
481 arrays of arrays (which in turn can again be arrays of arrays), the
482 types at the lowest level have to satisfy the corresponding sub
485 *******************************************************************************/
487 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
489 arraydescriptor *desc;
494 desc = o->vftbl->arraydesc;
499 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
503 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
508 return builtin_arraycheckcast(o, targetclass);
512 /* builtin_throw_exception *****************************************************
514 Sets the exceptionptr with the thrown exception and prints some
515 debugging information. Called from asm_vm_call_method.
517 *******************************************************************************/
519 void *builtin_throw_exception(java_objectheader *xptr)
522 java_lang_Throwable *t;
528 t = (java_lang_Throwable *) xptr;
530 /* calculate message length */
532 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
536 utf_bytes(xptr->vftbl->class->name);
537 if (t->detailMessage) {
538 logtextlen += strlen(": ") +
539 u2_utflength(t->detailMessage->value->data
540 + t->detailMessage->offset,
541 t->detailMessage->count);
545 logtextlen += strlen("(nil)");
548 /* allocate memory */
550 dumpsize = dump_size();
552 logtext = DMNEW(char, logtextlen);
554 strcpy(logtext, "Builtin exception thrown: ");
557 utf_cat_classname(logtext, xptr->vftbl->class->name);
559 if (t->detailMessage) {
562 buf = javastring_tochar((java_objectheader *) t->detailMessage);
563 strcat(logtext, ": ");
564 strcat(logtext, buf);
565 MFREE(buf, char, strlen(buf) + 1);
569 strcat(logtext, "(nil)");
576 dump_release(dumpsize);
578 #endif /* !defined(NDEBUG) */
580 /* actually set the exception */
582 exceptions_set_exception(xptr);
584 /* Return a NULL pointer. This is required for vm_call_method to
585 check for an exception. This is for convenience. */
591 /* builtin_canstore ************************************************************
593 Checks, if an object can be stored in an array.
595 Return value: 1 ... possible
596 0 ... otherwise (throws an ArrayStoreException)
598 *******************************************************************************/
600 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
602 arraydescriptor *desc;
603 arraydescriptor *valuedesc;
604 vftbl_t *componentvftbl;
607 castinfo classvalues;
613 /* The following is guaranteed (by verifier checks):
615 * *) oa->...vftbl->arraydesc != NULL
616 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
617 * *) o->vftbl is not an interface vftbl
620 desc = oa->header.objheader.vftbl->arraydesc;
621 componentvftbl = desc->componentvftbl;
622 valuevftbl = o->vftbl;
623 valuedesc = valuevftbl->arraydesc;
625 if ((desc->dimension - 1) == 0) {
626 /* {oa is a one-dimensional array} */
627 /* {oa is an array of references} */
629 if (valuevftbl == componentvftbl)
632 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
634 base = classvalues.super_baseval;
637 /* an array of interface references */
639 result = ((valuevftbl->interfacetablelength > -base) &&
640 (valuevftbl->interfacetable[base] != NULL));
643 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
644 <= (unsigned) classvalues.super_diffval);
647 else if (valuedesc == NULL) {
648 /* {oa has dimension > 1} */
649 /* {componentvftbl->arraydesc != NULL} */
651 /* check if o is an array */
656 /* {o is an array} */
658 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
661 /* if not possible, throw an exception */
664 exceptions_throw_arraystoreexception();
672 /* This is an optimized version where a is guaranteed to be one-dimensional */
673 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
675 arraydescriptor *desc;
676 vftbl_t *elementvftbl;
680 castinfo classvalues;
684 /* The following is guaranteed (by verifier checks):
686 * *) a->...vftbl->arraydesc != NULL
687 * *) a->...vftbl->arraydesc->elementvftbl != NULL
688 * *) a->...vftbl->arraydesc->dimension == 1
689 * *) o->vftbl is not an interface vftbl
692 desc = a->header.objheader.vftbl->arraydesc;
693 elementvftbl = desc->elementvftbl;
694 valuevftbl = o->vftbl;
696 /* {a is a one-dimensional array} */
698 if (valuevftbl == elementvftbl)
701 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
703 if ((base = classvalues.super_baseval) <= 0)
704 /* an array of interface references */
705 return (valuevftbl->interfacetablelength > -base &&
706 valuevftbl->interfacetable[base] != NULL);
708 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
709 <= (unsigned) classvalues.super_diffval;
715 /* This is an optimized version where a is guaranteed to be a
716 * one-dimensional array of a class type */
717 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
719 vftbl_t *elementvftbl;
722 castinfo classvalues;
726 /* The following is guaranteed (by verifier checks):
728 * *) a->...vftbl->arraydesc != NULL
729 * *) a->...vftbl->arraydesc->elementvftbl != NULL
730 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
731 * *) a->...vftbl->arraydesc->dimension == 1
732 * *) o->vftbl is not an interface vftbl
735 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
736 valuevftbl = o->vftbl;
738 /* {a is a one-dimensional array} */
740 if (valuevftbl == elementvftbl)
743 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
745 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
746 <= (unsigned) classvalues.super_diffval;
752 /* builtin_new *****************************************************************
754 Creates a new instance of class c on the heap.
756 Return value: pointer to the object or NULL if no memory is
759 *******************************************************************************/
761 java_objectheader *builtin_new(classinfo *c)
763 java_objectheader *o;
764 #if defined(ENABLE_RT_TIMING)
765 struct timespec time_start, time_end;
767 #if defined(ENABLE_CYCLES_STATS)
768 u8 cycles_start, cycles_end;
771 RT_TIMING_GET_TIME(time_start);
772 CYCLES_STATS_GET(cycles_start);
774 /* is the class loaded */
776 assert(c->state & CLASS_LOADED);
778 /* check if we can instantiate this class */
780 if (c->flags & ACC_ABSTRACT) {
781 exceptions_throw_instantiationerror(c);
785 /* is the class linked */
787 if (!(c->state & CLASS_LINKED))
791 if (!(c->state & CLASS_INITIALIZED)) {
794 log_message_class("Initialize class (from builtin_new): ", c);
797 if (!initialize_class(c))
801 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
809 #if defined(ENABLE_THREADS)
810 lock_init_object_lock(o);
813 CYCLES_STATS_GET(cycles_end);
814 RT_TIMING_GET_TIME(time_end);
816 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
817 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
823 /* builtin_fast_new ************************************************************
825 Creates a new instance of class c on the heap.
827 Return value: pointer to the object or NULL if no fast return
828 is possible for any reason.
830 *******************************************************************************/
832 java_objectheader *builtin_fast_new(classinfo *c)
834 java_objectheader *o;
835 #if defined(ENABLE_RT_TIMING)
836 struct timespec time_start, time_end;
838 #if defined(ENABLE_CYCLES_STATS)
839 u8 cycles_start, cycles_end;
842 RT_TIMING_GET_TIME(time_start);
843 CYCLES_STATS_GET(cycles_start);
845 /* is the class loaded */
847 assert(c->state & CLASS_LOADED);
849 /* check if we can instantiate this class */
851 if (c->flags & ACC_ABSTRACT)
854 /* is the class linked */
856 if (!(c->state & CLASS_LINKED))
859 if (!(c->state & CLASS_INITIALIZED))
862 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
863 c->finalizer, false);
870 #if defined(ENABLE_THREADS)
871 lock_init_object_lock(o);
874 CYCLES_STATS_GET(cycles_end);
875 RT_TIMING_GET_TIME(time_end);
877 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
878 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
884 /* builtin_newarray ************************************************************
886 Creates an array with the given vftbl on the heap. This function
887 takes as class argument an array class.
889 Return value: pointer to the array or NULL if no memory is available
891 *******************************************************************************/
893 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
895 arraydescriptor *desc;
900 #if defined(ENABLE_RT_TIMING)
901 struct timespec time_start, time_end;
904 RT_TIMING_GET_TIME(time_start);
906 desc = arrayclass->vftbl->arraydesc;
907 dataoffset = desc->dataoffset;
908 componentsize = desc->componentsize;
911 exceptions_throw_negativearraysizeexception();
915 actualsize = dataoffset + size * componentsize;
917 /* check for overflow */
919 if (((u4) actualsize) < ((u4) size)) {
920 exceptions_throw_outofmemoryerror();
924 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
929 a->objheader.vftbl = arrayclass->vftbl;
931 #if defined(ENABLE_THREADS)
932 lock_init_object_lock(&a->objheader);
937 RT_TIMING_GET_TIME(time_end);
938 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
944 /* builtin_anewarray ***********************************************************
946 Creates an array of references to the given class type on the heap.
948 Return value: pointer to the array or NULL if no memory is
951 *******************************************************************************/
953 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
955 classinfo *arrayclass;
957 /* is class loaded */
959 assert(componentclass->state & CLASS_LOADED);
961 /* is class linked */
963 if (!(componentclass->state & CLASS_LINKED))
964 if (!link_class(componentclass))
967 arrayclass = class_array_of(componentclass, true);
972 return (java_objectarray *) builtin_newarray(size, arrayclass);
976 /* builtin_newarray_boolean ****************************************************
978 Creates an array of bytes on the heap. The array is designated as
979 an array of booleans (important for casts)
981 Return value: pointer to the array or NULL if no memory is
984 *******************************************************************************/
986 java_booleanarray *builtin_newarray_boolean(s4 size)
988 return (java_booleanarray *)
989 builtin_newarray(size,
990 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
994 /* builtin_newarray_byte *******************************************************
996 Creates an array of 8 bit Integers on the heap.
998 Return value: pointer to the array or NULL if no memory is
1001 *******************************************************************************/
1003 java_bytearray *builtin_newarray_byte(s4 size)
1005 return (java_bytearray *)
1006 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
1010 /* builtin_newarray_char *******************************************************
1012 Creates an array of characters on the heap.
1014 Return value: pointer to the array or NULL if no memory is
1017 *******************************************************************************/
1019 java_chararray *builtin_newarray_char(s4 size)
1021 return (java_chararray *)
1022 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1026 /* builtin_newarray_short ******************************************************
1028 Creates an array of 16 bit Integers on the heap.
1030 Return value: pointer to the array or NULL if no memory is
1033 *******************************************************************************/
1035 java_shortarray *builtin_newarray_short(s4 size)
1037 return (java_shortarray *)
1038 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1042 /* builtin_newarray_int ********************************************************
1044 Creates an array of 32 bit Integers on the heap.
1046 Return value: pointer to the array or NULL if no memory is
1049 *******************************************************************************/
1051 java_intarray *builtin_newarray_int(s4 size)
1053 return (java_intarray *)
1054 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1058 /* builtin_newarray_long *******************************************************
1060 Creates an array of 64 bit Integers on the heap.
1062 Return value: pointer to the array or NULL if no memory is
1065 *******************************************************************************/
1067 java_longarray *builtin_newarray_long(s4 size)
1069 return (java_longarray *)
1070 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1074 /* builtin_newarray_float ******************************************************
1076 Creates an array of 32 bit IEEE floats on the heap.
1078 Return value: pointer to the array or NULL if no memory is
1081 *******************************************************************************/
1083 java_floatarray *builtin_newarray_float(s4 size)
1085 return (java_floatarray *)
1086 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1090 /* builtin_newarray_double *****************************************************
1092 Creates an array of 64 bit IEEE floats on the heap.
1094 Return value: pointer to the array or NULL if no memory is
1097 *******************************************************************************/
1099 java_doublearray *builtin_newarray_double(s4 size)
1101 return (java_doublearray *)
1102 builtin_newarray(size,
1103 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1107 /* builtin_multianewarray_intern ***********************************************
1109 Creates a multi-dimensional array on the heap. The dimensions are
1110 passed in an array of longs.
1113 n.............number of dimensions to create
1114 arrayclass....the array class
1115 dims..........array containing the size of each dimension to create
1117 Return value: pointer to the array or NULL if no memory is
1120 ******************************************************************************/
1122 static java_arrayheader *builtin_multianewarray_intern(int n,
1123 classinfo *arrayclass,
1127 java_arrayheader *a;
1128 classinfo *componentclass;
1131 /* create this dimension */
1133 size = (s4) dims[0];
1134 a = builtin_newarray(size, arrayclass);
1139 /* if this is the last dimension return */
1144 /* get the class of the components to create */
1146 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1148 /* The verifier guarantees that the dimension count is in the range. */
1150 /* create the component arrays */
1152 for (i = 0; i < size; i++) {
1153 java_arrayheader *ea =
1154 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1155 /* we save an s4 to a s8 slot, 8-byte aligned */
1157 builtin_multianewarray_intern(n, componentclass, dims + 2);
1159 builtin_multianewarray_intern(n, componentclass, dims + 1);
1165 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1172 /* builtin_multianewarray ******************************************************
1174 Wrapper for builtin_multianewarray_intern which checks all
1175 dimensions before we start allocating.
1177 ******************************************************************************/
1179 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1185 /* check all dimensions before doing anything */
1187 for (i = 0; i < n; i++) {
1188 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1189 /* we save an s4 to a s8 slot, 8-byte aligned */
1190 size = (s4) dims[i * 2];
1192 size = (s4) dims[i];
1196 exceptions_throw_negativearraysizeexception();
1201 /* now call the real function */
1203 return builtin_multianewarray_intern(n, arrayclass, dims);
1207 /*****************************************************************************
1210 Various functions for printing a message at method entry or exit (for
1213 *****************************************************************************/
1215 #if !defined(NDEBUG)
1216 static s4 methodindent = 0;
1217 static u4 callcount = 0;
1219 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1229 #if defined(ENABLE_DEBUG_FILTER)
1230 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1233 #if defined(ENABLE_VMLOG)
1237 if (opt_verbosecall && indent)
1240 /* calculate message length */
1244 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1247 logtextlen = strlen("Some Throwable");
1250 logtextlen += strlen(" thrown in ");
1254 utf_bytes(m->class->name) +
1256 utf_bytes(m->name) +
1257 utf_bytes(m->descriptor) +
1258 strlen("(NOSYNC,NATIVE");
1260 #if SIZEOF_VOID_P == 8
1262 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1264 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1267 if (m->class->sourcefile == NULL)
1268 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1270 logtextlen += utf_bytes(m->class->sourcefile);
1272 logtextlen += strlen(":65536)");
1276 logtextlen += strlen("call_java_method");
1279 logtextlen += strlen("0");
1281 /* allocate memory */
1283 dumpsize = dump_size();
1285 logtext = DMNEW(char, logtextlen);
1288 strcpy(logtext, "Exception ");
1289 utf_cat_classname(logtext, xptr->vftbl->class->name);
1292 strcpy(logtext, "Some Throwable");
1295 strcat(logtext, " thrown in ");
1298 utf_cat_classname(logtext, m->class->name);
1299 strcat(logtext, ".");
1300 utf_cat(logtext, m->name);
1301 utf_cat(logtext, m->descriptor);
1303 if (m->flags & ACC_SYNCHRONIZED)
1304 strcat(logtext, "(SYNC");
1306 strcat(logtext, "(NOSYNC");
1308 if (m->flags & ACC_NATIVE) {
1309 strcat(logtext, ",NATIVE");
1313 #if SIZEOF_VOID_P == 8
1314 sprintf(logtext + strlen(logtext),
1315 ")(0x%016lx) at position 0x%016lx",
1316 (ptrint) code->entrypoint, (ptrint) pos);
1318 sprintf(logtext + strlen(logtext),
1319 ")(0x%08x) at position 0x%08x",
1320 (ptrint) code->entrypoint, (ptrint) pos);
1325 /* XXX preliminary: This should get the actual codeinfo */
1326 /* in which the exception happened. */
1329 #if SIZEOF_VOID_P == 8
1330 sprintf(logtext + strlen(logtext),
1331 ")(0x%016lx) at position 0x%016lx (",
1332 (ptrint) code->entrypoint, (ptrint) pos);
1334 sprintf(logtext + strlen(logtext),
1335 ")(0x%08x) at position 0x%08x (",
1336 (ptrint) code->entrypoint, (ptrint) pos);
1339 if (m->class->sourcefile == NULL)
1340 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1342 utf_cat(logtext, m->class->sourcefile);
1344 sprintf(logtext + strlen(logtext), ":%d)", 0);
1348 strcat(logtext, "call_java_method");
1352 /* release memory */
1354 dump_release(dumpsize);
1358 #endif /* !defined(NDEBUG) */
1361 /* builtin_print_argument ******************************************************
1363 Prints arguments and return values for the call trace.
1365 *******************************************************************************/
1367 #if !defined(NDEBUG)
1368 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1369 typedesc *paramtype, s8 value)
1372 java_objectheader *o;
1377 switch (paramtype->type) {
1380 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1385 #if SIZEOF_VOID_P == 4
1386 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1388 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1393 #if defined(__S390__)
1395 /* The below won't work on S390 */
1399 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1404 #if SIZEOF_VOID_P == 4
1405 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1407 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1412 #if SIZEOF_VOID_P == 4
1413 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1415 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1418 /* cast to java.lang.Object */
1420 o = (java_objectheader *) (ptrint) value;
1422 /* check return argument for java.lang.Class or java.lang.String */
1425 if (o->vftbl->class == class_java_lang_String) {
1426 /* get java.lang.String object and the length of the
1429 u = javastring_toutf(o, false);
1431 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1433 /* realloc memory for string length */
1435 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1438 /* convert to utf8 string and strcat it to the logtext */
1440 strcat(logtext, " (String = \"");
1441 utf_cat(logtext, u);
1442 strcat(logtext, "\")");
1445 if (o->vftbl->class == class_java_lang_Class) {
1446 /* if the object returned is a java.lang.Class
1447 cast it to classinfo structure and get the name
1450 c = (classinfo *) o;
1455 /* if the object returned is not a java.lang.String or
1456 a java.lang.Class just print the name of the class */
1458 u = o->vftbl->class->name;
1461 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1463 /* realloc memory for string length */
1465 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1468 /* strcat to the logtext */
1470 strcat(logtext, " (Class = \"");
1471 utf_cat_classname(logtext, u);
1472 strcat(logtext, "\")");
1479 #endif /* !defined(NDEBUG) */
1481 /* builtin_verbosecall_enter ***************************************************
1483 Print method call with arguments for -verbose:call.
1485 *******************************************************************************/
1487 #if !defined(NDEBUG)
1489 #ifdef TRACE_ARGS_NUM
1490 void builtin_verbosecall_enter(s8 a0, s8 a1,
1491 # if TRACE_ARGS_NUM >= 4
1494 # if TRACE_ARGS_NUM >= 6
1497 # if TRACE_ARGS_NUM == 8
1509 #if defined(ENABLE_DEBUG_FILTER)
1510 if (! show_filters_test_verbosecall_enter(m)) return;
1513 #if defined(ENABLE_VMLOG)
1514 vmlog_cacao_enter_method(m);
1520 /* calculate message length */
1523 strlen("4294967295 ") +
1524 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1526 strlen("called: ") +
1527 utf_bytes(m->class->name) +
1529 utf_bytes(m->name) +
1530 utf_bytes(m->descriptor);
1532 /* Actually it's not possible to have all flags printed, but:
1537 strlen(" PRIVATE") +
1538 strlen(" PROTECTED") +
1541 strlen(" SYNCHRONIZED") +
1542 strlen(" VOLATILE") +
1543 strlen(" TRANSIENT") +
1545 strlen(" INTERFACE") +
1546 strlen(" ABSTRACT");
1548 /* add maximal argument length */
1552 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1553 strlen("...(255)") +
1556 /* allocate memory */
1558 dumpsize = dump_size();
1560 logtext = DMNEW(char, logtextlen);
1564 sprintf(logtext, "%10d ", callcount);
1565 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1567 pos = strlen(logtext);
1569 for (i = 0; i < methodindent; i++)
1570 logtext[pos++] = '\t';
1572 strcpy(logtext + pos, "called: ");
1574 utf_cat_classname(logtext, m->class->name);
1575 strcat(logtext, ".");
1576 utf_cat(logtext, m->name);
1577 utf_cat(logtext, m->descriptor);
1579 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1580 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1581 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1582 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1583 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1584 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1585 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1586 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1587 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1588 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1589 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1591 strcat(logtext, "(");
1593 if (md->paramcount >= 1) {
1594 logtext = builtin_print_argument(logtext, &logtextlen,
1595 &md->paramtypes[0], a0);
1598 if (md->paramcount >= 2) {
1599 strcat(logtext, ", ");
1601 logtext = builtin_print_argument(logtext, &logtextlen,
1602 &md->paramtypes[1], a1);
1605 #if TRACE_ARGS_NUM >= 4
1606 if (md->paramcount >= 3) {
1607 strcat(logtext, ", ");
1609 logtext = builtin_print_argument(logtext, &logtextlen,
1610 &md->paramtypes[2], a2);
1613 if (md->paramcount >= 4) {
1614 strcat(logtext, ", ");
1616 logtext = builtin_print_argument(logtext, &logtextlen,
1617 &md->paramtypes[3], a3);
1621 #if TRACE_ARGS_NUM >= 6
1622 if (md->paramcount >= 5) {
1623 strcat(logtext, ", ");
1625 logtext = builtin_print_argument(logtext, &logtextlen,
1626 &md->paramtypes[4], a4);
1629 if (md->paramcount >= 6) {
1630 strcat(logtext, ", ");
1632 logtext = builtin_print_argument(logtext, &logtextlen,
1633 &md->paramtypes[5], a5);
1637 #if TRACE_ARGS_NUM == 8
1638 if (md->paramcount >= 7) {
1639 strcat(logtext, ", ");
1641 logtext = builtin_print_argument(logtext, &logtextlen,
1642 &md->paramtypes[6], a6);
1645 if (md->paramcount >= 8) {
1646 strcat(logtext, ", ");
1648 logtext = builtin_print_argument(logtext, &logtextlen,
1649 &md->paramtypes[7], a7);
1653 if (md->paramcount > 8) {
1654 sprintf(logtext + strlen(logtext), ", ...(%d)",
1655 md->paramcount - TRACE_ARGS_NUM);
1658 strcat(logtext, ")");
1662 /* release memory */
1664 dump_release(dumpsize);
1670 #endif /* !defined(NDEBUG) */
1673 /* builtin_verbosecall_exit ****************************************************
1675 Print method exit for -verbose:call.
1677 *******************************************************************************/
1679 #if !defined(NDEBUG)
1680 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1690 #if defined(ENABLE_DEBUG_FILTER)
1691 if (! show_filters_test_verbosecall_exit(m)) return;
1694 #if defined(ENABLE_VMLOG)
1695 vmlog_cacao_leave_method(m);
1701 /* calculate message length */
1704 strlen("4294967295 ") +
1705 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1707 strlen("finished: ") +
1708 utf_bytes(m->class->name) +
1710 utf_bytes(m->name) +
1711 utf_bytes(m->descriptor) +
1712 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1714 /* add maximal argument length */
1716 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1718 /* allocate memory */
1720 dumpsize = dump_size();
1722 logtext = DMNEW(char, logtextlen);
1724 /* outdent the log message */
1729 log_text("WARNING: unmatched methodindent--");
1731 /* generate the message */
1733 sprintf(logtext, " ");
1734 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1736 pos = strlen(logtext);
1738 for (i = 0; i < methodindent; i++)
1739 logtext[pos++] = '\t';
1741 strcpy(logtext + pos, "finished: ");
1742 utf_cat_classname(logtext, m->class->name);
1743 strcat(logtext, ".");
1744 utf_cat(logtext, m->name);
1745 utf_cat(logtext, m->descriptor);
1747 if (!IS_VOID_TYPE(md->returntype.type)) {
1748 strcat(logtext, "->");
1750 switch (md->returntype.type) {
1767 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1772 /* release memory */
1774 dump_release(dumpsize);
1777 #endif /* !defined(NDEBUG) */
1780 #if defined(ENABLE_CYCLES_STATS)
1781 void builtin_print_cycles_stats(FILE *file)
1783 fprintf(file,"builtin cylce count statistics:\n");
1785 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1786 CYCLES_STATS_PRINT(builtin_new ,file);
1790 #endif /* defined(ENABLE_CYCLES_STATS) */
1793 /*****************************************************************************
1794 MISCELLANEOUS HELPER FUNCTIONS
1795 *****************************************************************************/
1799 /*********** Functions for integer divisions *****************************
1801 On some systems (eg. DEC ALPHA), integer division is not supported by the
1802 CPU. These helper functions implement the missing functionality.
1804 ******************************************************************************/
1806 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1807 s4 builtin_idiv(s4 a, s4 b)
1816 s4 builtin_irem(s4 a, s4 b)
1824 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1827 /* functions for long arithmetics **********************************************
1829 On systems where 64 bit Integers are not supported by the CPU,
1830 these functions are needed.
1832 ******************************************************************************/
1834 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1835 s8 builtin_ladd(s8 a, s8 b)
1848 s8 builtin_lsub(s8 a, s8 b)
1861 s8 builtin_lneg(s8 a)
1873 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1876 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1877 s8 builtin_lmul(s8 a, s8 b)
1889 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1892 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1893 s8 builtin_ldiv(s8 a, s8 b)
1906 s8 builtin_lrem(s8 a, s8 b)
1918 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1921 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1922 s8 builtin_lshl(s8 a, s4 b)
1935 s8 builtin_lshr(s8 a, s4 b)
1948 s8 builtin_lushr(s8 a, s4 b)
1953 c = ((u8) a) >> (b & 63);
1960 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1963 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1964 s8 builtin_land(s8 a, s8 b)
1977 s8 builtin_lor(s8 a, s8 b)
1990 s8 builtin_lxor(s8 a, s8 b)
2002 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2005 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2006 s4 builtin_lcmp(s8 a, s8 b)
2020 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2023 /* functions for unsupported floating instructions ****************************/
2025 /* used to convert FLT_xxx defines into float values */
2027 static inline float intBitsToFloat(s4 i)
2036 /* used to convert DBL_xxx defines into double values */
2038 static inline float longBitsToDouble(s8 l)
2048 float builtin_fadd(float a, float b)
2050 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2051 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2062 if (copysignf(1.0, a) == copysignf(1.0, b))
2065 return intBitsToFloat(FLT_NAN);
2071 float builtin_fsub(float a, float b)
2073 return builtin_fadd(a, builtin_fneg(b));
2077 float builtin_fmul(float a, float b)
2079 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2080 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2082 if (finitef(b)) return a * b;
2084 if (a == 0) return intBitsToFloat(FLT_NAN);
2085 else return copysignf(b, copysignf(1.0, b)*a);
2090 if (b == 0) return intBitsToFloat(FLT_NAN);
2091 else return copysignf(a, copysignf(1.0, a)*b);
2094 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2100 /* builtin_ddiv ****************************************************************
2102 Implementation as described in VM Spec.
2104 *******************************************************************************/
2106 float builtin_fdiv(float a, float b)
2110 /* If neither value1' nor value2' is NaN, the sign of the result */
2111 /* is positive if both values have the same sign, negative if the */
2112 /* values have different signs. */
2118 /* If either value1' or value2' is NaN, the result is NaN. */
2120 return intBitsToFloat(FLT_NAN);
2123 /* Division of a finite value by an infinity results in a */
2124 /* signed zero, with the sign-producing rule just given. */
2126 /* is sign equal? */
2128 if (copysignf(1.0, a) == copysignf(1.0, b))
2137 /* If either value1' or value2' is NaN, the result is NaN. */
2139 return intBitsToFloat(FLT_NAN);
2141 } else if (finitef(b)) {
2142 /* Division of an infinity by a finite value results in a signed */
2143 /* infinity, with the sign-producing rule just given. */
2145 /* is sign equal? */
2147 if (copysignf(1.0, a) == copysignf(1.0, b))
2148 return intBitsToFloat(FLT_POSINF);
2150 return intBitsToFloat(FLT_NEGINF);
2153 /* Division of an infinity by an infinity results in NaN. */
2155 return intBitsToFloat(FLT_NAN);
2161 float builtin_fneg(float a)
2163 if (isnanf(a)) return a;
2165 if (finitef(a)) return -a;
2166 else return copysignf(a, -copysignf(1.0, a));
2169 #endif /* !SUPPORT_FLOAT */
2172 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2173 s4 builtin_fcmpl(float a, float b)
2181 if (!finitef(a) || !finitef(b)) {
2182 a = finitef(a) ? 0 : copysignf(1.0, a);
2183 b = finitef(b) ? 0 : copysignf(1.0, b);
2196 s4 builtin_fcmpg(float a, float b)
2198 if (isnanf(a)) return 1;
2199 if (isnanf(b)) return 1;
2200 if (!finitef(a) || !finitef(b)) {
2201 a = finitef(a) ? 0 : copysignf(1.0, a);
2202 b = finitef(b) ? 0 : copysignf(1.0, b);
2204 if (a > b) return 1;
2205 if (a == b) return 0;
2208 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2211 float builtin_frem(float a, float b)
2217 /* functions for unsupported double instructions ******************************/
2220 double builtin_dadd(double a, double b)
2222 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2223 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2225 if (finite(b)) return a + b;
2229 if (finite(b)) return a;
2231 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2232 else return longBitsToDouble(DBL_NAN);
2238 double builtin_dsub(double a, double b)
2240 return builtin_dadd(a, builtin_dneg(b));
2244 double builtin_dmul(double a, double b)
2246 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2247 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2249 if (finite(b)) return a * b;
2251 if (a == 0) return longBitsToDouble(DBL_NAN);
2252 else return copysign(b, copysign(1.0, b) * a);
2257 if (b == 0) return longBitsToDouble(DBL_NAN);
2258 else return copysign(a, copysign(1.0, a) * b);
2261 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2267 /* builtin_ddiv ****************************************************************
2269 Implementation as described in VM Spec.
2271 *******************************************************************************/
2273 double builtin_ddiv(double a, double b)
2277 /* If neither value1' nor value2' is NaN, the sign of the result */
2278 /* is positive if both values have the same sign, negative if the */
2279 /* values have different signs. */
2285 /* If either value1' or value2' is NaN, the result is NaN. */
2287 return longBitsToDouble(DBL_NAN);
2290 /* Division of a finite value by an infinity results in a */
2291 /* signed zero, with the sign-producing rule just given. */
2293 /* is sign equal? */
2295 if (copysign(1.0, a) == copysign(1.0, b))
2304 /* If either value1' or value2' is NaN, the result is NaN. */
2306 return longBitsToDouble(DBL_NAN);
2308 } else if (finite(b)) {
2309 /* Division of an infinity by a finite value results in a signed */
2310 /* infinity, with the sign-producing rule just given. */
2312 /* is sign equal? */
2314 if (copysign(1.0, a) == copysign(1.0, b))
2315 return longBitsToDouble(DBL_POSINF);
2317 return longBitsToDouble(DBL_NEGINF);
2320 /* Division of an infinity by an infinity results in NaN. */
2322 return longBitsToDouble(DBL_NAN);
2328 /* builtin_dneg ****************************************************************
2330 Implemented as described in VM Spec.
2332 *******************************************************************************/
2334 double builtin_dneg(double a)
2337 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2344 /* If the operand is a zero, the result is the zero of opposite */
2350 /* If the operand is an infinity, the result is the infinity of */
2351 /* opposite sign. */
2353 return copysign(a, -copysign(1.0, a));
2357 #endif /* !SUPPORT_DOUBLE */
2360 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2361 s4 builtin_dcmpl(double a, double b)
2369 if (!finite(a) || !finite(b)) {
2370 a = finite(a) ? 0 : copysign(1.0, a);
2371 b = finite(b) ? 0 : copysign(1.0, b);
2384 s4 builtin_dcmpg(double a, double b)
2392 if (!finite(a) || !finite(b)) {
2393 a = finite(a) ? 0 : copysign(1.0, a);
2394 b = finite(b) ? 0 : copysign(1.0, b);
2405 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2408 double builtin_drem(double a, double b)
2414 /* conversion operations ******************************************************/
2417 s8 builtin_i2l(s4 i)
2429 s4 builtin_l2i(s8 l)
2440 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2441 float builtin_i2f(s4 a)
2443 float f = (float) a;
2446 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2449 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2450 double builtin_i2d(s4 a)
2452 double d = (double) a;
2455 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2458 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2459 float builtin_l2f(s8 a)
2462 float f = (float) a;
2468 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2471 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2472 double builtin_l2d(s8 a)
2475 double d = (double) a;
2481 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2484 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2485 s4 builtin_f2i(float a)
2489 i = builtin_d2i((double) a);
2500 if (a < (-2147483648))
2501 return (-2147483648);
2504 f = copysignf((float) 1.0, a);
2507 return (-2147483648); */
2509 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2512 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2513 s8 builtin_f2l(float a)
2517 l = builtin_d2l((double) a);
2524 if (a > 9223372036854775807L)
2525 return 9223372036854775807L;
2526 if (a < (-9223372036854775808L))
2527 return (-9223372036854775808L);
2532 f = copysignf((float) 1.0, a);
2534 return 9223372036854775807L;
2535 return (-9223372036854775808L); */
2537 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2540 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2541 s4 builtin_d2i(double a)
2546 if (a >= 2147483647)
2548 if (a <= (-2147483647-1))
2549 return (-2147483647-1);
2554 d = copysign(1.0, a);
2557 return (-2147483647-1);
2559 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2562 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2563 s8 builtin_d2l(double a)
2568 if (a >= 9223372036854775807LL)
2569 return 9223372036854775807LL;
2570 if (a <= (-9223372036854775807LL-1))
2571 return (-9223372036854775807LL-1);
2576 d = copysign(1.0, a);
2578 return 9223372036854775807LL;
2579 return (-9223372036854775807LL-1);
2581 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2584 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2585 double builtin_f2d(float a)
2587 if (finitef(a)) return (double) a;
2590 return longBitsToDouble(DBL_NAN);
2592 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2596 float builtin_d2f(double a)
2602 return intBitsToFloat(FLT_NAN);
2604 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2607 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2610 /* builtin_arraycopy ***********************************************************
2612 Builtin for java.lang.System.arraycopy.
2614 ATTENTION: This builtin function returns a boolean value to signal
2615 the ICMD_BUILTIN if there was an exception.
2617 *******************************************************************************/
2619 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2620 java_arrayheader *dest, s4 destStart, s4 len)
2622 arraydescriptor *sdesc;
2623 arraydescriptor *ddesc;
2626 if ((src == NULL) || (dest == NULL)) {
2627 exceptions_throw_nullpointerexception();
2631 sdesc = src->objheader.vftbl->arraydesc;
2632 ddesc = dest->objheader.vftbl->arraydesc;
2634 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2635 exceptions_throw_arraystoreexception();
2639 /* we try to throw exception with the same message as SUN does */
2641 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2642 (srcStart + len < 0) || (srcStart + len > src->size) ||
2643 (destStart + len < 0) || (destStart + len > dest->size)) {
2644 exceptions_throw_arrayindexoutofboundsexception();
2648 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2649 /* We copy primitive values or references of exactly the same type */
2651 s4 dataoffset = sdesc->dataoffset;
2652 s4 componentsize = sdesc->componentsize;
2654 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2655 ((u1 *) src) + dataoffset + componentsize * srcStart,
2656 (size_t) len * componentsize);
2659 /* We copy references of different type */
2661 java_objectarray *oas = (java_objectarray *) src;
2662 java_objectarray *oad = (java_objectarray *) dest;
2664 if (destStart <= srcStart) {
2665 for (i = 0; i < len; i++) {
2666 java_objectheader *o = oas->data[srcStart + i];
2668 if (!builtin_canstore(oad, o))
2671 oad->data[destStart + i] = o;
2675 /* XXX this does not completely obey the specification!
2676 If an exception is thrown only the elements above the
2677 current index have been copied. The specification
2678 requires that only the elements *below* the current
2679 index have been copied before the throw. */
2681 for (i = len - 1; i >= 0; i--) {
2682 java_objectheader *o = oas->data[srcStart + i];
2684 if (!builtin_canstore(oad, o))
2687 oad->data[destStart + i] = o;
2696 /* builtin_nanotime ************************************************************
2698 Return the current time in nanoseconds.
2700 *******************************************************************************/
2702 s8 builtin_nanotime(void)
2707 if (gettimeofday(&tv, NULL) == -1)
2708 vm_abort("gettimeofday failed: %s", strerror(errno));
2710 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2712 return usecs * 1000;
2716 /* builtin_currenttimemillis ***************************************************
2718 Return the current time in milliseconds.
2720 *******************************************************************************/
2722 s8 builtin_currenttimemillis(void)
2726 msecs = builtin_nanotime() / 1000 / 1000;
2732 /* builtin_clone ***************************************************************
2734 Function for cloning objects or arrays.
2736 *******************************************************************************/
2738 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2740 arraydescriptor *ad;
2741 java_arrayheader *ah;
2744 java_objectheader *co; /* cloned object header */
2746 /* get the array descriptor */
2748 ad = o->vftbl->arraydesc;
2750 /* we are cloning an array */
2753 ah = (java_arrayheader *) o;
2755 size = ad->dataoffset + ad->componentsize * ah->size;
2757 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2762 MCOPY(co, o, u1, size);
2764 #if defined(ENABLE_GC_CACAO)
2765 heap_init_objectheader(co, size);
2768 #if defined(ENABLE_THREADS)
2769 lock_init_object_lock(co);
2775 /* we are cloning a non-array */
2777 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2778 exceptions_throw_clonenotsupportedexception();
2782 /* get the class of the object */
2784 c = o->vftbl->class;
2786 /* create new object */
2788 co = builtin_new(c);
2793 MCOPY(co, o, u1, c->instancesize);
2795 #if defined(ENABLE_GC_CACAO)
2796 heap_init_objectheader(co, c->instancesize);
2799 #if defined(ENABLE_THREADS)
2800 lock_init_object_lock(co);
2806 #if defined(ENABLE_VMLOG)
2808 #include <vmlog_cacao.c>
2813 * These are local overrides for various environment variables in Emacs.
2814 * Please do not remove this and leave it at the end of the file, where
2815 * Emacs will automagically detect them.
2816 * ---------------------------------------------------------------------
2819 * indent-tabs-mode: t
2823 * vim:noexpandtab:sw=4:ts=4: