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 8060 2007-06-10 20:00:40Z twisti $
49 #include "fdlibm/fdlibm.h"
50 #if defined(__CYGWIN__) && defined(Bias)
54 #include "mm/gc-common.h"
55 #include "mm/memory.h"
57 #include "native/jni.h"
58 #include "native/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,
181 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
182 bte->md = descriptor_pool_parse_method_descriptor(descpool,
187 for (bte = builtintable_function; bte->fp != NULL; bte++) {
188 bte->md = descriptor_pool_parse_method_descriptor(descpool,
193 /* release dump area */
195 dump_release(dumpsize);
201 /* builtintable_comparator *****************************************************
203 qsort comparator for the automatic builtin table.
205 *******************************************************************************/
207 static int builtintable_comparator(const void *a, const void *b)
209 builtintable_entry *bte1;
210 builtintable_entry *bte2;
212 bte1 = (builtintable_entry *) a;
213 bte2 = (builtintable_entry *) b;
215 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
219 /* builtintable_sort_automatic *************************************************
221 Sorts the automatic builtin table.
223 *******************************************************************************/
225 static void builtintable_sort_automatic(void)
229 /* calculate table size statically (`- 1' comment see builtintable.inc) */
231 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
233 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
234 builtintable_comparator);
238 /* builtin_init ****************************************************************
240 Initialize the global table of builtin functions.
242 *******************************************************************************/
244 bool builtin_init(void)
246 /* initialize the builtin tables */
248 if (!builtintable_init())
251 /* sort builtin tables */
253 builtintable_sort_automatic();
259 /* builtintable_get_internal ***************************************************
261 Finds an entry in the builtintable for internal functions and
262 returns the a pointer to the structure.
264 *******************************************************************************/
266 builtintable_entry *builtintable_get_internal(functionptr fp)
268 builtintable_entry *bte;
270 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
279 /* builtintable_get_automatic **************************************************
281 Finds an entry in the builtintable for functions which are replaced
282 automatically and returns the a pointer to the structure.
284 *******************************************************************************/
286 builtintable_entry *builtintable_get_automatic(s4 opcode)
288 builtintable_entry *first;
289 builtintable_entry *last;
290 builtintable_entry *middle;
294 /* calculate table size statically (`- 1' comment see builtintable.inc) */
296 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
298 first = builtintable_automatic;
299 last = builtintable_automatic + entries;
301 while (entries > 0) {
303 middle = first + half;
305 if (middle->opcode < opcode) {
312 return (first != last ? first : NULL);
316 /* builtintable_replace_function ***********************************************
320 *******************************************************************************/
322 #if defined(ENABLE_JIT)
323 bool builtintable_replace_function(void *iptr_)
326 builtintable_entry *bte;
329 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
331 /* get name and descriptor of the function */
334 case ICMD_INVOKESTATIC:
335 /* The instruction MUST be resolved, otherwise we run into
336 lazy loading troubles. Anyway, we should/can only replace
337 very VM-close functions. */
339 if (INSTRUCTION_IS_UNRESOLVED(iptr))
342 mr = iptr->sx.s23.s3.fmiref;
349 /* search the function table */
351 for (bte = builtintable_function; bte->fp != NULL; bte++) {
352 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
353 (mr->name == bte->name) &&
354 (mr->descriptor == bte->descriptor)) {
356 /* set the values in the instruction */
358 iptr->opc = bte->opcode;
359 iptr->sx.s23.s3.bte = bte;
360 if (bte->checkexception)
361 iptr->flags.bits |= INS_FLAG_CHECK;
363 iptr->flags.bits &= ~INS_FLAG_CHECK;
371 #endif /* defined(ENABLE_JIT) */
374 /*****************************************************************************
376 *****************************************************************************/
378 /* builtin_instanceof **********************************************************
380 Checks if an object is an instance of some given class (or subclass
381 of that class). If class is an interface, checks if the interface
384 Return value: 1 ... o is an instance of class or implements the interface
385 0 ... otherwise or if o == NULL
387 *******************************************************************************/
389 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
394 return class_isanysubclass(o->vftbl->class, class);
399 /* builtin_checkcast ***********************************************************
401 The same as builtin_instanceof except that 1 is returned when o ==
404 *******************************************************************************/
406 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
411 if (class_isanysubclass(o->vftbl->class, class))
418 /* builtin_descriptorscompatible ***********************************************
420 Checks if two array type descriptors are assignment compatible
422 Return value: 1 ... target = desc is possible
425 *******************************************************************************/
427 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
428 arraydescriptor *target)
433 if (desc->arraytype != target->arraytype)
436 if (desc->arraytype != ARRAYTYPE_OBJECT)
439 /* {both arrays are arrays of references} */
441 if (desc->dimension == target->dimension) {
442 /* an array which contains elements of interface types is
443 allowed to be casted to Object (JOWENN)*/
445 if ((desc->elementvftbl->baseval < 0) &&
446 (target->elementvftbl->baseval == 1))
449 return class_isanysubclass(desc->elementvftbl->class,
450 target->elementvftbl->class);
453 if (desc->dimension < target->dimension)
456 /* {desc has higher dimension than target} */
458 return class_isanysubclass(pseudo_class_Arraystub,
459 target->elementvftbl->class);
463 /* builtin_arraycheckcast ******************************************************
465 Checks if an object is really a subtype of the requested array
466 type. The object has to be an array to begin with. For simple
467 arrays (int, short, double, etc.) the types have to match exactly.
468 For arrays of objects, the type of elements in the array has to be
469 a subtype (or the same type) of the requested element type. For
470 arrays of arrays (which in turn can again be arrays of arrays), the
471 types at the lowest level have to satisfy the corresponding sub
474 *******************************************************************************/
476 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
478 arraydescriptor *desc;
483 desc = o->vftbl->arraydesc;
488 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
492 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
497 return builtin_arraycheckcast(o, targetclass);
501 /* builtin_throw_exception *****************************************************
503 Sets the exceptionptr with the thrown exception and prints some
504 debugging information. Called from asm_vm_call_method.
506 *******************************************************************************/
508 void *builtin_throw_exception(java_objectheader *xptr)
511 java_lang_Throwable *t;
517 t = (java_lang_Throwable *) xptr;
519 /* calculate message length */
521 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
525 utf_bytes(xptr->vftbl->class->name);
526 if (t->detailMessage) {
527 logtextlen += strlen(": ") +
528 u2_utflength(t->detailMessage->value->data
529 + t->detailMessage->offset,
530 t->detailMessage->count);
534 logtextlen += strlen("(nil)");
537 /* allocate memory */
539 dumpsize = dump_size();
541 logtext = DMNEW(char, logtextlen);
543 strcpy(logtext, "Builtin exception thrown: ");
546 utf_cat_classname(logtext, xptr->vftbl->class->name);
548 if (t->detailMessage) {
551 buf = javastring_tochar((java_objectheader *) t->detailMessage);
552 strcat(logtext, ": ");
553 strcat(logtext, buf);
554 MFREE(buf, char, strlen(buf) + 1);
558 strcat(logtext, "(nil)");
565 dump_release(dumpsize);
567 #endif /* !defined(NDEBUG) */
569 /* actually set the exception */
571 exceptions_set_exception(xptr);
573 /* Return a NULL pointer. This is required for vm_call_method to
574 check for an exception. This is for convenience. */
580 /* builtin_canstore ************************************************************
582 Checks, if an object can be stored in an array.
584 Return value: 1 ... possible
585 0 ... otherwise (throws an ArrayStoreException)
587 *******************************************************************************/
589 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
591 arraydescriptor *desc;
592 arraydescriptor *valuedesc;
593 vftbl_t *componentvftbl;
596 castinfo classvalues;
602 /* The following is guaranteed (by verifier checks):
604 * *) oa->...vftbl->arraydesc != NULL
605 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
606 * *) o->vftbl is not an interface vftbl
609 desc = oa->header.objheader.vftbl->arraydesc;
610 componentvftbl = desc->componentvftbl;
611 valuevftbl = o->vftbl;
612 valuedesc = valuevftbl->arraydesc;
614 if ((desc->dimension - 1) == 0) {
615 /* {oa is a one-dimensional array} */
616 /* {oa is an array of references} */
618 if (valuevftbl == componentvftbl)
621 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
623 base = classvalues.super_baseval;
626 /* an array of interface references */
628 result = ((valuevftbl->interfacetablelength > -base) &&
629 (valuevftbl->interfacetable[base] != NULL));
632 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
633 <= (unsigned) classvalues.super_diffval);
636 else if (valuedesc == NULL) {
637 /* {oa has dimension > 1} */
638 /* {componentvftbl->arraydesc != NULL} */
640 /* check if o is an array */
645 /* {o is an array} */
647 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
650 /* if not possible, throw an exception */
653 exceptions_throw_arraystoreexception();
661 /* This is an optimized version where a is guaranteed to be one-dimensional */
662 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
664 arraydescriptor *desc;
665 vftbl_t *elementvftbl;
669 castinfo classvalues;
673 /* The following is guaranteed (by verifier checks):
675 * *) a->...vftbl->arraydesc != NULL
676 * *) a->...vftbl->arraydesc->elementvftbl != NULL
677 * *) a->...vftbl->arraydesc->dimension == 1
678 * *) o->vftbl is not an interface vftbl
681 desc = a->header.objheader.vftbl->arraydesc;
682 elementvftbl = desc->elementvftbl;
683 valuevftbl = o->vftbl;
685 /* {a is a one-dimensional array} */
687 if (valuevftbl == elementvftbl)
690 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
692 if ((base = classvalues.super_baseval) <= 0)
693 /* an array of interface references */
694 return (valuevftbl->interfacetablelength > -base &&
695 valuevftbl->interfacetable[base] != NULL);
697 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
698 <= (unsigned) classvalues.super_diffval;
704 /* This is an optimized version where a is guaranteed to be a
705 * one-dimensional array of a class type */
706 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
708 vftbl_t *elementvftbl;
711 castinfo classvalues;
715 /* The following is guaranteed (by verifier checks):
717 * *) a->...vftbl->arraydesc != NULL
718 * *) a->...vftbl->arraydesc->elementvftbl != NULL
719 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
720 * *) a->...vftbl->arraydesc->dimension == 1
721 * *) o->vftbl is not an interface vftbl
724 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
725 valuevftbl = o->vftbl;
727 /* {a is a one-dimensional array} */
729 if (valuevftbl == elementvftbl)
732 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
734 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
735 <= (unsigned) classvalues.super_diffval;
741 /* builtin_new *****************************************************************
743 Creates a new instance of class c on the heap.
745 Return value: pointer to the object or NULL if no memory is
748 *******************************************************************************/
750 java_objectheader *builtin_new(classinfo *c)
752 java_objectheader *o;
753 #if defined(ENABLE_RT_TIMING)
754 struct timespec time_start, time_end;
756 #if defined(ENABLE_CYCLES_STATS)
757 u8 cycles_start, cycles_end;
760 RT_TIMING_GET_TIME(time_start);
761 CYCLES_STATS_GET(cycles_start);
763 /* is the class loaded */
765 assert(c->state & CLASS_LOADED);
767 /* check if we can instantiate this class */
769 if (c->flags & ACC_ABSTRACT) {
770 exceptions_throw_instantiationerror(c);
774 /* is the class linked */
776 if (!(c->state & CLASS_LINKED))
780 if (!(c->state & CLASS_INITIALIZED)) {
783 log_message_class("Initialize class (from builtin_new): ", c);
786 if (!initialize_class(c))
790 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
798 #if defined(ENABLE_THREADS)
799 lock_init_object_lock(o);
802 CYCLES_STATS_GET(cycles_end);
803 RT_TIMING_GET_TIME(time_end);
805 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
806 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
812 /* builtin_newarray ************************************************************
814 Creates an array with the given vftbl on the heap. This function
815 takes as class argument an array class.
817 Return value: pointer to the array or NULL if no memory is available
819 *******************************************************************************/
821 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
823 arraydescriptor *desc;
828 #if defined(ENABLE_RT_TIMING)
829 struct timespec time_start, time_end;
832 RT_TIMING_GET_TIME(time_start);
834 desc = arrayclass->vftbl->arraydesc;
835 dataoffset = desc->dataoffset;
836 componentsize = desc->componentsize;
839 exceptions_throw_negativearraysizeexception();
843 actualsize = dataoffset + size * componentsize;
845 /* check for overflow */
847 if (((u4) actualsize) < ((u4) size)) {
848 exceptions_throw_outofmemoryerror();
852 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
857 a->objheader.vftbl = arrayclass->vftbl;
859 #if defined(ENABLE_THREADS)
860 lock_init_object_lock(&a->objheader);
865 RT_TIMING_GET_TIME(time_end);
866 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
872 /* builtin_anewarray ***********************************************************
874 Creates an array of references to the given class type on the heap.
876 Return value: pointer to the array or NULL if no memory is
879 *******************************************************************************/
881 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
883 classinfo *arrayclass;
885 /* is class loaded */
887 assert(componentclass->state & CLASS_LOADED);
889 /* is class linked */
891 if (!(componentclass->state & CLASS_LINKED))
892 if (!link_class(componentclass))
895 arrayclass = class_array_of(componentclass, true);
900 return (java_objectarray *) builtin_newarray(size, arrayclass);
904 /* builtin_newarray_boolean ****************************************************
906 Creates an array of bytes on the heap. The array is designated as
907 an array of booleans (important for casts)
909 Return value: pointer to the array or NULL if no memory is
912 *******************************************************************************/
914 java_booleanarray *builtin_newarray_boolean(s4 size)
916 return (java_booleanarray *)
917 builtin_newarray(size,
918 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
922 /* builtin_newarray_byte *******************************************************
924 Creates an array of 8 bit Integers on the heap.
926 Return value: pointer to the array or NULL if no memory is
929 *******************************************************************************/
931 java_bytearray *builtin_newarray_byte(s4 size)
933 return (java_bytearray *)
934 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
938 /* builtin_newarray_char *******************************************************
940 Creates an array of characters on the heap.
942 Return value: pointer to the array or NULL if no memory is
945 *******************************************************************************/
947 java_chararray *builtin_newarray_char(s4 size)
949 return (java_chararray *)
950 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
954 /* builtin_newarray_short ******************************************************
956 Creates an array of 16 bit Integers on the heap.
958 Return value: pointer to the array or NULL if no memory is
961 *******************************************************************************/
963 java_shortarray *builtin_newarray_short(s4 size)
965 return (java_shortarray *)
966 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
970 /* builtin_newarray_int ********************************************************
972 Creates an array of 32 bit Integers on the heap.
974 Return value: pointer to the array or NULL if no memory is
977 *******************************************************************************/
979 java_intarray *builtin_newarray_int(s4 size)
981 return (java_intarray *)
982 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
986 /* builtin_newarray_long *******************************************************
988 Creates an array of 64 bit Integers on the heap.
990 Return value: pointer to the array or NULL if no memory is
993 *******************************************************************************/
995 java_longarray *builtin_newarray_long(s4 size)
997 return (java_longarray *)
998 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1002 /* builtin_newarray_float ******************************************************
1004 Creates an array of 32 bit IEEE floats on the heap.
1006 Return value: pointer to the array or NULL if no memory is
1009 *******************************************************************************/
1011 java_floatarray *builtin_newarray_float(s4 size)
1013 return (java_floatarray *)
1014 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1018 /* builtin_newarray_double *****************************************************
1020 Creates an array of 64 bit IEEE floats on the heap.
1022 Return value: pointer to the array or NULL if no memory is
1025 *******************************************************************************/
1027 java_doublearray *builtin_newarray_double(s4 size)
1029 return (java_doublearray *)
1030 builtin_newarray(size,
1031 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1035 /* builtin_multianewarray_intern ***********************************************
1037 Creates a multi-dimensional array on the heap. The dimensions are
1038 passed in an array of longs.
1041 n.............number of dimensions to create
1042 arrayclass....the array class
1043 dims..........array containing the size of each dimension to create
1045 Return value: pointer to the array or NULL if no memory is
1048 ******************************************************************************/
1050 static java_arrayheader *builtin_multianewarray_intern(int n,
1051 classinfo *arrayclass,
1055 java_arrayheader *a;
1056 classinfo *componentclass;
1059 /* create this dimension */
1061 size = (s4) dims[0];
1062 a = builtin_newarray(size, arrayclass);
1067 /* if this is the last dimension return */
1072 /* get the class of the components to create */
1074 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1076 /* The verifier guarantees that the dimension count is in the range. */
1078 /* create the component arrays */
1080 for (i = 0; i < size; i++) {
1081 java_arrayheader *ea =
1082 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1083 /* we save an s4 to a s8 slot, 8-byte aligned */
1085 builtin_multianewarray_intern(n, componentclass, dims + 2);
1087 builtin_multianewarray_intern(n, componentclass, dims + 1);
1093 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1100 /* builtin_multianewarray ******************************************************
1102 Wrapper for builtin_multianewarray_intern which checks all
1103 dimensions before we start allocating.
1105 ******************************************************************************/
1107 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1113 /* check all dimensions before doing anything */
1115 for (i = 0; i < n; i++) {
1116 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1117 /* we save an s4 to a s8 slot, 8-byte aligned */
1118 size = (s4) dims[i * 2];
1120 size = (s4) dims[i];
1124 exceptions_throw_negativearraysizeexception();
1129 /* now call the real function */
1131 return builtin_multianewarray_intern(n, arrayclass, dims);
1135 /*****************************************************************************
1138 Various functions for printing a message at method entry or exit (for
1141 *****************************************************************************/
1143 #if !defined(NDEBUG)
1144 static s4 methodindent = 0;
1145 static u4 callcount = 0;
1147 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1157 #if defined(ENABLE_DEBUG_FILTER)
1158 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1161 #if defined(ENABLE_VMLOG)
1165 if (opt_verbosecall && indent)
1168 /* calculate message length */
1172 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1175 logtextlen = strlen("Some Throwable");
1178 logtextlen += strlen(" thrown in ");
1182 utf_bytes(m->class->name) +
1184 utf_bytes(m->name) +
1185 utf_bytes(m->descriptor) +
1186 strlen("(NOSYNC,NATIVE");
1188 #if SIZEOF_VOID_P == 8
1190 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1192 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1195 if (m->class->sourcefile == NULL)
1196 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1198 logtextlen += utf_bytes(m->class->sourcefile);
1200 logtextlen += strlen(":65536)");
1204 logtextlen += strlen("call_java_method");
1207 logtextlen += strlen("0");
1209 /* allocate memory */
1211 dumpsize = dump_size();
1213 logtext = DMNEW(char, logtextlen);
1216 strcpy(logtext, "Exception ");
1217 utf_cat_classname(logtext, xptr->vftbl->class->name);
1220 strcpy(logtext, "Some Throwable");
1223 strcat(logtext, " thrown in ");
1226 utf_cat_classname(logtext, m->class->name);
1227 strcat(logtext, ".");
1228 utf_cat(logtext, m->name);
1229 utf_cat(logtext, m->descriptor);
1231 if (m->flags & ACC_SYNCHRONIZED)
1232 strcat(logtext, "(SYNC");
1234 strcat(logtext, "(NOSYNC");
1236 if (m->flags & ACC_NATIVE) {
1237 strcat(logtext, ",NATIVE");
1241 #if SIZEOF_VOID_P == 8
1242 sprintf(logtext + strlen(logtext),
1243 ")(0x%016lx) at position 0x%016lx",
1244 (ptrint) code->entrypoint, (ptrint) pos);
1246 sprintf(logtext + strlen(logtext),
1247 ")(0x%08x) at position 0x%08x",
1248 (ptrint) code->entrypoint, (ptrint) pos);
1253 /* XXX preliminary: This should get the actual codeinfo */
1254 /* in which the exception happened. */
1257 #if SIZEOF_VOID_P == 8
1258 sprintf(logtext + strlen(logtext),
1259 ")(0x%016lx) at position 0x%016lx (",
1260 (ptrint) code->entrypoint, (ptrint) pos);
1262 sprintf(logtext + strlen(logtext),
1263 ")(0x%08x) at position 0x%08x (",
1264 (ptrint) code->entrypoint, (ptrint) pos);
1267 if (m->class->sourcefile == NULL)
1268 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1270 utf_cat(logtext, m->class->sourcefile);
1272 sprintf(logtext + strlen(logtext), ":%d)", 0);
1276 strcat(logtext, "call_java_method");
1280 /* release memory */
1282 dump_release(dumpsize);
1286 #endif /* !defined(NDEBUG) */
1289 /* builtin_print_argument ******************************************************
1291 Prints arguments and return values for the call trace.
1293 *******************************************************************************/
1295 #if !defined(NDEBUG)
1296 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1297 typedesc *paramtype, s8 value)
1300 java_objectheader *o;
1305 switch (paramtype->type) {
1308 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1313 #if SIZEOF_VOID_P == 4
1314 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1316 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1321 #if defined(__S390__)
1323 /* The below won't work on S390 */
1327 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1332 #if SIZEOF_VOID_P == 4
1333 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1335 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1340 #if SIZEOF_VOID_P == 4
1341 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1343 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1346 /* cast to java.lang.Object */
1348 o = (java_objectheader *) (ptrint) value;
1350 /* check return argument for java.lang.Class or java.lang.String */
1353 if (o->vftbl->class == class_java_lang_String) {
1354 /* get java.lang.String object and the length of the
1357 u = javastring_toutf(o, false);
1359 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1361 /* realloc memory for string length */
1363 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1366 /* convert to utf8 string and strcat it to the logtext */
1368 strcat(logtext, " (String = \"");
1369 utf_cat(logtext, u);
1370 strcat(logtext, "\")");
1373 if (o->vftbl->class == class_java_lang_Class) {
1374 /* if the object returned is a java.lang.Class
1375 cast it to classinfo structure and get the name
1378 c = (classinfo *) o;
1383 /* if the object returned is not a java.lang.String or
1384 a java.lang.Class just print the name of the class */
1386 u = o->vftbl->class->name;
1389 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1391 /* realloc memory for string length */
1393 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1396 /* strcat to the logtext */
1398 strcat(logtext, " (Class = \"");
1399 utf_cat_classname(logtext, u);
1400 strcat(logtext, "\")");
1407 #endif /* !defined(NDEBUG) */
1409 /* builtin_verbosecall_enter ***************************************************
1411 Print method call with arguments for -verbose:call.
1413 *******************************************************************************/
1415 #if !defined(NDEBUG)
1417 #ifdef TRACE_ARGS_NUM
1418 void builtin_verbosecall_enter(s8 a0, s8 a1,
1419 # if TRACE_ARGS_NUM >= 4
1422 # if TRACE_ARGS_NUM >= 6
1425 # if TRACE_ARGS_NUM == 8
1437 #if defined(ENABLE_DEBUG_FILTER)
1438 if (! show_filters_test_verbosecall_enter(m)) return;
1441 #if defined(ENABLE_VMLOG)
1442 vmlog_cacao_enter_method(m);
1448 /* calculate message length */
1451 strlen("4294967295 ") +
1452 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1454 strlen("called: ") +
1455 utf_bytes(m->class->name) +
1457 utf_bytes(m->name) +
1458 utf_bytes(m->descriptor);
1460 /* Actually it's not possible to have all flags printed, but:
1465 strlen(" PRIVATE") +
1466 strlen(" PROTECTED") +
1469 strlen(" SYNCHRONIZED") +
1470 strlen(" VOLATILE") +
1471 strlen(" TRANSIENT") +
1473 strlen(" INTERFACE") +
1474 strlen(" ABSTRACT");
1476 /* add maximal argument length */
1480 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1481 strlen("...(255)") +
1484 /* allocate memory */
1486 dumpsize = dump_size();
1488 logtext = DMNEW(char, logtextlen);
1492 sprintf(logtext, "%10d ", callcount);
1493 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1495 pos = strlen(logtext);
1497 for (i = 0; i < methodindent; i++)
1498 logtext[pos++] = '\t';
1500 strcpy(logtext + pos, "called: ");
1502 utf_cat_classname(logtext, m->class->name);
1503 strcat(logtext, ".");
1504 utf_cat(logtext, m->name);
1505 utf_cat(logtext, m->descriptor);
1507 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1508 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1509 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1510 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1511 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1512 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1513 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1514 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1515 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1516 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1517 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1519 strcat(logtext, "(");
1521 if (md->paramcount >= 1) {
1522 logtext = builtin_print_argument(logtext, &logtextlen,
1523 &md->paramtypes[0], a0);
1526 if (md->paramcount >= 2) {
1527 strcat(logtext, ", ");
1529 logtext = builtin_print_argument(logtext, &logtextlen,
1530 &md->paramtypes[1], a1);
1533 #if TRACE_ARGS_NUM >= 4
1534 if (md->paramcount >= 3) {
1535 strcat(logtext, ", ");
1537 logtext = builtin_print_argument(logtext, &logtextlen,
1538 &md->paramtypes[2], a2);
1541 if (md->paramcount >= 4) {
1542 strcat(logtext, ", ");
1544 logtext = builtin_print_argument(logtext, &logtextlen,
1545 &md->paramtypes[3], a3);
1549 #if TRACE_ARGS_NUM >= 6
1550 if (md->paramcount >= 5) {
1551 strcat(logtext, ", ");
1553 logtext = builtin_print_argument(logtext, &logtextlen,
1554 &md->paramtypes[4], a4);
1557 if (md->paramcount >= 6) {
1558 strcat(logtext, ", ");
1560 logtext = builtin_print_argument(logtext, &logtextlen,
1561 &md->paramtypes[5], a5);
1565 #if TRACE_ARGS_NUM == 8
1566 if (md->paramcount >= 7) {
1567 strcat(logtext, ", ");
1569 logtext = builtin_print_argument(logtext, &logtextlen,
1570 &md->paramtypes[6], a6);
1573 if (md->paramcount >= 8) {
1574 strcat(logtext, ", ");
1576 logtext = builtin_print_argument(logtext, &logtextlen,
1577 &md->paramtypes[7], a7);
1581 if (md->paramcount > 8) {
1582 sprintf(logtext + strlen(logtext), ", ...(%d)",
1583 md->paramcount - TRACE_ARGS_NUM);
1586 strcat(logtext, ")");
1590 /* release memory */
1592 dump_release(dumpsize);
1598 #endif /* !defined(NDEBUG) */
1601 /* builtin_verbosecall_exit ****************************************************
1603 Print method exit for -verbose:call.
1605 *******************************************************************************/
1607 #if !defined(NDEBUG)
1608 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1618 #if defined(ENABLE_DEBUG_FILTER)
1619 if (! show_filters_test_verbosecall_exit(m)) return;
1622 #if defined(ENABLE_VMLOG)
1623 vmlog_cacao_leave_method(m);
1629 /* calculate message length */
1632 strlen("4294967295 ") +
1633 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1635 strlen("finished: ") +
1636 utf_bytes(m->class->name) +
1638 utf_bytes(m->name) +
1639 utf_bytes(m->descriptor) +
1640 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1642 /* add maximal argument length */
1644 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1646 /* allocate memory */
1648 dumpsize = dump_size();
1650 logtext = DMNEW(char, logtextlen);
1652 /* outdent the log message */
1657 log_text("WARNING: unmatched methodindent--");
1659 /* generate the message */
1661 sprintf(logtext, " ");
1662 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1664 pos = strlen(logtext);
1666 for (i = 0; i < methodindent; i++)
1667 logtext[pos++] = '\t';
1669 strcpy(logtext + pos, "finished: ");
1670 utf_cat_classname(logtext, m->class->name);
1671 strcat(logtext, ".");
1672 utf_cat(logtext, m->name);
1673 utf_cat(logtext, m->descriptor);
1675 if (!IS_VOID_TYPE(md->returntype.type)) {
1676 strcat(logtext, "->");
1678 switch (md->returntype.type) {
1695 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1700 /* release memory */
1702 dump_release(dumpsize);
1705 #endif /* !defined(NDEBUG) */
1708 #if defined(ENABLE_CYCLES_STATS)
1709 void builtin_print_cycles_stats(FILE *file)
1711 fprintf(file,"builtin cylce count statistics:\n");
1713 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1714 CYCLES_STATS_PRINT(builtin_new ,file);
1718 #endif /* defined(ENABLE_CYCLES_STATS) */
1721 /*****************************************************************************
1722 MISCELLANEOUS HELPER FUNCTIONS
1723 *****************************************************************************/
1727 /*********** Functions for integer divisions *****************************
1729 On some systems (eg. DEC ALPHA), integer division is not supported by the
1730 CPU. These helper functions implement the missing functionality.
1732 ******************************************************************************/
1734 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1735 s4 builtin_idiv(s4 a, s4 b)
1744 s4 builtin_irem(s4 a, s4 b)
1752 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1755 /* functions for long arithmetics **********************************************
1757 On systems where 64 bit Integers are not supported by the CPU,
1758 these functions are needed.
1760 ******************************************************************************/
1762 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1763 s8 builtin_ladd(s8 a, s8 b)
1776 s8 builtin_lsub(s8 a, s8 b)
1789 s8 builtin_lneg(s8 a)
1801 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1804 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1805 s8 builtin_lmul(s8 a, s8 b)
1817 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1820 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1821 s8 builtin_ldiv(s8 a, s8 b)
1834 s8 builtin_lrem(s8 a, s8 b)
1846 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1849 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1850 s8 builtin_lshl(s8 a, s4 b)
1863 s8 builtin_lshr(s8 a, s4 b)
1876 s8 builtin_lushr(s8 a, s4 b)
1881 c = ((u8) a) >> (b & 63);
1888 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1891 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1892 s8 builtin_land(s8 a, s8 b)
1905 s8 builtin_lor(s8 a, s8 b)
1918 s8 builtin_lxor(s8 a, s8 b)
1930 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1933 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1934 s4 builtin_lcmp(s8 a, s8 b)
1948 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1951 /* functions for unsupported floating instructions ****************************/
1953 /* used to convert FLT_xxx defines into float values */
1955 static inline float intBitsToFloat(s4 i)
1964 /* used to convert DBL_xxx defines into double values */
1966 static inline float longBitsToDouble(s8 l)
1976 float builtin_fadd(float a, float b)
1978 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1979 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1990 if (copysignf(1.0, a) == copysignf(1.0, b))
1993 return intBitsToFloat(FLT_NAN);
1999 float builtin_fsub(float a, float b)
2001 return builtin_fadd(a, builtin_fneg(b));
2005 float builtin_fmul(float a, float b)
2007 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2008 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2010 if (finitef(b)) return a * b;
2012 if (a == 0) return intBitsToFloat(FLT_NAN);
2013 else return copysignf(b, copysignf(1.0, b)*a);
2018 if (b == 0) return intBitsToFloat(FLT_NAN);
2019 else return copysignf(a, copysignf(1.0, a)*b);
2022 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2028 /* builtin_ddiv ****************************************************************
2030 Implementation as described in VM Spec.
2032 *******************************************************************************/
2034 float builtin_fdiv(float a, float b)
2038 /* If neither value1' nor value2' is NaN, the sign of the result */
2039 /* is positive if both values have the same sign, negative if the */
2040 /* values have different signs. */
2046 /* If either value1' or value2' is NaN, the result is NaN. */
2048 return intBitsToFloat(FLT_NAN);
2051 /* Division of a finite value by an infinity results in a */
2052 /* signed zero, with the sign-producing rule just given. */
2054 /* is sign equal? */
2056 if (copysignf(1.0, a) == copysignf(1.0, b))
2065 /* If either value1' or value2' is NaN, the result is NaN. */
2067 return intBitsToFloat(FLT_NAN);
2069 } else if (finitef(b)) {
2070 /* Division of an infinity by a finite value results in a signed */
2071 /* infinity, with the sign-producing rule just given. */
2073 /* is sign equal? */
2075 if (copysignf(1.0, a) == copysignf(1.0, b))
2076 return intBitsToFloat(FLT_POSINF);
2078 return intBitsToFloat(FLT_NEGINF);
2081 /* Division of an infinity by an infinity results in NaN. */
2083 return intBitsToFloat(FLT_NAN);
2089 float builtin_fneg(float a)
2091 if (isnanf(a)) return a;
2093 if (finitef(a)) return -a;
2094 else return copysignf(a, -copysignf(1.0, a));
2097 #endif /* !SUPPORT_FLOAT */
2100 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2101 s4 builtin_fcmpl(float a, float b)
2109 if (!finitef(a) || !finitef(b)) {
2110 a = finitef(a) ? 0 : copysignf(1.0, a);
2111 b = finitef(b) ? 0 : copysignf(1.0, b);
2124 s4 builtin_fcmpg(float a, float b)
2126 if (isnanf(a)) return 1;
2127 if (isnanf(b)) return 1;
2128 if (!finitef(a) || !finitef(b)) {
2129 a = finitef(a) ? 0 : copysignf(1.0, a);
2130 b = finitef(b) ? 0 : copysignf(1.0, b);
2132 if (a > b) return 1;
2133 if (a == b) return 0;
2136 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2139 float builtin_frem(float a, float b)
2145 /* functions for unsupported double instructions ******************************/
2148 double builtin_dadd(double a, double b)
2150 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2151 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2153 if (finite(b)) return a + b;
2157 if (finite(b)) return a;
2159 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2160 else return longBitsToDouble(DBL_NAN);
2166 double builtin_dsub(double a, double b)
2168 return builtin_dadd(a, builtin_dneg(b));
2172 double builtin_dmul(double a, double b)
2174 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2175 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2177 if (finite(b)) return a * b;
2179 if (a == 0) return longBitsToDouble(DBL_NAN);
2180 else return copysign(b, copysign(1.0, b) * a);
2185 if (b == 0) return longBitsToDouble(DBL_NAN);
2186 else return copysign(a, copysign(1.0, a) * b);
2189 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2195 /* builtin_ddiv ****************************************************************
2197 Implementation as described in VM Spec.
2199 *******************************************************************************/
2201 double builtin_ddiv(double a, double b)
2205 /* If neither value1' nor value2' is NaN, the sign of the result */
2206 /* is positive if both values have the same sign, negative if the */
2207 /* values have different signs. */
2213 /* If either value1' or value2' is NaN, the result is NaN. */
2215 return longBitsToDouble(DBL_NAN);
2218 /* Division of a finite value by an infinity results in a */
2219 /* signed zero, with the sign-producing rule just given. */
2221 /* is sign equal? */
2223 if (copysign(1.0, a) == copysign(1.0, b))
2232 /* If either value1' or value2' is NaN, the result is NaN. */
2234 return longBitsToDouble(DBL_NAN);
2236 } else if (finite(b)) {
2237 /* Division of an infinity by a finite value results in a signed */
2238 /* infinity, with the sign-producing rule just given. */
2240 /* is sign equal? */
2242 if (copysign(1.0, a) == copysign(1.0, b))
2243 return longBitsToDouble(DBL_POSINF);
2245 return longBitsToDouble(DBL_NEGINF);
2248 /* Division of an infinity by an infinity results in NaN. */
2250 return longBitsToDouble(DBL_NAN);
2256 /* builtin_dneg ****************************************************************
2258 Implemented as described in VM Spec.
2260 *******************************************************************************/
2262 double builtin_dneg(double a)
2265 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2272 /* If the operand is a zero, the result is the zero of opposite */
2278 /* If the operand is an infinity, the result is the infinity of */
2279 /* opposite sign. */
2281 return copysign(a, -copysign(1.0, a));
2285 #endif /* !SUPPORT_DOUBLE */
2288 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2289 s4 builtin_dcmpl(double a, double b)
2297 if (!finite(a) || !finite(b)) {
2298 a = finite(a) ? 0 : copysign(1.0, a);
2299 b = finite(b) ? 0 : copysign(1.0, b);
2312 s4 builtin_dcmpg(double a, double b)
2320 if (!finite(a) || !finite(b)) {
2321 a = finite(a) ? 0 : copysign(1.0, a);
2322 b = finite(b) ? 0 : copysign(1.0, b);
2333 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2336 double builtin_drem(double a, double b)
2342 /* conversion operations ******************************************************/
2345 s8 builtin_i2l(s4 i)
2357 s4 builtin_l2i(s8 l)
2368 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2369 float builtin_i2f(s4 a)
2371 float f = (float) a;
2374 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2377 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2378 double builtin_i2d(s4 a)
2380 double d = (double) a;
2383 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2386 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2387 float builtin_l2f(s8 a)
2390 float f = (float) a;
2396 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2399 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2400 double builtin_l2d(s8 a)
2403 double d = (double) a;
2409 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2412 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2413 s4 builtin_f2i(float a)
2417 i = builtin_d2i((double) a);
2428 if (a < (-2147483648))
2429 return (-2147483648);
2432 f = copysignf((float) 1.0, a);
2435 return (-2147483648); */
2437 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2440 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2441 s8 builtin_f2l(float a)
2445 l = builtin_d2l((double) a);
2452 if (a > 9223372036854775807L)
2453 return 9223372036854775807L;
2454 if (a < (-9223372036854775808L))
2455 return (-9223372036854775808L);
2460 f = copysignf((float) 1.0, a);
2462 return 9223372036854775807L;
2463 return (-9223372036854775808L); */
2465 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2468 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2469 s4 builtin_d2i(double a)
2474 if (a >= 2147483647)
2476 if (a <= (-2147483647-1))
2477 return (-2147483647-1);
2482 d = copysign(1.0, a);
2485 return (-2147483647-1);
2487 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2490 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2491 s8 builtin_d2l(double a)
2496 if (a >= 9223372036854775807LL)
2497 return 9223372036854775807LL;
2498 if (a <= (-9223372036854775807LL-1))
2499 return (-9223372036854775807LL-1);
2504 d = copysign(1.0, a);
2506 return 9223372036854775807LL;
2507 return (-9223372036854775807LL-1);
2509 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2512 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2513 double builtin_f2d(float a)
2515 if (finitef(a)) return (double) a;
2518 return longBitsToDouble(DBL_NAN);
2520 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2524 float builtin_d2f(double a)
2530 return intBitsToFloat(FLT_NAN);
2532 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2535 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2538 /* builtin_arraycopy ***********************************************************
2540 Builtin for java.lang.System.arraycopy.
2542 ATTENTION: This builtin function returns a boolean value to signal
2543 the ICMD_BUILTIN if there was an exception.
2545 *******************************************************************************/
2547 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2548 java_arrayheader *dest, s4 destStart, s4 len)
2550 arraydescriptor *sdesc;
2551 arraydescriptor *ddesc;
2554 if ((src == NULL) || (dest == NULL)) {
2555 exceptions_throw_nullpointerexception();
2559 sdesc = src->objheader.vftbl->arraydesc;
2560 ddesc = dest->objheader.vftbl->arraydesc;
2562 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2563 exceptions_throw_arraystoreexception();
2567 /* we try to throw exception with the same message as SUN does */
2569 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2570 (srcStart + len < 0) || (srcStart + len > src->size) ||
2571 (destStart + len < 0) || (destStart + len > dest->size)) {
2572 exceptions_throw_arrayindexoutofboundsexception();
2576 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2577 /* We copy primitive values or references of exactly the same type */
2579 s4 dataoffset = sdesc->dataoffset;
2580 s4 componentsize = sdesc->componentsize;
2582 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2583 ((u1 *) src) + dataoffset + componentsize * srcStart,
2584 (size_t) len * componentsize);
2587 /* We copy references of different type */
2589 java_objectarray *oas = (java_objectarray *) src;
2590 java_objectarray *oad = (java_objectarray *) dest;
2592 if (destStart <= srcStart) {
2593 for (i = 0; i < len; i++) {
2594 java_objectheader *o = oas->data[srcStart + i];
2596 if (!builtin_canstore(oad, o))
2599 oad->data[destStart + i] = o;
2603 /* XXX this does not completely obey the specification!
2604 If an exception is thrown only the elements above the
2605 current index have been copied. The specification
2606 requires that only the elements *below* the current
2607 index have been copied before the throw. */
2609 for (i = len - 1; i >= 0; i--) {
2610 java_objectheader *o = oas->data[srcStart + i];
2612 if (!builtin_canstore(oad, o))
2615 oad->data[destStart + i] = o;
2624 /* builtin_nanotime ************************************************************
2626 Return the current time in nanoseconds.
2628 *******************************************************************************/
2630 s8 builtin_nanotime(void)
2635 if (gettimeofday(&tv, NULL) == -1)
2636 vm_abort("gettimeofday failed: %s", strerror(errno));
2638 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2640 return usecs * 1000;
2644 /* builtin_currenttimemillis ***************************************************
2646 Return the current time in milliseconds.
2648 *******************************************************************************/
2650 s8 builtin_currenttimemillis(void)
2654 msecs = builtin_nanotime() / 1000 / 1000;
2660 /* builtin_clone ***************************************************************
2662 Function for cloning objects or arrays.
2664 *******************************************************************************/
2666 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2668 arraydescriptor *ad;
2669 java_arrayheader *ah;
2672 java_objectheader *co; /* cloned object header */
2674 /* get the array descriptor */
2676 ad = o->vftbl->arraydesc;
2678 /* we are cloning an array */
2681 ah = (java_arrayheader *) o;
2683 size = ad->dataoffset + ad->componentsize * ah->size;
2685 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2690 MCOPY(co, o, u1, size);
2692 #if defined(ENABLE_GC_CACAO)
2693 heap_init_objectheader(co, size);
2696 #if defined(ENABLE_THREADS)
2697 lock_init_object_lock(co);
2703 /* we are cloning a non-array */
2705 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2706 exceptions_throw_clonenotsupportedexception();
2710 /* get the class of the object */
2712 c = o->vftbl->class;
2714 /* create new object */
2716 co = builtin_new(c);
2721 MCOPY(co, o, u1, c->instancesize);
2723 #if defined(ENABLE_GC_CACAO)
2724 heap_init_objectheader(co, c->instancesize);
2727 #if defined(ENABLE_THREADS)
2728 lock_init_object_lock(co);
2734 #if defined(ENABLE_VMLOG)
2736 #include <vmlog_cacao.c>
2741 * These are local overrides for various environment variables in Emacs.
2742 * Please do not remove this and leave it at the end of the file, where
2743 * Emacs will automagically detect them.
2744 * ---------------------------------------------------------------------
2747 * indent-tabs-mode: t
2751 * vim:noexpandtab:sw=4:ts=4: