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 8330 2007-08-16 18:15:51Z 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/llni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
62 #include "threads/lock-common.h"
64 #include "toolbox/logging.h"
65 #include "toolbox/util.h"
68 #include "vm/builtin.h"
69 #include "vm/cycles-stats.h"
70 #include "vm/exceptions.h"
71 #include "vm/global.h"
72 #include "vm/initialize.h"
73 #include "vm/primitive.h"
74 #include "vm/stringlocal.h"
76 #include "vm/jit/asmpart.h"
78 #include "vmcore/class.h"
79 #include "vmcore/linker.h"
80 #include "vmcore/loader.h"
81 #include "vmcore/options.h"
82 #include "vmcore/rt-timing.h"
84 #if defined(ENABLE_VMLOG)
85 #include <vmlog_cacao.h>
88 #if defined(ENABLE_DEBUG_FILTER)
89 # include "vm/jit/show.h"
92 /* include builtin tables *****************************************************/
94 #include "vm/builtintable.inc"
97 CYCLES_STATS_DECLARE(builtin_new ,100,5)
98 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
100 /* builtintable_init ***********************************************************
102 Parse the descriptors of builtin functions and create the parsed
105 *******************************************************************************/
107 static bool builtintable_init(void)
109 descriptor_pool *descpool;
111 builtintable_entry *bte;
113 /* mark start of dump memory area */
115 dumpsize = dump_size();
117 /* create a new descriptor pool */
119 descpool = descriptor_pool_new(class_java_lang_Object);
121 /* add some entries we need */
123 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
126 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
129 /* first add all descriptors to the pool */
131 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
132 /* create a utf8 string from descriptor */
134 bte->descriptor = utf_new_char(bte->cdescriptor);
136 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
137 /* release dump area */
139 dump_release(dumpsize);
145 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
146 bte->descriptor = utf_new_char(bte->cdescriptor);
148 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
149 dump_release(dumpsize);
154 for (bte = builtintable_function; bte->fp != NULL; bte++) {
155 bte->classname = utf_new_char(bte->cclassname);
156 bte->name = utf_new_char(bte->cname);
157 bte->descriptor = utf_new_char(bte->cdescriptor);
159 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
160 dump_release(dumpsize);
165 /* create the class reference table */
167 (void) descriptor_pool_create_classrefs(descpool, NULL);
169 /* allocate space for the parsed descriptors */
171 descriptor_pool_alloc_parsed_descriptors(descpool);
173 /* Now parse all descriptors. NOTE: builtin-functions are treated
174 like static methods (no `this' pointer). */
176 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
178 descriptor_pool_parse_method_descriptor(descpool,
180 ACC_STATIC | ACC_METHOD_BUILTIN,
184 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
186 descriptor_pool_parse_method_descriptor(descpool,
188 ACC_STATIC | ACC_METHOD_BUILTIN,
192 for (bte = builtintable_function; bte->fp != NULL; bte++) {
194 descriptor_pool_parse_method_descriptor(descpool,
196 ACC_STATIC | ACC_METHOD_BUILTIN,
200 /* release dump area */
202 dump_release(dumpsize);
208 /* builtintable_comparator *****************************************************
210 qsort comparator for the automatic builtin table.
212 *******************************************************************************/
214 static int builtintable_comparator(const void *a, const void *b)
216 builtintable_entry *bte1;
217 builtintable_entry *bte2;
219 bte1 = (builtintable_entry *) a;
220 bte2 = (builtintable_entry *) b;
222 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
226 /* builtintable_sort_automatic *************************************************
228 Sorts the automatic builtin table.
230 *******************************************************************************/
232 static void builtintable_sort_automatic(void)
236 /* calculate table size statically (`- 1' comment see builtintable.inc) */
238 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
240 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
241 builtintable_comparator);
245 /* builtin_init ****************************************************************
247 Initialize the global table of builtin functions.
249 *******************************************************************************/
251 bool builtin_init(void)
253 /* initialize the builtin tables */
255 if (!builtintable_init())
258 /* sort builtin tables */
260 builtintable_sort_automatic();
266 /* builtintable_get_internal ***************************************************
268 Finds an entry in the builtintable for internal functions and
269 returns the a pointer to the structure.
271 *******************************************************************************/
273 builtintable_entry *builtintable_get_internal(functionptr fp)
275 builtintable_entry *bte;
277 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
286 /* builtintable_get_automatic **************************************************
288 Finds an entry in the builtintable for functions which are replaced
289 automatically and returns the a pointer to the structure.
291 *******************************************************************************/
293 builtintable_entry *builtintable_get_automatic(s4 opcode)
295 builtintable_entry *first;
296 builtintable_entry *last;
297 builtintable_entry *middle;
301 /* calculate table size statically (`- 1' comment see builtintable.inc) */
303 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
305 first = builtintable_automatic;
306 last = builtintable_automatic + entries;
308 while (entries > 0) {
310 middle = first + half;
312 if (middle->opcode < opcode) {
319 return (first != last ? first : NULL);
323 /* builtintable_replace_function ***********************************************
327 *******************************************************************************/
329 #if defined(ENABLE_JIT)
330 bool builtintable_replace_function(void *iptr_)
333 builtintable_entry *bte;
336 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
338 /* get name and descriptor of the function */
341 case ICMD_INVOKESTATIC:
342 /* The instruction MUST be resolved, otherwise we run into
343 lazy loading troubles. Anyway, we should/can only replace
344 very VM-close functions. */
346 if (INSTRUCTION_IS_UNRESOLVED(iptr))
349 mr = iptr->sx.s23.s3.fmiref;
356 /* search the function table */
358 for (bte = builtintable_function; bte->fp != NULL; bte++) {
359 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
360 (mr->name == bte->name) &&
361 (mr->descriptor == bte->descriptor)) {
363 /* set the values in the instruction */
365 iptr->opc = bte->opcode;
366 iptr->sx.s23.s3.bte = bte;
367 if (bte->checkexception)
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_handle_t *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_handle_t *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_handle_t *o, classinfo *targetclass)
485 arraydescriptor *desc;
490 desc = o->vftbl->arraydesc;
495 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
499 s4 builtin_arrayinstanceof(java_handle_t *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_handle_t *xptr)
518 java_lang_Throwable *t;
525 t = (java_lang_Throwable *) xptr;
527 /* get detail message */
529 LLNI_field_get_ref(t, detailMessage, s);
531 /* calculate message length */
533 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
537 utf_bytes(xptr->vftbl->class->name);
539 logtextlen += strlen(": ") +
540 u2_utflength(LLNI_field_direct(s, value)->data
541 + LLNI_field_direct(s, offset),
542 LLNI_field_direct(s,count));
546 logtextlen += strlen("(nil)");
549 /* allocate memory */
551 dumpsize = dump_size();
553 logtext = DMNEW(char, logtextlen);
555 strcpy(logtext, "Builtin exception thrown: ");
558 utf_cat_classname(logtext, xptr->vftbl->class->name);
563 buf = javastring_tochar((java_handle_t *) s);
564 strcat(logtext, ": ");
565 strcat(logtext, buf);
566 MFREE(buf, char, strlen(buf) + 1);
570 strcat(logtext, "(nil)");
577 dump_release(dumpsize);
579 #endif /* !defined(NDEBUG) */
581 /* actually set the exception */
583 exceptions_set_exception(xptr);
585 /* Return a NULL pointer. This is required for vm_call_method to
586 check for an exception. This is for convenience. */
592 /* builtin_canstore ************************************************************
594 Checks, if an object can be stored in an array.
596 Return value: 1 ... possible
597 0 ... otherwise (throws an ArrayStoreException)
599 *******************************************************************************/
601 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
603 arraydescriptor *desc;
604 arraydescriptor *valuedesc;
605 vftbl_t *componentvftbl;
614 /* The following is guaranteed (by verifier checks):
616 * *) oa->...vftbl->arraydesc != NULL
617 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
618 * *) o->vftbl is not an interface vftbl
621 desc = oa->header.objheader.vftbl->arraydesc;
622 componentvftbl = desc->componentvftbl;
623 valuevftbl = o->vftbl;
624 valuedesc = valuevftbl->arraydesc;
626 if ((desc->dimension - 1) == 0) {
627 /* {oa is a one-dimensional array} */
628 /* {oa is an array of references} */
630 if (valuevftbl == componentvftbl)
633 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
635 baseval = componentvftbl->baseval;
638 /* an array of interface references */
640 result = ((valuevftbl->interfacetablelength > -baseval) &&
641 (valuevftbl->interfacetable[baseval] != NULL));
644 diffval = valuevftbl->baseval - componentvftbl->baseval;
645 result = diffval <= (uint32_t) componentvftbl->diffval;
648 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
650 else if (valuedesc == NULL) {
651 /* {oa has dimension > 1} */
652 /* {componentvftbl->arraydesc != NULL} */
654 /* check if o is an array */
659 /* {o is an array} */
661 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
664 /* if not possible, throw an exception */
667 exceptions_throw_arraystoreexception();
675 /* This is an optimized version where a is guaranteed to be one-dimensional */
676 s4 builtin_canstore_onedim (java_handle_objectarray_t *a, java_handle_t *o)
678 arraydescriptor *desc;
679 vftbl_t *elementvftbl;
688 /* The following is guaranteed (by verifier checks):
690 * *) a->...vftbl->arraydesc != NULL
691 * *) a->...vftbl->arraydesc->elementvftbl != NULL
692 * *) a->...vftbl->arraydesc->dimension == 1
693 * *) o->vftbl is not an interface vftbl
696 desc = a->header.objheader.vftbl->arraydesc;
697 elementvftbl = desc->elementvftbl;
698 valuevftbl = o->vftbl;
700 /* {a is a one-dimensional array} */
702 if (valuevftbl == elementvftbl)
705 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
707 baseval = elementvftbl->baseval;
710 /* an array of interface references */
711 result = ((valuevftbl->interfacetablelength > -baseval) &&
712 (valuevftbl->interfacetable[baseval] != NULL));
715 diffval = valuevftbl->baseval - elementvftbl->baseval;
716 result = diffval <= (uint32_t) elementvftbl->diffval;
719 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
725 /* This is an optimized version where a is guaranteed to be a
726 * one-dimensional array of a class type */
727 s4 builtin_canstore_onedim_class(java_handle_objectarray_t *a, java_handle_t *o)
729 vftbl_t *elementvftbl;
737 /* The following is guaranteed (by verifier checks):
739 * *) a->...vftbl->arraydesc != NULL
740 * *) a->...vftbl->arraydesc->elementvftbl != NULL
741 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
742 * *) a->...vftbl->arraydesc->dimension == 1
743 * *) o->vftbl is not an interface vftbl
746 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
747 valuevftbl = o->vftbl;
749 /* {a is a one-dimensional array} */
751 if (valuevftbl == elementvftbl)
754 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
756 diffval = valuevftbl->baseval - elementvftbl->baseval;
757 result = diffval <= (uint32_t) elementvftbl->diffval;
759 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
765 /* builtin_new *****************************************************************
767 Creates a new instance of class c on the heap.
769 Return value: pointer to the object or NULL if no memory is
772 *******************************************************************************/
774 java_handle_t *builtin_new(classinfo *c)
777 #if defined(ENABLE_RT_TIMING)
778 struct timespec time_start, time_end;
780 #if defined(ENABLE_CYCLES_STATS)
781 u8 cycles_start, cycles_end;
784 RT_TIMING_GET_TIME(time_start);
785 CYCLES_STATS_GET(cycles_start);
787 /* is the class loaded */
789 assert(c->state & CLASS_LOADED);
791 /* check if we can instantiate this class */
793 if (c->flags & ACC_ABSTRACT) {
794 exceptions_throw_instantiationerror(c);
798 /* is the class linked */
800 if (!(c->state & CLASS_LINKED))
804 if (!(c->state & CLASS_INITIALIZED)) {
807 log_message_class("Initialize class (from builtin_new): ", c);
810 if (!initialize_class(c))
814 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
822 #if defined(ENABLE_THREADS)
823 lock_init_object_lock(o);
826 CYCLES_STATS_GET(cycles_end);
827 RT_TIMING_GET_TIME(time_end);
829 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
830 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
836 /* builtin_newarray ************************************************************
838 Creates an array with the given vftbl on the heap. This function
839 takes as class argument an array class.
841 Return value: pointer to the array or NULL if no memory is available
843 *******************************************************************************/
845 java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
847 arraydescriptor *desc;
852 #if defined(ENABLE_RT_TIMING)
853 struct timespec time_start, time_end;
856 RT_TIMING_GET_TIME(time_start);
858 desc = arrayclass->vftbl->arraydesc;
859 dataoffset = desc->dataoffset;
860 componentsize = desc->componentsize;
863 exceptions_throw_negativearraysizeexception();
867 actualsize = dataoffset + size * componentsize;
869 /* check for overflow */
871 if (((u4) actualsize) < ((u4) size)) {
872 exceptions_throw_outofmemoryerror();
876 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
881 a->objheader.vftbl = arrayclass->vftbl;
883 #if defined(ENABLE_THREADS)
884 lock_init_object_lock(&a->objheader);
887 LLNI_array_size(a) = size;
889 RT_TIMING_GET_TIME(time_end);
890 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
896 /* builtin_anewarray ***********************************************************
898 Creates an array of references to the given class type on the heap.
900 Return value: pointer to the array or NULL if no memory is
903 *******************************************************************************/
905 java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
907 classinfo *arrayclass;
909 /* is class loaded */
911 assert(componentclass->state & CLASS_LOADED);
913 /* is class linked */
915 if (!(componentclass->state & CLASS_LINKED))
916 if (!link_class(componentclass))
919 arrayclass = class_array_of(componentclass, true);
924 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
928 /* builtin_newarray_boolean ****************************************************
930 Creates an array of bytes on the heap. The array is designated as
931 an array of booleans (important for casts)
933 Return value: pointer to the array or NULL if no memory is
936 *******************************************************************************/
938 java_handle_booleanarray_t *builtin_newarray_boolean(s4 size)
940 return (java_handle_booleanarray_t *)
941 builtin_newarray(size,
942 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
946 /* builtin_newarray_byte *******************************************************
948 Creates an array of 8 bit Integers on the heap.
950 Return value: pointer to the array or NULL if no memory is
953 *******************************************************************************/
955 java_handle_bytearray_t *builtin_newarray_byte(s4 size)
957 return (java_handle_bytearray_t *)
958 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
962 /* builtin_newarray_char *******************************************************
964 Creates an array of characters on the heap.
966 Return value: pointer to the array or NULL if no memory is
969 *******************************************************************************/
971 java_handle_chararray_t *builtin_newarray_char(s4 size)
973 return (java_handle_chararray_t *)
974 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
978 /* builtin_newarray_short ******************************************************
980 Creates an array of 16 bit Integers on the heap.
982 Return value: pointer to the array or NULL if no memory is
985 *******************************************************************************/
987 java_handle_shortarray_t *builtin_newarray_short(s4 size)
989 return (java_handle_shortarray_t *)
990 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
994 /* builtin_newarray_int ********************************************************
996 Creates an array of 32 bit Integers on the heap.
998 Return value: pointer to the array or NULL if no memory is
1001 *******************************************************************************/
1003 java_handle_intarray_t *builtin_newarray_int(s4 size)
1005 return (java_handle_intarray_t *)
1006 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1010 /* builtin_newarray_long *******************************************************
1012 Creates an array of 64 bit Integers on the heap.
1014 Return value: pointer to the array or NULL if no memory is
1017 *******************************************************************************/
1019 java_handle_longarray_t *builtin_newarray_long(s4 size)
1021 return (java_handle_longarray_t *)
1022 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1026 /* builtin_newarray_float ******************************************************
1028 Creates an array of 32 bit IEEE floats on the heap.
1030 Return value: pointer to the array or NULL if no memory is
1033 *******************************************************************************/
1035 java_handle_floatarray_t *builtin_newarray_float(s4 size)
1037 return (java_handle_floatarray_t *)
1038 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1042 /* builtin_newarray_double *****************************************************
1044 Creates an array of 64 bit IEEE floats on the heap.
1046 Return value: pointer to the array or NULL if no memory is
1049 *******************************************************************************/
1051 java_handle_doublearray_t *builtin_newarray_double(s4 size)
1053 return (java_handle_doublearray_t *)
1054 builtin_newarray(size,
1055 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1059 /* builtin_multianewarray_intern ***********************************************
1061 Creates a multi-dimensional array on the heap. The dimensions are
1062 passed in an array of longs.
1065 n.............number of dimensions to create
1066 arrayclass....the array class
1067 dims..........array containing the size of each dimension to create
1069 Return value: pointer to the array or NULL if no memory is
1072 ******************************************************************************/
1074 static java_handle_t *builtin_multianewarray_intern(int n,
1075 classinfo *arrayclass,
1080 classinfo *componentclass;
1083 /* create this dimension */
1085 size = (s4) dims[0];
1086 a = builtin_newarray(size, arrayclass);
1091 /* if this is the last dimension return */
1096 /* get the class of the components to create */
1098 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1100 /* The verifier guarantees that the dimension count is in the range. */
1102 /* create the component arrays */
1104 for (i = 0; i < size; i++) {
1106 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1107 /* we save an s4 to a s8 slot, 8-byte aligned */
1109 builtin_multianewarray_intern(n, componentclass, dims + 2);
1111 builtin_multianewarray_intern(n, componentclass, dims + 1);
1117 ((java_handle_objectarray_t *) a)->data[i] = (java_object_t *) ea;
1124 /* builtin_multianewarray ******************************************************
1126 Wrapper for builtin_multianewarray_intern which checks all
1127 dimensions before we start allocating.
1129 ******************************************************************************/
1131 java_handle_objectarray_t *builtin_multianewarray(int n, classinfo *arrayclass,
1137 /* check all dimensions before doing anything */
1139 for (i = 0; i < n; i++) {
1140 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1141 /* we save an s4 to a s8 slot, 8-byte aligned */
1142 size = (s4) dims[i * 2];
1144 size = (s4) dims[i];
1148 exceptions_throw_negativearraysizeexception();
1153 /* now call the real function */
1155 return builtin_multianewarray_intern(n, arrayclass, dims);
1159 /*****************************************************************************
1162 Various functions for printing a message at method entry or exit (for
1165 *****************************************************************************/
1167 #if !defined(NDEBUG)
1168 static s4 methodindent = 0;
1169 static u4 callcount = 0;
1171 java_handle_t *builtin_trace_exception(java_handle_t *xptr,
1181 #if defined(ENABLE_DEBUG_FILTER)
1182 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1185 #if defined(ENABLE_VMLOG)
1189 if (opt_verbosecall && indent)
1192 /* calculate message length */
1196 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1199 logtextlen = strlen("Some Throwable");
1202 logtextlen += strlen(" thrown in ");
1206 utf_bytes(m->class->name) +
1208 utf_bytes(m->name) +
1209 utf_bytes(m->descriptor) +
1210 strlen("(NOSYNC,NATIVE");
1212 #if SIZEOF_VOID_P == 8
1214 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1216 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1219 if (m->class->sourcefile == NULL)
1220 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1222 logtextlen += utf_bytes(m->class->sourcefile);
1224 logtextlen += strlen(":65536)");
1228 logtextlen += strlen("call_java_method");
1231 logtextlen += strlen("0");
1233 /* allocate memory */
1235 dumpsize = dump_size();
1237 logtext = DMNEW(char, logtextlen);
1240 strcpy(logtext, "Exception ");
1241 utf_cat_classname(logtext, xptr->vftbl->class->name);
1244 strcpy(logtext, "Some Throwable");
1247 strcat(logtext, " thrown in ");
1250 utf_cat_classname(logtext, m->class->name);
1251 strcat(logtext, ".");
1252 utf_cat(logtext, m->name);
1253 utf_cat(logtext, m->descriptor);
1255 if (m->flags & ACC_SYNCHRONIZED)
1256 strcat(logtext, "(SYNC");
1258 strcat(logtext, "(NOSYNC");
1260 if (m->flags & ACC_NATIVE) {
1261 strcat(logtext, ",NATIVE");
1265 #if SIZEOF_VOID_P == 8
1266 sprintf(logtext + strlen(logtext),
1267 ")(0x%016lx) at position 0x%016lx",
1268 (ptrint) code->entrypoint, (ptrint) pos);
1270 sprintf(logtext + strlen(logtext),
1271 ")(0x%08x) at position 0x%08x",
1272 (ptrint) code->entrypoint, (ptrint) pos);
1277 /* XXX preliminary: This should get the actual codeinfo */
1278 /* in which the exception happened. */
1281 #if SIZEOF_VOID_P == 8
1282 sprintf(logtext + strlen(logtext),
1283 ")(0x%016lx) at position 0x%016lx (",
1284 (ptrint) code->entrypoint, (ptrint) pos);
1286 sprintf(logtext + strlen(logtext),
1287 ")(0x%08x) at position 0x%08x (",
1288 (ptrint) code->entrypoint, (ptrint) pos);
1291 if (m->class->sourcefile == NULL)
1292 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1294 utf_cat(logtext, m->class->sourcefile);
1296 sprintf(logtext + strlen(logtext), ":%d)", 0);
1300 strcat(logtext, "call_java_method");
1304 /* release memory */
1306 dump_release(dumpsize);
1310 #endif /* !defined(NDEBUG) */
1313 /* builtin_print_argument ******************************************************
1315 Prints arguments and return values for the call trace.
1317 *******************************************************************************/
1319 #if !defined(NDEBUG)
1320 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1321 typedesc *paramtype, s8 value)
1329 switch (paramtype->type) {
1332 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1337 #if SIZEOF_VOID_P == 4
1338 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1340 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1345 #if defined(__S390__)
1347 /* The below won't work on S390 */
1351 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1356 #if SIZEOF_VOID_P == 4
1357 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1359 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1364 #if SIZEOF_VOID_P == 4
1365 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1367 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1370 /* cast to java.lang.Object */
1372 o = (java_handle_t *) (ptrint) value;
1374 /* check return argument for java.lang.Class or java.lang.String */
1377 if (o->vftbl->class == class_java_lang_String) {
1378 /* get java.lang.String object and the length of the
1381 u = javastring_toutf(o, false);
1383 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1385 /* realloc memory for string length */
1387 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1390 /* convert to utf8 string and strcat it to the logtext */
1392 strcat(logtext, " (String = \"");
1393 utf_cat(logtext, u);
1394 strcat(logtext, "\")");
1397 if (o->vftbl->class == class_java_lang_Class) {
1398 /* if the object returned is a java.lang.Class
1399 cast it to classinfo structure and get the name
1402 c = (classinfo *) o;
1407 /* if the object returned is not a java.lang.String or
1408 a java.lang.Class just print the name of the class */
1410 u = o->vftbl->class->name;
1413 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1415 /* realloc memory for string length */
1417 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1420 /* strcat to the logtext */
1422 strcat(logtext, " (Class = \"");
1423 utf_cat_classname(logtext, u);
1424 strcat(logtext, "\")");
1431 #endif /* !defined(NDEBUG) */
1433 /* builtin_verbosecall_enter ***************************************************
1435 Print method call with arguments for -verbose:call.
1437 *******************************************************************************/
1439 #if !defined(NDEBUG)
1441 #ifdef TRACE_ARGS_NUM
1442 void builtin_verbosecall_enter(s8 a0, s8 a1,
1443 # if TRACE_ARGS_NUM >= 4
1446 # if TRACE_ARGS_NUM >= 6
1449 # if TRACE_ARGS_NUM == 8
1461 #if defined(ENABLE_DEBUG_FILTER)
1462 if (! show_filters_test_verbosecall_enter(m)) return;
1465 #if defined(ENABLE_VMLOG)
1466 vmlog_cacao_enter_method(m);
1472 /* calculate message length */
1475 strlen("4294967295 ") +
1476 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1478 strlen("called: ") +
1479 utf_bytes(m->class->name) +
1481 utf_bytes(m->name) +
1482 utf_bytes(m->descriptor);
1484 /* Actually it's not possible to have all flags printed, but:
1489 strlen(" PRIVATE") +
1490 strlen(" PROTECTED") +
1493 strlen(" SYNCHRONIZED") +
1494 strlen(" VOLATILE") +
1495 strlen(" TRANSIENT") +
1497 strlen(" INTERFACE") +
1498 strlen(" ABSTRACT");
1500 /* add maximal argument length */
1504 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1505 strlen("...(255)") +
1508 /* allocate memory */
1510 dumpsize = dump_size();
1512 logtext = DMNEW(char, logtextlen);
1516 sprintf(logtext, "%10d ", callcount);
1517 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1519 pos = strlen(logtext);
1521 for (i = 0; i < methodindent; i++)
1522 logtext[pos++] = '\t';
1524 strcpy(logtext + pos, "called: ");
1526 utf_cat_classname(logtext, m->class->name);
1527 strcat(logtext, ".");
1528 utf_cat(logtext, m->name);
1529 utf_cat(logtext, m->descriptor);
1531 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1532 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1533 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1534 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1535 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1536 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1537 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1538 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1539 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1540 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1541 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1543 strcat(logtext, "(");
1545 if (md->paramcount >= 1) {
1546 logtext = builtin_print_argument(logtext, &logtextlen,
1547 &md->paramtypes[0], a0);
1550 if (md->paramcount >= 2) {
1551 strcat(logtext, ", ");
1553 logtext = builtin_print_argument(logtext, &logtextlen,
1554 &md->paramtypes[1], a1);
1557 #if TRACE_ARGS_NUM >= 4
1558 if (md->paramcount >= 3) {
1559 strcat(logtext, ", ");
1561 logtext = builtin_print_argument(logtext, &logtextlen,
1562 &md->paramtypes[2], a2);
1565 if (md->paramcount >= 4) {
1566 strcat(logtext, ", ");
1568 logtext = builtin_print_argument(logtext, &logtextlen,
1569 &md->paramtypes[3], a3);
1573 #if TRACE_ARGS_NUM >= 6
1574 if (md->paramcount >= 5) {
1575 strcat(logtext, ", ");
1577 logtext = builtin_print_argument(logtext, &logtextlen,
1578 &md->paramtypes[4], a4);
1581 if (md->paramcount >= 6) {
1582 strcat(logtext, ", ");
1584 logtext = builtin_print_argument(logtext, &logtextlen,
1585 &md->paramtypes[5], a5);
1589 #if TRACE_ARGS_NUM == 8
1590 if (md->paramcount >= 7) {
1591 strcat(logtext, ", ");
1593 logtext = builtin_print_argument(logtext, &logtextlen,
1594 &md->paramtypes[6], a6);
1597 if (md->paramcount >= 8) {
1598 strcat(logtext, ", ");
1600 logtext = builtin_print_argument(logtext, &logtextlen,
1601 &md->paramtypes[7], a7);
1605 if (md->paramcount > 8) {
1606 sprintf(logtext + strlen(logtext), ", ...(%d)",
1607 md->paramcount - TRACE_ARGS_NUM);
1610 strcat(logtext, ")");
1614 /* release memory */
1616 dump_release(dumpsize);
1622 #endif /* !defined(NDEBUG) */
1625 /* builtin_verbosecall_exit ****************************************************
1627 Print method exit for -verbose:call.
1629 *******************************************************************************/
1631 #if !defined(NDEBUG)
1632 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1642 #if defined(ENABLE_DEBUG_FILTER)
1643 if (! show_filters_test_verbosecall_exit(m)) return;
1646 #if defined(ENABLE_VMLOG)
1647 vmlog_cacao_leave_method(m);
1653 /* calculate message length */
1656 strlen("4294967295 ") +
1657 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1659 strlen("finished: ") +
1660 utf_bytes(m->class->name) +
1662 utf_bytes(m->name) +
1663 utf_bytes(m->descriptor) +
1664 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1666 /* add maximal argument length */
1668 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1670 /* allocate memory */
1672 dumpsize = dump_size();
1674 logtext = DMNEW(char, logtextlen);
1676 /* outdent the log message */
1681 log_text("WARNING: unmatched methodindent--");
1683 /* generate the message */
1685 sprintf(logtext, " ");
1686 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1688 pos = strlen(logtext);
1690 for (i = 0; i < methodindent; i++)
1691 logtext[pos++] = '\t';
1693 strcpy(logtext + pos, "finished: ");
1694 utf_cat_classname(logtext, m->class->name);
1695 strcat(logtext, ".");
1696 utf_cat(logtext, m->name);
1697 utf_cat(logtext, m->descriptor);
1699 if (!IS_VOID_TYPE(md->returntype.type)) {
1700 strcat(logtext, "->");
1702 switch (md->returntype.type) {
1719 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1724 /* release memory */
1726 dump_release(dumpsize);
1729 #endif /* !defined(NDEBUG) */
1732 #if defined(ENABLE_CYCLES_STATS)
1733 void builtin_print_cycles_stats(FILE *file)
1735 fprintf(file,"builtin cylce count statistics:\n");
1737 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1738 CYCLES_STATS_PRINT(builtin_new ,file);
1742 #endif /* defined(ENABLE_CYCLES_STATS) */
1745 /*****************************************************************************
1746 MISCELLANEOUS HELPER FUNCTIONS
1747 *****************************************************************************/
1751 /*********** Functions for integer divisions *****************************
1753 On some systems (eg. DEC ALPHA), integer division is not supported by the
1754 CPU. These helper functions implement the missing functionality.
1756 ******************************************************************************/
1758 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1759 s4 builtin_idiv(s4 a, s4 b)
1768 s4 builtin_irem(s4 a, s4 b)
1776 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1779 /* functions for long arithmetics **********************************************
1781 On systems where 64 bit Integers are not supported by the CPU,
1782 these functions are needed.
1784 ******************************************************************************/
1786 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1787 s8 builtin_ladd(s8 a, s8 b)
1800 s8 builtin_lsub(s8 a, s8 b)
1813 s8 builtin_lneg(s8 a)
1825 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1828 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1829 s8 builtin_lmul(s8 a, s8 b)
1841 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1844 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1845 s8 builtin_ldiv(s8 a, s8 b)
1858 s8 builtin_lrem(s8 a, s8 b)
1870 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1873 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1874 s8 builtin_lshl(s8 a, s4 b)
1887 s8 builtin_lshr(s8 a, s4 b)
1900 s8 builtin_lushr(s8 a, s4 b)
1905 c = ((u8) a) >> (b & 63);
1912 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1915 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1916 s8 builtin_land(s8 a, s8 b)
1929 s8 builtin_lor(s8 a, s8 b)
1942 s8 builtin_lxor(s8 a, s8 b)
1954 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1957 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1958 s4 builtin_lcmp(s8 a, s8 b)
1972 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1975 /* functions for unsupported floating instructions ****************************/
1977 /* used to convert FLT_xxx defines into float values */
1979 static inline float intBitsToFloat(s4 i)
1988 /* used to convert DBL_xxx defines into double values */
1990 static inline float longBitsToDouble(s8 l)
2000 float builtin_fadd(float a, float b)
2002 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2003 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2014 if (copysignf(1.0, a) == copysignf(1.0, b))
2017 return intBitsToFloat(FLT_NAN);
2023 float builtin_fsub(float a, float b)
2025 return builtin_fadd(a, builtin_fneg(b));
2029 float builtin_fmul(float a, float b)
2031 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2032 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2034 if (finitef(b)) return a * b;
2036 if (a == 0) return intBitsToFloat(FLT_NAN);
2037 else return copysignf(b, copysignf(1.0, b)*a);
2042 if (b == 0) return intBitsToFloat(FLT_NAN);
2043 else return copysignf(a, copysignf(1.0, a)*b);
2046 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2052 /* builtin_ddiv ****************************************************************
2054 Implementation as described in VM Spec.
2056 *******************************************************************************/
2058 float builtin_fdiv(float a, float b)
2062 /* If neither value1' nor value2' is NaN, the sign of the result */
2063 /* is positive if both values have the same sign, negative if the */
2064 /* values have different signs. */
2070 /* If either value1' or value2' is NaN, the result is NaN. */
2072 return intBitsToFloat(FLT_NAN);
2075 /* Division of a finite value by an infinity results in a */
2076 /* signed zero, with the sign-producing rule just given. */
2078 /* is sign equal? */
2080 if (copysignf(1.0, a) == copysignf(1.0, b))
2089 /* If either value1' or value2' is NaN, the result is NaN. */
2091 return intBitsToFloat(FLT_NAN);
2093 } else if (finitef(b)) {
2094 /* Division of an infinity by a finite value results in a signed */
2095 /* infinity, with the sign-producing rule just given. */
2097 /* is sign equal? */
2099 if (copysignf(1.0, a) == copysignf(1.0, b))
2100 return intBitsToFloat(FLT_POSINF);
2102 return intBitsToFloat(FLT_NEGINF);
2105 /* Division of an infinity by an infinity results in NaN. */
2107 return intBitsToFloat(FLT_NAN);
2113 float builtin_fneg(float a)
2115 if (isnanf(a)) return a;
2117 if (finitef(a)) return -a;
2118 else return copysignf(a, -copysignf(1.0, a));
2121 #endif /* !SUPPORT_FLOAT */
2124 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2125 s4 builtin_fcmpl(float a, float b)
2133 if (!finitef(a) || !finitef(b)) {
2134 a = finitef(a) ? 0 : copysignf(1.0, a);
2135 b = finitef(b) ? 0 : copysignf(1.0, b);
2148 s4 builtin_fcmpg(float a, float b)
2150 if (isnanf(a)) return 1;
2151 if (isnanf(b)) return 1;
2152 if (!finitef(a) || !finitef(b)) {
2153 a = finitef(a) ? 0 : copysignf(1.0, a);
2154 b = finitef(b) ? 0 : copysignf(1.0, b);
2156 if (a > b) return 1;
2157 if (a == b) return 0;
2160 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2163 float builtin_frem(float a, float b)
2169 /* functions for unsupported double instructions ******************************/
2172 double builtin_dadd(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;
2181 if (finite(b)) return a;
2183 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2184 else return longBitsToDouble(DBL_NAN);
2190 double builtin_dsub(double a, double b)
2192 return builtin_dadd(a, builtin_dneg(b));
2196 double builtin_dmul(double a, double b)
2198 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2199 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2201 if (finite(b)) return a * b;
2203 if (a == 0) return longBitsToDouble(DBL_NAN);
2204 else return copysign(b, copysign(1.0, b) * a);
2209 if (b == 0) return longBitsToDouble(DBL_NAN);
2210 else return copysign(a, copysign(1.0, a) * b);
2213 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2219 /* builtin_ddiv ****************************************************************
2221 Implementation as described in VM Spec.
2223 *******************************************************************************/
2225 double builtin_ddiv(double a, double b)
2229 /* If neither value1' nor value2' is NaN, the sign of the result */
2230 /* is positive if both values have the same sign, negative if the */
2231 /* values have different signs. */
2237 /* If either value1' or value2' is NaN, the result is NaN. */
2239 return longBitsToDouble(DBL_NAN);
2242 /* Division of a finite value by an infinity results in a */
2243 /* signed zero, with the sign-producing rule just given. */
2245 /* is sign equal? */
2247 if (copysign(1.0, a) == copysign(1.0, b))
2256 /* If either value1' or value2' is NaN, the result is NaN. */
2258 return longBitsToDouble(DBL_NAN);
2260 } else if (finite(b)) {
2261 /* Division of an infinity by a finite value results in a signed */
2262 /* infinity, with the sign-producing rule just given. */
2264 /* is sign equal? */
2266 if (copysign(1.0, a) == copysign(1.0, b))
2267 return longBitsToDouble(DBL_POSINF);
2269 return longBitsToDouble(DBL_NEGINF);
2272 /* Division of an infinity by an infinity results in NaN. */
2274 return longBitsToDouble(DBL_NAN);
2280 /* builtin_dneg ****************************************************************
2282 Implemented as described in VM Spec.
2284 *******************************************************************************/
2286 double builtin_dneg(double a)
2289 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2296 /* If the operand is a zero, the result is the zero of opposite */
2302 /* If the operand is an infinity, the result is the infinity of */
2303 /* opposite sign. */
2305 return copysign(a, -copysign(1.0, a));
2309 #endif /* !SUPPORT_DOUBLE */
2312 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2313 s4 builtin_dcmpl(double a, double b)
2321 if (!finite(a) || !finite(b)) {
2322 a = finite(a) ? 0 : copysign(1.0, a);
2323 b = finite(b) ? 0 : copysign(1.0, b);
2336 s4 builtin_dcmpg(double a, double b)
2344 if (!finite(a) || !finite(b)) {
2345 a = finite(a) ? 0 : copysign(1.0, a);
2346 b = finite(b) ? 0 : copysign(1.0, b);
2357 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2360 double builtin_drem(double a, double b)
2366 /* conversion operations ******************************************************/
2369 s8 builtin_i2l(s4 i)
2381 s4 builtin_l2i(s8 l)
2392 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2393 float builtin_i2f(s4 a)
2395 float f = (float) a;
2398 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2401 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2402 double builtin_i2d(s4 a)
2404 double d = (double) a;
2407 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2410 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2411 float builtin_l2f(s8 a)
2414 float f = (float) a;
2420 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2423 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2424 double builtin_l2d(s8 a)
2427 double d = (double) a;
2433 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2436 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2437 s4 builtin_f2i(float a)
2441 i = builtin_d2i((double) a);
2452 if (a < (-2147483648))
2453 return (-2147483648);
2456 f = copysignf((float) 1.0, a);
2459 return (-2147483648); */
2461 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2464 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2465 s8 builtin_f2l(float a)
2469 l = builtin_d2l((double) a);
2476 if (a > 9223372036854775807L)
2477 return 9223372036854775807L;
2478 if (a < (-9223372036854775808L))
2479 return (-9223372036854775808L);
2484 f = copysignf((float) 1.0, a);
2486 return 9223372036854775807L;
2487 return (-9223372036854775808L); */
2489 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2492 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2493 s4 builtin_d2i(double a)
2498 if (a >= 2147483647)
2500 if (a <= (-2147483647-1))
2501 return (-2147483647-1);
2506 d = copysign(1.0, a);
2509 return (-2147483647-1);
2511 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2514 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2515 s8 builtin_d2l(double a)
2520 if (a >= 9223372036854775807LL)
2521 return 9223372036854775807LL;
2522 if (a <= (-9223372036854775807LL-1))
2523 return (-9223372036854775807LL-1);
2528 d = copysign(1.0, a);
2530 return 9223372036854775807LL;
2531 return (-9223372036854775807LL-1);
2533 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2536 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2537 double builtin_f2d(float a)
2539 if (finitef(a)) return (double) a;
2542 return longBitsToDouble(DBL_NAN);
2544 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2548 float builtin_d2f(double a)
2554 return intBitsToFloat(FLT_NAN);
2556 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2559 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2562 /* builtin_arraycopy ***********************************************************
2564 Builtin for java.lang.System.arraycopy.
2566 ATTENTION: This builtin function returns a boolean value to signal
2567 the ICMD_BUILTIN if there was an exception.
2569 *******************************************************************************/
2571 bool builtin_arraycopy(java_handle_t *src, s4 srcStart,
2572 java_handle_t *dest, s4 destStart, s4 len)
2574 arraydescriptor *sdesc;
2575 arraydescriptor *ddesc;
2578 if ((src == NULL) || (dest == NULL)) {
2579 exceptions_throw_nullpointerexception();
2583 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2584 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2586 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2587 exceptions_throw_arraystoreexception();
2591 /* we try to throw exception with the same message as SUN does */
2593 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2594 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2595 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2596 exceptions_throw_arrayindexoutofboundsexception();
2600 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2601 /* We copy primitive values or references of exactly the same type */
2603 s4 dataoffset = sdesc->dataoffset;
2604 s4 componentsize = sdesc->componentsize;
2606 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2607 ((u1 *) src) + dataoffset + componentsize * srcStart,
2608 (size_t) len * componentsize);
2611 /* We copy references of different type */
2613 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2614 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2616 if (destStart <= srcStart) {
2617 for (i = 0; i < len; i++) {
2618 java_handle_t *o = oas->data[srcStart + i];
2620 if (!builtin_canstore(oad, o))
2623 oad->data[destStart + i] = o;
2627 /* XXX this does not completely obey the specification!
2628 If an exception is thrown only the elements above the
2629 current index have been copied. The specification
2630 requires that only the elements *below* the current
2631 index have been copied before the throw. */
2633 for (i = len - 1; i >= 0; i--) {
2634 java_handle_t *o = oas->data[srcStart + i];
2636 if (!builtin_canstore(oad, o))
2639 oad->data[destStart + i] = o;
2648 /* builtin_nanotime ************************************************************
2650 Return the current time in nanoseconds.
2652 *******************************************************************************/
2654 s8 builtin_nanotime(void)
2659 if (gettimeofday(&tv, NULL) == -1)
2660 vm_abort("gettimeofday failed: %s", strerror(errno));
2662 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2664 return usecs * 1000;
2668 /* builtin_currenttimemillis ***************************************************
2670 Return the current time in milliseconds.
2672 *******************************************************************************/
2674 s8 builtin_currenttimemillis(void)
2678 msecs = builtin_nanotime() / 1000 / 1000;
2684 /* builtin_clone ***************************************************************
2686 Function for cloning objects or arrays.
2688 *******************************************************************************/
2690 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2692 arraydescriptor *ad;
2696 java_handle_t *co; /* cloned object header */
2698 /* get the array descriptor */
2700 ad = o->vftbl->arraydesc;
2702 /* we are cloning an array */
2705 ah = (java_handle_t *) o;
2707 size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah);
2709 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2714 MCOPY(co, o, u1, size);
2716 #if defined(ENABLE_GC_CACAO)
2717 heap_init_objectheader(co, size);
2720 #if defined(ENABLE_THREADS)
2721 lock_init_object_lock(co);
2727 /* we are cloning a non-array */
2729 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2730 exceptions_throw_clonenotsupportedexception();
2734 /* get the class of the object */
2736 c = o->vftbl->class;
2738 /* create new object */
2740 co = builtin_new(c);
2745 MCOPY(co, o, u1, c->instancesize);
2747 #if defined(ENABLE_GC_CACAO)
2748 heap_init_objectheader(co, c->instancesize);
2751 #if defined(ENABLE_THREADS)
2752 lock_init_object_lock(co);
2758 #if defined(ENABLE_VMLOG)
2760 #include <vmlog_cacao.c>
2765 * These are local overrides for various environment variables in Emacs.
2766 * Please do not remove this and leave it at the end of the file, where
2767 * Emacs will automagically detect them.
2768 * ---------------------------------------------------------------------
2771 * indent-tabs-mode: t
2775 * vim:noexpandtab:sw=4:ts=4: