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 8123 2007-06-20 23:50:55Z 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"
74 #include "vm/jit/patcher.h"
76 #include "vmcore/class.h"
77 #include "vmcore/loader.h"
78 #include "vmcore/options.h"
79 #include "vmcore/primitive.h"
80 #include "vmcore/rt-timing.h"
82 #if defined(ENABLE_VMLOG)
83 #include <vmlog_cacao.h>
86 #if defined(ENABLE_DEBUG_FILTER)
87 # include "vm/jit/show.h"
90 /* include builtin tables *****************************************************/
92 #include "vm/builtintable.inc"
95 CYCLES_STATS_DECLARE(builtin_new ,100,5)
96 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
98 /* builtintable_init ***********************************************************
100 Parse the descriptors of builtin functions and create the parsed
103 *******************************************************************************/
105 static bool builtintable_init(void)
107 descriptor_pool *descpool;
109 builtintable_entry *bte;
111 /* mark start of dump memory area */
113 dumpsize = dump_size();
115 /* create a new descriptor pool */
117 descpool = descriptor_pool_new(class_java_lang_Object);
119 /* add some entries we need */
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
124 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
127 /* first add all descriptors to the pool */
129 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
130 /* create a utf8 string from descriptor */
132 bte->descriptor = utf_new_char(bte->cdescriptor);
134 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
135 /* release dump area */
137 dump_release(dumpsize);
143 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
144 bte->descriptor = utf_new_char(bte->cdescriptor);
146 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
147 dump_release(dumpsize);
152 for (bte = builtintable_function; bte->fp != NULL; bte++) {
153 bte->classname = utf_new_char(bte->cclassname);
154 bte->name = utf_new_char(bte->cname);
155 bte->descriptor = utf_new_char(bte->cdescriptor);
157 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
158 dump_release(dumpsize);
163 /* create the class reference table */
165 (void) descriptor_pool_create_classrefs(descpool, NULL);
167 /* allocate space for the parsed descriptors */
169 descriptor_pool_alloc_parsed_descriptors(descpool);
171 /* now parse all descriptors */
173 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
174 /* parse the descriptor, builtin is always static (no `this' pointer) */
176 bte->md = descriptor_pool_parse_method_descriptor(descpool,
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++) {
187 bte->md = descriptor_pool_parse_method_descriptor(descpool,
192 for (bte = builtintable_function; bte->fp != NULL; bte++) {
193 bte->md = descriptor_pool_parse_method_descriptor(descpool,
198 /* release dump area */
200 dump_release(dumpsize);
206 /* builtintable_comparator *****************************************************
208 qsort comparator for the automatic builtin table.
210 *******************************************************************************/
212 static int builtintable_comparator(const void *a, const void *b)
214 builtintable_entry *bte1;
215 builtintable_entry *bte2;
217 bte1 = (builtintable_entry *) a;
218 bte2 = (builtintable_entry *) b;
220 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
224 /* builtintable_sort_automatic *************************************************
226 Sorts the automatic builtin table.
228 *******************************************************************************/
230 static void builtintable_sort_automatic(void)
234 /* calculate table size statically (`- 1' comment see builtintable.inc) */
236 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
238 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
239 builtintable_comparator);
243 /* builtin_init ****************************************************************
245 Initialize the global table of builtin functions.
247 *******************************************************************************/
249 bool builtin_init(void)
251 /* initialize the builtin tables */
253 if (!builtintable_init())
256 /* sort builtin tables */
258 builtintable_sort_automatic();
264 /* builtintable_get_internal ***************************************************
266 Finds an entry in the builtintable for internal functions and
267 returns the a pointer to the structure.
269 *******************************************************************************/
271 builtintable_entry *builtintable_get_internal(functionptr fp)
273 builtintable_entry *bte;
275 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
284 /* builtintable_get_automatic **************************************************
286 Finds an entry in the builtintable for functions which are replaced
287 automatically and returns the a pointer to the structure.
289 *******************************************************************************/
291 builtintable_entry *builtintable_get_automatic(s4 opcode)
293 builtintable_entry *first;
294 builtintable_entry *last;
295 builtintable_entry *middle;
299 /* calculate table size statically (`- 1' comment see builtintable.inc) */
301 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
303 first = builtintable_automatic;
304 last = builtintable_automatic + entries;
306 while (entries > 0) {
308 middle = first + half;
310 if (middle->opcode < opcode) {
318 return (first != last ? first : NULL);
322 /* builtintable_replace_function ***********************************************
326 *******************************************************************************/
328 #if defined(ENABLE_JIT)
329 bool builtintable_replace_function(void *iptr_)
332 builtintable_entry *bte;
335 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
337 /* get name and descriptor of the function */
340 case ICMD_INVOKESTATIC:
341 /* The instruction MUST be resolved, otherwise we run into
342 lazy loading troubles. Anyway, we should/can only replace
343 very VM-close functions. */
345 if (INSTRUCTION_IS_UNRESOLVED(iptr))
348 mr = iptr->sx.s23.s3.fmiref;
355 /* search the function table */
357 for (bte = builtintable_function; bte->fp != NULL; bte++) {
358 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
359 (mr->name == bte->name) &&
360 (mr->descriptor == bte->descriptor)) {
362 /* set the values in the instruction */
364 iptr->opc = bte->opcode;
365 iptr->sx.s23.s3.bte = bte;
367 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
368 iptr->flags.bits |= INS_FLAG_CHECK;
370 iptr->flags.bits &= ~INS_FLAG_CHECK;
378 #endif /* defined(ENABLE_JIT) */
381 /*****************************************************************************
383 *****************************************************************************/
385 /* builtin_instanceof **********************************************************
387 Checks if an object is an instance of some given class (or subclass
388 of that class). If class is an interface, checks if the interface
391 Return value: 1 ... o is an instance of class or implements the interface
392 0 ... otherwise or if o == NULL
394 *******************************************************************************/
396 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
401 return class_isanysubclass(o->vftbl->class, class);
406 /* builtin_checkcast ***********************************************************
408 The same as builtin_instanceof except that 1 is returned when o ==
411 *******************************************************************************/
413 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
418 if (class_isanysubclass(o->vftbl->class, class))
425 /* builtin_descriptorscompatible ***********************************************
427 Checks if two array type descriptors are assignment compatible
429 Return value: 1 ... target = desc is possible
432 *******************************************************************************/
434 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
435 arraydescriptor *target)
440 if (desc->arraytype != target->arraytype)
443 if (desc->arraytype != ARRAYTYPE_OBJECT)
446 /* {both arrays are arrays of references} */
448 if (desc->dimension == target->dimension) {
449 /* an array which contains elements of interface types is
450 allowed to be casted to Object (JOWENN)*/
452 if ((desc->elementvftbl->baseval < 0) &&
453 (target->elementvftbl->baseval == 1))
456 return class_isanysubclass(desc->elementvftbl->class,
457 target->elementvftbl->class);
460 if (desc->dimension < target->dimension)
463 /* {desc has higher dimension than target} */
465 return class_isanysubclass(pseudo_class_Arraystub,
466 target->elementvftbl->class);
470 /* builtin_arraycheckcast ******************************************************
472 Checks if an object is really a subtype of the requested array
473 type. The object has to be an array to begin with. For simple
474 arrays (int, short, double, etc.) the types have to match exactly.
475 For arrays of objects, the type of elements in the array has to be
476 a subtype (or the same type) of the requested element type. For
477 arrays of arrays (which in turn can again be arrays of arrays), the
478 types at the lowest level have to satisfy the corresponding sub
481 *******************************************************************************/
483 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
485 arraydescriptor *desc;
490 desc = o->vftbl->arraydesc;
495 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
499 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
504 return builtin_arraycheckcast(o, targetclass);
508 /* builtin_throw_exception *****************************************************
510 Sets the exceptionptr with the thrown exception and prints some
511 debugging information. Called from asm_vm_call_method.
513 *******************************************************************************/
515 void *builtin_throw_exception(java_objectheader *xptr)
518 java_lang_Throwable *t;
524 t = (java_lang_Throwable *) xptr;
526 /* calculate message length */
528 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
532 utf_bytes(xptr->vftbl->class->name);
533 if (t->detailMessage) {
534 logtextlen += strlen(": ") +
535 u2_utflength(t->detailMessage->value->data
536 + t->detailMessage->offset,
537 t->detailMessage->count);
541 logtextlen += strlen("(nil)");
544 /* allocate memory */
546 dumpsize = dump_size();
548 logtext = DMNEW(char, logtextlen);
550 strcpy(logtext, "Builtin exception thrown: ");
553 utf_cat_classname(logtext, xptr->vftbl->class->name);
555 if (t->detailMessage) {
558 buf = javastring_tochar((java_objectheader *) t->detailMessage);
559 strcat(logtext, ": ");
560 strcat(logtext, buf);
561 MFREE(buf, char, strlen(buf) + 1);
565 strcat(logtext, "(nil)");
572 dump_release(dumpsize);
574 #endif /* !defined(NDEBUG) */
576 /* actually set the exception */
578 exceptions_set_exception(xptr);
580 /* Return a NULL pointer. This is required for vm_call_method to
581 check for an exception. This is for convenience. */
587 /* builtin_canstore ************************************************************
589 Checks, if an object can be stored in an array.
591 Return value: 1 ... possible
592 0 ... otherwise (throws an ArrayStoreException)
594 *******************************************************************************/
596 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
598 arraydescriptor *desc;
599 arraydescriptor *valuedesc;
600 vftbl_t *componentvftbl;
603 castinfo classvalues;
609 /* The following is guaranteed (by verifier checks):
611 * *) oa->...vftbl->arraydesc != NULL
612 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
613 * *) o->vftbl is not an interface vftbl
616 desc = oa->header.objheader.vftbl->arraydesc;
617 componentvftbl = desc->componentvftbl;
618 valuevftbl = o->vftbl;
619 valuedesc = valuevftbl->arraydesc;
621 if ((desc->dimension - 1) == 0) {
622 /* {oa is a one-dimensional array} */
623 /* {oa is an array of references} */
625 if (valuevftbl == componentvftbl)
628 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
630 base = classvalues.super_baseval;
633 /* an array of interface references */
635 result = ((valuevftbl->interfacetablelength > -base) &&
636 (valuevftbl->interfacetable[base] != NULL));
639 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
640 <= (unsigned) classvalues.super_diffval);
643 else if (valuedesc == NULL) {
644 /* {oa has dimension > 1} */
645 /* {componentvftbl->arraydesc != NULL} */
647 /* check if o is an array */
652 /* {o is an array} */
654 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
657 /* if not possible, throw an exception */
660 exceptions_throw_arraystoreexception();
668 /* This is an optimized version where a is guaranteed to be one-dimensional */
669 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
671 arraydescriptor *desc;
672 vftbl_t *elementvftbl;
676 castinfo classvalues;
680 /* The following is guaranteed (by verifier checks):
682 * *) a->...vftbl->arraydesc != NULL
683 * *) a->...vftbl->arraydesc->elementvftbl != NULL
684 * *) a->...vftbl->arraydesc->dimension == 1
685 * *) o->vftbl is not an interface vftbl
688 desc = a->header.objheader.vftbl->arraydesc;
689 elementvftbl = desc->elementvftbl;
690 valuevftbl = o->vftbl;
692 /* {a is a one-dimensional array} */
694 if (valuevftbl == elementvftbl)
697 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
699 if ((base = classvalues.super_baseval) <= 0)
700 /* an array of interface references */
701 return (valuevftbl->interfacetablelength > -base &&
702 valuevftbl->interfacetable[base] != NULL);
704 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
705 <= (unsigned) classvalues.super_diffval;
711 /* This is an optimized version where a is guaranteed to be a
712 * one-dimensional array of a class type */
713 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
715 vftbl_t *elementvftbl;
718 castinfo classvalues;
722 /* The following is guaranteed (by verifier checks):
724 * *) a->...vftbl->arraydesc != NULL
725 * *) a->...vftbl->arraydesc->elementvftbl != NULL
726 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
727 * *) a->...vftbl->arraydesc->dimension == 1
728 * *) o->vftbl is not an interface vftbl
731 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
732 valuevftbl = o->vftbl;
734 /* {a is a one-dimensional array} */
736 if (valuevftbl == elementvftbl)
739 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
741 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
742 <= (unsigned) classvalues.super_diffval;
748 /* builtin_new *****************************************************************
750 Creates a new instance of class c on the heap.
752 Return value: pointer to the object or NULL if no memory is
755 *******************************************************************************/
757 java_objectheader *builtin_new(classinfo *c)
759 java_objectheader *o;
760 #if defined(ENABLE_RT_TIMING)
761 struct timespec time_start, time_end;
763 #if defined(ENABLE_CYCLES_STATS)
764 u8 cycles_start, cycles_end;
767 RT_TIMING_GET_TIME(time_start);
768 CYCLES_STATS_GET(cycles_start);
770 /* is the class loaded */
772 assert(c->state & CLASS_LOADED);
774 /* check if we can instantiate this class */
776 if (c->flags & ACC_ABSTRACT) {
777 exceptions_throw_instantiationerror(c);
781 /* is the class linked */
783 if (!(c->state & CLASS_LINKED))
787 if (!(c->state & CLASS_INITIALIZED)) {
790 log_message_class("Initialize class (from builtin_new): ", c);
793 if (!initialize_class(c))
797 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
805 #if defined(ENABLE_THREADS)
806 lock_init_object_lock(o);
809 CYCLES_STATS_GET(cycles_end);
810 RT_TIMING_GET_TIME(time_end);
812 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
813 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
819 /* builtin_fast_new ************************************************************
821 Creates a new instance of class c on the heap.
823 Return value: pointer to the object or NULL if no fast return
824 is possible for any reason.
826 *******************************************************************************/
828 java_objectheader *builtin_fast_new(classinfo *c)
830 java_objectheader *o;
831 #if defined(ENABLE_RT_TIMING)
832 struct timespec time_start, time_end;
834 #if defined(ENABLE_CYCLES_STATS)
835 u8 cycles_start, cycles_end;
838 RT_TIMING_GET_TIME(time_start);
839 CYCLES_STATS_GET(cycles_start);
841 /* is the class loaded */
843 assert(c->state & CLASS_LOADED);
845 /* check if we can instantiate this class */
847 if (c->flags & ACC_ABSTRACT)
850 /* is the class linked */
852 if (!(c->state & CLASS_LINKED))
855 if (!(c->state & CLASS_INITIALIZED))
858 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
859 c->finalizer, false);
866 #if defined(ENABLE_THREADS)
867 lock_init_object_lock(o);
870 CYCLES_STATS_GET(cycles_end);
871 RT_TIMING_GET_TIME(time_end);
873 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
874 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
880 /* builtin_newarray ************************************************************
882 Creates an array with the given vftbl on the heap. This function
883 takes as class argument an array class.
885 Return value: pointer to the array or NULL if no memory is available
887 *******************************************************************************/
889 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
891 arraydescriptor *desc;
896 #if defined(ENABLE_RT_TIMING)
897 struct timespec time_start, time_end;
900 RT_TIMING_GET_TIME(time_start);
902 desc = arrayclass->vftbl->arraydesc;
903 dataoffset = desc->dataoffset;
904 componentsize = desc->componentsize;
907 exceptions_throw_negativearraysizeexception();
911 actualsize = dataoffset + size * componentsize;
913 /* check for overflow */
915 if (((u4) actualsize) < ((u4) size)) {
916 exceptions_throw_outofmemoryerror();
920 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
925 a->objheader.vftbl = arrayclass->vftbl;
927 #if defined(ENABLE_THREADS)
928 lock_init_object_lock(&a->objheader);
933 RT_TIMING_GET_TIME(time_end);
934 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
940 /* builtin_anewarray ***********************************************************
942 Creates an array of references to the given class type on the heap.
944 Return value: pointer to the array or NULL if no memory is
947 *******************************************************************************/
949 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
951 classinfo *arrayclass;
953 /* is class loaded */
955 assert(componentclass->state & CLASS_LOADED);
957 /* is class linked */
959 if (!(componentclass->state & CLASS_LINKED))
960 if (!link_class(componentclass))
963 arrayclass = class_array_of(componentclass, true);
968 return (java_objectarray *) builtin_newarray(size, arrayclass);
972 /* builtin_newarray_boolean ****************************************************
974 Creates an array of bytes on the heap. The array is designated as
975 an array of booleans (important for casts)
977 Return value: pointer to the array or NULL if no memory is
980 *******************************************************************************/
982 java_booleanarray *builtin_newarray_boolean(s4 size)
984 return (java_booleanarray *)
985 builtin_newarray(size,
986 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
990 /* builtin_newarray_byte *******************************************************
992 Creates an array of 8 bit Integers on the heap.
994 Return value: pointer to the array or NULL if no memory is
997 *******************************************************************************/
999 java_bytearray *builtin_newarray_byte(s4 size)
1001 return (java_bytearray *)
1002 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
1006 /* builtin_newarray_char *******************************************************
1008 Creates an array of characters on the heap.
1010 Return value: pointer to the array or NULL if no memory is
1013 *******************************************************************************/
1015 java_chararray *builtin_newarray_char(s4 size)
1017 return (java_chararray *)
1018 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1022 /* builtin_newarray_short ******************************************************
1024 Creates an array of 16 bit Integers on the heap.
1026 Return value: pointer to the array or NULL if no memory is
1029 *******************************************************************************/
1031 java_shortarray *builtin_newarray_short(s4 size)
1033 return (java_shortarray *)
1034 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1038 /* builtin_newarray_int ********************************************************
1040 Creates an array of 32 bit Integers on the heap.
1042 Return value: pointer to the array or NULL if no memory is
1045 *******************************************************************************/
1047 java_intarray *builtin_newarray_int(s4 size)
1049 return (java_intarray *)
1050 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1054 /* builtin_newarray_long *******************************************************
1056 Creates an array of 64 bit Integers on the heap.
1058 Return value: pointer to the array or NULL if no memory is
1061 *******************************************************************************/
1063 java_longarray *builtin_newarray_long(s4 size)
1065 return (java_longarray *)
1066 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1070 /* builtin_newarray_float ******************************************************
1072 Creates an array of 32 bit IEEE floats on the heap.
1074 Return value: pointer to the array or NULL if no memory is
1077 *******************************************************************************/
1079 java_floatarray *builtin_newarray_float(s4 size)
1081 return (java_floatarray *)
1082 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1086 /* builtin_newarray_double *****************************************************
1088 Creates an array of 64 bit IEEE floats on the heap.
1090 Return value: pointer to the array or NULL if no memory is
1093 *******************************************************************************/
1095 java_doublearray *builtin_newarray_double(s4 size)
1097 return (java_doublearray *)
1098 builtin_newarray(size,
1099 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1103 /* builtin_multianewarray_intern ***********************************************
1105 Creates a multi-dimensional array on the heap. The dimensions are
1106 passed in an array of longs.
1109 n.............number of dimensions to create
1110 arrayclass....the array class
1111 dims..........array containing the size of each dimension to create
1113 Return value: pointer to the array or NULL if no memory is
1116 ******************************************************************************/
1118 static java_arrayheader *builtin_multianewarray_intern(int n,
1119 classinfo *arrayclass,
1123 java_arrayheader *a;
1124 classinfo *componentclass;
1127 /* create this dimension */
1129 size = (s4) dims[0];
1130 a = builtin_newarray(size, arrayclass);
1135 /* if this is the last dimension return */
1140 /* get the class of the components to create */
1142 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1144 /* The verifier guarantees that the dimension count is in the range. */
1146 /* create the component arrays */
1148 for (i = 0; i < size; i++) {
1149 java_arrayheader *ea =
1150 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1151 /* we save an s4 to a s8 slot, 8-byte aligned */
1153 builtin_multianewarray_intern(n, componentclass, dims + 2);
1155 builtin_multianewarray_intern(n, componentclass, dims + 1);
1161 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1168 /* builtin_multianewarray ******************************************************
1170 Wrapper for builtin_multianewarray_intern which checks all
1171 dimensions before we start allocating.
1173 ******************************************************************************/
1175 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1181 /* check all dimensions before doing anything */
1183 for (i = 0; i < n; i++) {
1184 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1185 /* we save an s4 to a s8 slot, 8-byte aligned */
1186 size = (s4) dims[i * 2];
1188 size = (s4) dims[i];
1192 exceptions_throw_negativearraysizeexception();
1197 /* now call the real function */
1199 return builtin_multianewarray_intern(n, arrayclass, dims);
1203 /*****************************************************************************
1206 Various functions for printing a message at method entry or exit (for
1209 *****************************************************************************/
1211 #if !defined(NDEBUG)
1212 static s4 methodindent = 0;
1213 static u4 callcount = 0;
1215 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1225 #if defined(ENABLE_DEBUG_FILTER)
1226 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1229 #if defined(ENABLE_VMLOG)
1233 if (opt_verbosecall && indent)
1236 /* calculate message length */
1240 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1243 logtextlen = strlen("Some Throwable");
1246 logtextlen += strlen(" thrown in ");
1250 utf_bytes(m->class->name) +
1252 utf_bytes(m->name) +
1253 utf_bytes(m->descriptor) +
1254 strlen("(NOSYNC,NATIVE");
1256 #if SIZEOF_VOID_P == 8
1258 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1260 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1263 if (m->class->sourcefile == NULL)
1264 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1266 logtextlen += utf_bytes(m->class->sourcefile);
1268 logtextlen += strlen(":65536)");
1272 logtextlen += strlen("call_java_method");
1275 logtextlen += strlen("0");
1277 /* allocate memory */
1279 dumpsize = dump_size();
1281 logtext = DMNEW(char, logtextlen);
1284 strcpy(logtext, "Exception ");
1285 utf_cat_classname(logtext, xptr->vftbl->class->name);
1288 strcpy(logtext, "Some Throwable");
1291 strcat(logtext, " thrown in ");
1294 utf_cat_classname(logtext, m->class->name);
1295 strcat(logtext, ".");
1296 utf_cat(logtext, m->name);
1297 utf_cat(logtext, m->descriptor);
1299 if (m->flags & ACC_SYNCHRONIZED)
1300 strcat(logtext, "(SYNC");
1302 strcat(logtext, "(NOSYNC");
1304 if (m->flags & ACC_NATIVE) {
1305 strcat(logtext, ",NATIVE");
1309 #if SIZEOF_VOID_P == 8
1310 sprintf(logtext + strlen(logtext),
1311 ")(0x%016lx) at position 0x%016lx",
1312 (ptrint) code->entrypoint, (ptrint) pos);
1314 sprintf(logtext + strlen(logtext),
1315 ")(0x%08x) at position 0x%08x",
1316 (ptrint) code->entrypoint, (ptrint) pos);
1321 /* XXX preliminary: This should get the actual codeinfo */
1322 /* in which the exception happened. */
1325 #if SIZEOF_VOID_P == 8
1326 sprintf(logtext + strlen(logtext),
1327 ")(0x%016lx) at position 0x%016lx (",
1328 (ptrint) code->entrypoint, (ptrint) pos);
1330 sprintf(logtext + strlen(logtext),
1331 ")(0x%08x) at position 0x%08x (",
1332 (ptrint) code->entrypoint, (ptrint) pos);
1335 if (m->class->sourcefile == NULL)
1336 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1338 utf_cat(logtext, m->class->sourcefile);
1340 sprintf(logtext + strlen(logtext), ":%d)", 0);
1344 strcat(logtext, "call_java_method");
1348 /* release memory */
1350 dump_release(dumpsize);
1354 #endif /* !defined(NDEBUG) */
1357 /* builtin_print_argument ******************************************************
1359 Prints arguments and return values for the call trace.
1361 *******************************************************************************/
1363 #if !defined(NDEBUG)
1364 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1365 typedesc *paramtype, s8 value)
1368 java_objectheader *o;
1373 switch (paramtype->type) {
1376 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1381 #if SIZEOF_VOID_P == 4
1382 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1384 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1389 #if defined(__S390__)
1391 /* The below won't work on S390 */
1395 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1400 #if SIZEOF_VOID_P == 4
1401 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1403 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1408 #if SIZEOF_VOID_P == 4
1409 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1411 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1414 /* cast to java.lang.Object */
1416 o = (java_objectheader *) (ptrint) value;
1418 /* check return argument for java.lang.Class or java.lang.String */
1421 if (o->vftbl->class == class_java_lang_String) {
1422 /* get java.lang.String object and the length of the
1425 u = javastring_toutf(o, false);
1427 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1429 /* realloc memory for string length */
1431 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1434 /* convert to utf8 string and strcat it to the logtext */
1436 strcat(logtext, " (String = \"");
1437 utf_cat(logtext, u);
1438 strcat(logtext, "\")");
1441 if (o->vftbl->class == class_java_lang_Class) {
1442 /* if the object returned is a java.lang.Class
1443 cast it to classinfo structure and get the name
1446 c = (classinfo *) o;
1451 /* if the object returned is not a java.lang.String or
1452 a java.lang.Class just print the name of the class */
1454 u = o->vftbl->class->name;
1457 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1459 /* realloc memory for string length */
1461 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1464 /* strcat to the logtext */
1466 strcat(logtext, " (Class = \"");
1467 utf_cat_classname(logtext, u);
1468 strcat(logtext, "\")");
1475 #endif /* !defined(NDEBUG) */
1477 /* builtin_verbosecall_enter ***************************************************
1479 Print method call with arguments for -verbose:call.
1481 *******************************************************************************/
1483 #if !defined(NDEBUG)
1485 #ifdef TRACE_ARGS_NUM
1486 void builtin_verbosecall_enter(s8 a0, s8 a1,
1487 # if TRACE_ARGS_NUM >= 4
1490 # if TRACE_ARGS_NUM >= 6
1493 # if TRACE_ARGS_NUM == 8
1505 #if defined(ENABLE_DEBUG_FILTER)
1506 if (! show_filters_test_verbosecall_enter(m)) return;
1509 #if defined(ENABLE_VMLOG)
1510 vmlog_cacao_enter_method(m);
1516 /* calculate message length */
1519 strlen("4294967295 ") +
1520 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1522 strlen("called: ") +
1523 utf_bytes(m->class->name) +
1525 utf_bytes(m->name) +
1526 utf_bytes(m->descriptor);
1528 /* Actually it's not possible to have all flags printed, but:
1533 strlen(" PRIVATE") +
1534 strlen(" PROTECTED") +
1537 strlen(" SYNCHRONIZED") +
1538 strlen(" VOLATILE") +
1539 strlen(" TRANSIENT") +
1541 strlen(" INTERFACE") +
1542 strlen(" ABSTRACT");
1544 /* add maximal argument length */
1548 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1549 strlen("...(255)") +
1552 /* allocate memory */
1554 dumpsize = dump_size();
1556 logtext = DMNEW(char, logtextlen);
1560 sprintf(logtext, "%10d ", callcount);
1561 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1563 pos = strlen(logtext);
1565 for (i = 0; i < methodindent; i++)
1566 logtext[pos++] = '\t';
1568 strcpy(logtext + pos, "called: ");
1570 utf_cat_classname(logtext, m->class->name);
1571 strcat(logtext, ".");
1572 utf_cat(logtext, m->name);
1573 utf_cat(logtext, m->descriptor);
1575 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1576 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1577 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1578 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1579 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1580 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1581 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1582 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1583 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1584 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1585 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1587 strcat(logtext, "(");
1589 if (md->paramcount >= 1) {
1590 logtext = builtin_print_argument(logtext, &logtextlen,
1591 &md->paramtypes[0], a0);
1594 if (md->paramcount >= 2) {
1595 strcat(logtext, ", ");
1597 logtext = builtin_print_argument(logtext, &logtextlen,
1598 &md->paramtypes[1], a1);
1601 #if TRACE_ARGS_NUM >= 4
1602 if (md->paramcount >= 3) {
1603 strcat(logtext, ", ");
1605 logtext = builtin_print_argument(logtext, &logtextlen,
1606 &md->paramtypes[2], a2);
1609 if (md->paramcount >= 4) {
1610 strcat(logtext, ", ");
1612 logtext = builtin_print_argument(logtext, &logtextlen,
1613 &md->paramtypes[3], a3);
1617 #if TRACE_ARGS_NUM >= 6
1618 if (md->paramcount >= 5) {
1619 strcat(logtext, ", ");
1621 logtext = builtin_print_argument(logtext, &logtextlen,
1622 &md->paramtypes[4], a4);
1625 if (md->paramcount >= 6) {
1626 strcat(logtext, ", ");
1628 logtext = builtin_print_argument(logtext, &logtextlen,
1629 &md->paramtypes[5], a5);
1633 #if TRACE_ARGS_NUM == 8
1634 if (md->paramcount >= 7) {
1635 strcat(logtext, ", ");
1637 logtext = builtin_print_argument(logtext, &logtextlen,
1638 &md->paramtypes[6], a6);
1641 if (md->paramcount >= 8) {
1642 strcat(logtext, ", ");
1644 logtext = builtin_print_argument(logtext, &logtextlen,
1645 &md->paramtypes[7], a7);
1649 if (md->paramcount > 8) {
1650 sprintf(logtext + strlen(logtext), ", ...(%d)",
1651 md->paramcount - TRACE_ARGS_NUM);
1654 strcat(logtext, ")");
1658 /* release memory */
1660 dump_release(dumpsize);
1666 #endif /* !defined(NDEBUG) */
1669 /* builtin_verbosecall_exit ****************************************************
1671 Print method exit for -verbose:call.
1673 *******************************************************************************/
1675 #if !defined(NDEBUG)
1676 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1686 #if defined(ENABLE_DEBUG_FILTER)
1687 if (! show_filters_test_verbosecall_exit(m)) return;
1690 #if defined(ENABLE_VMLOG)
1691 vmlog_cacao_leave_method(m);
1697 /* calculate message length */
1700 strlen("4294967295 ") +
1701 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1703 strlen("finished: ") +
1704 utf_bytes(m->class->name) +
1706 utf_bytes(m->name) +
1707 utf_bytes(m->descriptor) +
1708 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1710 /* add maximal argument length */
1712 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1714 /* allocate memory */
1716 dumpsize = dump_size();
1718 logtext = DMNEW(char, logtextlen);
1720 /* outdent the log message */
1725 log_text("WARNING: unmatched methodindent--");
1727 /* generate the message */
1729 sprintf(logtext, " ");
1730 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1732 pos = strlen(logtext);
1734 for (i = 0; i < methodindent; i++)
1735 logtext[pos++] = '\t';
1737 strcpy(logtext + pos, "finished: ");
1738 utf_cat_classname(logtext, m->class->name);
1739 strcat(logtext, ".");
1740 utf_cat(logtext, m->name);
1741 utf_cat(logtext, m->descriptor);
1743 if (!IS_VOID_TYPE(md->returntype.type)) {
1744 strcat(logtext, "->");
1746 switch (md->returntype.type) {
1763 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1768 /* release memory */
1770 dump_release(dumpsize);
1773 #endif /* !defined(NDEBUG) */
1776 #if defined(ENABLE_CYCLES_STATS)
1777 void builtin_print_cycles_stats(FILE *file)
1779 fprintf(file,"builtin cylce count statistics:\n");
1781 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1782 CYCLES_STATS_PRINT(builtin_new ,file);
1786 #endif /* defined(ENABLE_CYCLES_STATS) */
1789 /*****************************************************************************
1790 MISCELLANEOUS HELPER FUNCTIONS
1791 *****************************************************************************/
1795 /*********** Functions for integer divisions *****************************
1797 On some systems (eg. DEC ALPHA), integer division is not supported by the
1798 CPU. These helper functions implement the missing functionality.
1800 ******************************************************************************/
1802 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1803 s4 builtin_idiv(s4 a, s4 b)
1812 s4 builtin_irem(s4 a, s4 b)
1820 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1823 /* functions for long arithmetics **********************************************
1825 On systems where 64 bit Integers are not supported by the CPU,
1826 these functions are needed.
1828 ******************************************************************************/
1830 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1831 s8 builtin_ladd(s8 a, s8 b)
1844 s8 builtin_lsub(s8 a, s8 b)
1857 s8 builtin_lneg(s8 a)
1869 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1872 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1873 s8 builtin_lmul(s8 a, s8 b)
1885 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1888 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1889 s8 builtin_ldiv(s8 a, s8 b)
1902 s8 builtin_lrem(s8 a, s8 b)
1914 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1917 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1918 s8 builtin_lshl(s8 a, s4 b)
1931 s8 builtin_lshr(s8 a, s4 b)
1944 s8 builtin_lushr(s8 a, s4 b)
1949 c = ((u8) a) >> (b & 63);
1956 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1959 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1960 s8 builtin_land(s8 a, s8 b)
1973 s8 builtin_lor(s8 a, s8 b)
1986 s8 builtin_lxor(s8 a, s8 b)
1998 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2001 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2002 s4 builtin_lcmp(s8 a, s8 b)
2016 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2019 /* functions for unsupported floating instructions ****************************/
2021 /* used to convert FLT_xxx defines into float values */
2023 static inline float intBitsToFloat(s4 i)
2032 /* used to convert DBL_xxx defines into double values */
2034 static inline float longBitsToDouble(s8 l)
2044 float builtin_fadd(float a, float b)
2046 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2047 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2058 if (copysignf(1.0, a) == copysignf(1.0, b))
2061 return intBitsToFloat(FLT_NAN);
2067 float builtin_fsub(float a, float b)
2069 return builtin_fadd(a, builtin_fneg(b));
2073 float builtin_fmul(float a, float b)
2075 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2076 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2078 if (finitef(b)) return a * b;
2080 if (a == 0) return intBitsToFloat(FLT_NAN);
2081 else return copysignf(b, copysignf(1.0, b)*a);
2086 if (b == 0) return intBitsToFloat(FLT_NAN);
2087 else return copysignf(a, copysignf(1.0, a)*b);
2090 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2096 /* builtin_ddiv ****************************************************************
2098 Implementation as described in VM Spec.
2100 *******************************************************************************/
2102 float builtin_fdiv(float a, float b)
2106 /* If neither value1' nor value2' is NaN, the sign of the result */
2107 /* is positive if both values have the same sign, negative if the */
2108 /* values have different signs. */
2114 /* If either value1' or value2' is NaN, the result is NaN. */
2116 return intBitsToFloat(FLT_NAN);
2119 /* Division of a finite value by an infinity results in a */
2120 /* signed zero, with the sign-producing rule just given. */
2122 /* is sign equal? */
2124 if (copysignf(1.0, a) == copysignf(1.0, b))
2133 /* If either value1' or value2' is NaN, the result is NaN. */
2135 return intBitsToFloat(FLT_NAN);
2137 } else if (finitef(b)) {
2138 /* Division of an infinity by a finite value results in a signed */
2139 /* infinity, with the sign-producing rule just given. */
2141 /* is sign equal? */
2143 if (copysignf(1.0, a) == copysignf(1.0, b))
2144 return intBitsToFloat(FLT_POSINF);
2146 return intBitsToFloat(FLT_NEGINF);
2149 /* Division of an infinity by an infinity results in NaN. */
2151 return intBitsToFloat(FLT_NAN);
2157 float builtin_fneg(float a)
2159 if (isnanf(a)) return a;
2161 if (finitef(a)) return -a;
2162 else return copysignf(a, -copysignf(1.0, a));
2165 #endif /* !SUPPORT_FLOAT */
2168 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2169 s4 builtin_fcmpl(float a, float b)
2177 if (!finitef(a) || !finitef(b)) {
2178 a = finitef(a) ? 0 : copysignf(1.0, a);
2179 b = finitef(b) ? 0 : copysignf(1.0, b);
2192 s4 builtin_fcmpg(float a, float b)
2194 if (isnanf(a)) return 1;
2195 if (isnanf(b)) return 1;
2196 if (!finitef(a) || !finitef(b)) {
2197 a = finitef(a) ? 0 : copysignf(1.0, a);
2198 b = finitef(b) ? 0 : copysignf(1.0, b);
2200 if (a > b) return 1;
2201 if (a == b) return 0;
2204 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2207 float builtin_frem(float a, float b)
2213 /* functions for unsupported double instructions ******************************/
2216 double builtin_dadd(double a, double b)
2218 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2219 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2221 if (finite(b)) return a + b;
2225 if (finite(b)) return a;
2227 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2228 else return longBitsToDouble(DBL_NAN);
2234 double builtin_dsub(double a, double b)
2236 return builtin_dadd(a, builtin_dneg(b));
2240 double builtin_dmul(double a, double b)
2242 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2243 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2245 if (finite(b)) return a * b;
2247 if (a == 0) return longBitsToDouble(DBL_NAN);
2248 else return copysign(b, copysign(1.0, b) * a);
2253 if (b == 0) return longBitsToDouble(DBL_NAN);
2254 else return copysign(a, copysign(1.0, a) * b);
2257 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2263 /* builtin_ddiv ****************************************************************
2265 Implementation as described in VM Spec.
2267 *******************************************************************************/
2269 double builtin_ddiv(double a, double b)
2273 /* If neither value1' nor value2' is NaN, the sign of the result */
2274 /* is positive if both values have the same sign, negative if the */
2275 /* values have different signs. */
2281 /* If either value1' or value2' is NaN, the result is NaN. */
2283 return longBitsToDouble(DBL_NAN);
2286 /* Division of a finite value by an infinity results in a */
2287 /* signed zero, with the sign-producing rule just given. */
2289 /* is sign equal? */
2291 if (copysign(1.0, a) == copysign(1.0, b))
2300 /* If either value1' or value2' is NaN, the result is NaN. */
2302 return longBitsToDouble(DBL_NAN);
2304 } else if (finite(b)) {
2305 /* Division of an infinity by a finite value results in a signed */
2306 /* infinity, with the sign-producing rule just given. */
2308 /* is sign equal? */
2310 if (copysign(1.0, a) == copysign(1.0, b))
2311 return longBitsToDouble(DBL_POSINF);
2313 return longBitsToDouble(DBL_NEGINF);
2316 /* Division of an infinity by an infinity results in NaN. */
2318 return longBitsToDouble(DBL_NAN);
2324 /* builtin_dneg ****************************************************************
2326 Implemented as described in VM Spec.
2328 *******************************************************************************/
2330 double builtin_dneg(double a)
2333 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2340 /* If the operand is a zero, the result is the zero of opposite */
2346 /* If the operand is an infinity, the result is the infinity of */
2347 /* opposite sign. */
2349 return copysign(a, -copysign(1.0, a));
2353 #endif /* !SUPPORT_DOUBLE */
2356 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2357 s4 builtin_dcmpl(double a, double b)
2365 if (!finite(a) || !finite(b)) {
2366 a = finite(a) ? 0 : copysign(1.0, a);
2367 b = finite(b) ? 0 : copysign(1.0, b);
2380 s4 builtin_dcmpg(double a, double b)
2388 if (!finite(a) || !finite(b)) {
2389 a = finite(a) ? 0 : copysign(1.0, a);
2390 b = finite(b) ? 0 : copysign(1.0, b);
2401 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2404 double builtin_drem(double a, double b)
2410 /* conversion operations ******************************************************/
2413 s8 builtin_i2l(s4 i)
2425 s4 builtin_l2i(s8 l)
2436 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2437 float builtin_i2f(s4 a)
2439 float f = (float) a;
2442 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2445 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2446 double builtin_i2d(s4 a)
2448 double d = (double) a;
2451 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2454 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2455 float builtin_l2f(s8 a)
2458 float f = (float) a;
2464 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2467 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2468 double builtin_l2d(s8 a)
2471 double d = (double) a;
2477 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2480 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2481 s4 builtin_f2i(float a)
2485 i = builtin_d2i((double) a);
2496 if (a < (-2147483648))
2497 return (-2147483648);
2500 f = copysignf((float) 1.0, a);
2503 return (-2147483648); */
2505 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2508 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2509 s8 builtin_f2l(float a)
2513 l = builtin_d2l((double) a);
2520 if (a > 9223372036854775807L)
2521 return 9223372036854775807L;
2522 if (a < (-9223372036854775808L))
2523 return (-9223372036854775808L);
2528 f = copysignf((float) 1.0, a);
2530 return 9223372036854775807L;
2531 return (-9223372036854775808L); */
2533 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2536 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2537 s4 builtin_d2i(double a)
2542 if (a >= 2147483647)
2544 if (a <= (-2147483647-1))
2545 return (-2147483647-1);
2550 d = copysign(1.0, a);
2553 return (-2147483647-1);
2555 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2558 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2559 s8 builtin_d2l(double a)
2564 if (a >= 9223372036854775807LL)
2565 return 9223372036854775807LL;
2566 if (a <= (-9223372036854775807LL-1))
2567 return (-9223372036854775807LL-1);
2572 d = copysign(1.0, a);
2574 return 9223372036854775807LL;
2575 return (-9223372036854775807LL-1);
2577 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2580 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2581 double builtin_f2d(float a)
2583 if (finitef(a)) return (double) a;
2586 return longBitsToDouble(DBL_NAN);
2588 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2592 float builtin_d2f(double a)
2598 return intBitsToFloat(FLT_NAN);
2600 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2603 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2606 /* builtin_arraycopy ***********************************************************
2608 Builtin for java.lang.System.arraycopy.
2610 ATTENTION: This builtin function returns a boolean value to signal
2611 the ICMD_BUILTIN if there was an exception.
2613 *******************************************************************************/
2615 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2616 java_arrayheader *dest, s4 destStart, s4 len)
2618 arraydescriptor *sdesc;
2619 arraydescriptor *ddesc;
2622 if ((src == NULL) || (dest == NULL)) {
2623 exceptions_throw_nullpointerexception();
2627 sdesc = src->objheader.vftbl->arraydesc;
2628 ddesc = dest->objheader.vftbl->arraydesc;
2630 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2631 exceptions_throw_arraystoreexception();
2635 /* we try to throw exception with the same message as SUN does */
2637 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2638 (srcStart + len < 0) || (srcStart + len > src->size) ||
2639 (destStart + len < 0) || (destStart + len > dest->size)) {
2640 exceptions_throw_arrayindexoutofboundsexception();
2644 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2645 /* We copy primitive values or references of exactly the same type */
2647 s4 dataoffset = sdesc->dataoffset;
2648 s4 componentsize = sdesc->componentsize;
2650 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2651 ((u1 *) src) + dataoffset + componentsize * srcStart,
2652 (size_t) len * componentsize);
2655 /* We copy references of different type */
2657 java_objectarray *oas = (java_objectarray *) src;
2658 java_objectarray *oad = (java_objectarray *) dest;
2660 if (destStart <= srcStart) {
2661 for (i = 0; i < len; i++) {
2662 java_objectheader *o = oas->data[srcStart + i];
2664 if (!builtin_canstore(oad, o))
2667 oad->data[destStart + i] = o;
2671 /* XXX this does not completely obey the specification!
2672 If an exception is thrown only the elements above the
2673 current index have been copied. The specification
2674 requires that only the elements *below* the current
2675 index have been copied before the throw. */
2677 for (i = len - 1; i >= 0; i--) {
2678 java_objectheader *o = oas->data[srcStart + i];
2680 if (!builtin_canstore(oad, o))
2683 oad->data[destStart + i] = o;
2692 /* builtin_nanotime ************************************************************
2694 Return the current time in nanoseconds.
2696 *******************************************************************************/
2698 s8 builtin_nanotime(void)
2703 if (gettimeofday(&tv, NULL) == -1)
2704 vm_abort("gettimeofday failed: %s", strerror(errno));
2706 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2708 return usecs * 1000;
2712 /* builtin_currenttimemillis ***************************************************
2714 Return the current time in milliseconds.
2716 *******************************************************************************/
2718 s8 builtin_currenttimemillis(void)
2722 msecs = builtin_nanotime() / 1000 / 1000;
2728 /* builtin_clone ***************************************************************
2730 Function for cloning objects or arrays.
2732 *******************************************************************************/
2734 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2736 arraydescriptor *ad;
2737 java_arrayheader *ah;
2740 java_objectheader *co; /* cloned object header */
2742 /* get the array descriptor */
2744 ad = o->vftbl->arraydesc;
2746 /* we are cloning an array */
2749 ah = (java_arrayheader *) o;
2751 size = ad->dataoffset + ad->componentsize * ah->size;
2753 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2758 MCOPY(co, o, u1, size);
2760 #if defined(ENABLE_GC_CACAO)
2761 heap_init_objectheader(co, size);
2764 #if defined(ENABLE_THREADS)
2765 lock_init_object_lock(co);
2771 /* we are cloning a non-array */
2773 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2774 exceptions_throw_clonenotsupportedexception();
2778 /* get the class of the object */
2780 c = o->vftbl->class;
2782 /* create new object */
2784 co = builtin_new(c);
2789 MCOPY(co, o, u1, c->instancesize);
2791 #if defined(ENABLE_GC_CACAO)
2792 heap_init_objectheader(co, c->instancesize);
2795 #if defined(ENABLE_THREADS)
2796 lock_init_object_lock(co);
2802 #if defined(ENABLE_VMLOG)
2804 #include <vmlog_cacao.c>
2809 * These are local overrides for various environment variables in Emacs.
2810 * Please do not remove this and leave it at the end of the file, where
2811 * Emacs will automagically detect them.
2812 * ---------------------------------------------------------------------
2815 * indent-tabs-mode: t
2819 * vim:noexpandtab:sw=4:ts=4: