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 8348 2007-08-19 09:27:03Z pm $
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"
63 #if defined(ENABLE_THREADS)
64 #include "threads/native/threads.h"
66 #include "threads/none/threads.h"
69 #include "toolbox/logging.h"
70 #include "toolbox/util.h"
73 #include "vm/builtin.h"
74 #include "vm/cycles-stats.h"
75 #include "vm/exceptions.h"
76 #include "vm/global.h"
77 #include "vm/initialize.h"
78 #include "vm/primitive.h"
79 #include "vm/stringlocal.h"
81 #include "vm/jit/asmpart.h"
83 #include "vmcore/class.h"
84 #include "vmcore/linker.h"
85 #include "vmcore/loader.h"
86 #include "vmcore/options.h"
87 #include "vmcore/rt-timing.h"
89 #if defined(ENABLE_VMLOG)
90 #include <vmlog_cacao.h>
93 #if defined(ENABLE_DEBUG_FILTER)
94 # include "vm/jit/show.h"
97 /* include builtin tables *****************************************************/
99 #include "vm/builtintable.inc"
102 CYCLES_STATS_DECLARE(builtin_new ,100,5)
103 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
105 /* builtintable_init ***********************************************************
107 Parse the descriptors of builtin functions and create the parsed
110 *******************************************************************************/
112 static bool builtintable_init(void)
114 descriptor_pool *descpool;
116 builtintable_entry *bte;
118 /* mark start of dump memory area */
120 dumpsize = dump_size();
122 /* create a new descriptor pool */
124 descpool = descriptor_pool_new(class_java_lang_Object);
126 /* add some entries we need */
128 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
131 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
134 /* first add all descriptors to the pool */
136 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
137 /* create a utf8 string from descriptor */
139 bte->descriptor = utf_new_char(bte->cdescriptor);
141 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
142 /* release dump area */
144 dump_release(dumpsize);
150 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
151 bte->descriptor = utf_new_char(bte->cdescriptor);
153 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
154 dump_release(dumpsize);
159 for (bte = builtintable_function; bte->fp != NULL; bte++) {
160 bte->classname = utf_new_char(bte->cclassname);
161 bte->name = utf_new_char(bte->cname);
162 bte->descriptor = utf_new_char(bte->cdescriptor);
164 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
165 dump_release(dumpsize);
170 /* create the class reference table */
172 (void) descriptor_pool_create_classrefs(descpool, NULL);
174 /* allocate space for the parsed descriptors */
176 descriptor_pool_alloc_parsed_descriptors(descpool);
178 /* Now parse all descriptors. NOTE: builtin-functions are treated
179 like static methods (no `this' pointer). */
181 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
183 descriptor_pool_parse_method_descriptor(descpool,
185 ACC_STATIC | ACC_METHOD_BUILTIN,
189 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
191 descriptor_pool_parse_method_descriptor(descpool,
193 ACC_STATIC | ACC_METHOD_BUILTIN,
197 for (bte = builtintable_function; bte->fp != NULL; bte++) {
199 descriptor_pool_parse_method_descriptor(descpool,
201 ACC_STATIC | ACC_METHOD_BUILTIN,
205 /* release dump area */
207 dump_release(dumpsize);
213 /* builtintable_comparator *****************************************************
215 qsort comparator for the automatic builtin table.
217 *******************************************************************************/
219 static int builtintable_comparator(const void *a, const void *b)
221 builtintable_entry *bte1;
222 builtintable_entry *bte2;
224 bte1 = (builtintable_entry *) a;
225 bte2 = (builtintable_entry *) b;
227 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
231 /* builtintable_sort_automatic *************************************************
233 Sorts the automatic builtin table.
235 *******************************************************************************/
237 static void builtintable_sort_automatic(void)
241 /* calculate table size statically (`- 1' comment see builtintable.inc) */
243 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
245 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
246 builtintable_comparator);
250 /* builtin_init ****************************************************************
252 Initialize the global table of builtin functions.
254 *******************************************************************************/
256 bool builtin_init(void)
258 /* initialize the builtin tables */
260 if (!builtintable_init())
263 /* sort builtin tables */
265 builtintable_sort_automatic();
271 /* builtintable_get_internal ***************************************************
273 Finds an entry in the builtintable for internal functions and
274 returns the a pointer to the structure.
276 *******************************************************************************/
278 builtintable_entry *builtintable_get_internal(functionptr fp)
280 builtintable_entry *bte;
282 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
291 /* builtintable_get_automatic **************************************************
293 Finds an entry in the builtintable for functions which are replaced
294 automatically and returns the a pointer to the structure.
296 *******************************************************************************/
298 builtintable_entry *builtintable_get_automatic(s4 opcode)
300 builtintable_entry *first;
301 builtintable_entry *last;
302 builtintable_entry *middle;
306 /* calculate table size statically (`- 1' comment see builtintable.inc) */
308 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
310 first = builtintable_automatic;
311 last = builtintable_automatic + entries;
313 while (entries > 0) {
315 middle = first + half;
317 if (middle->opcode < opcode) {
324 return (first != last ? first : NULL);
328 /* builtintable_replace_function ***********************************************
332 *******************************************************************************/
334 #if defined(ENABLE_JIT)
335 bool builtintable_replace_function(void *iptr_)
338 builtintable_entry *bte;
341 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
343 /* get name and descriptor of the function */
346 case ICMD_INVOKESTATIC:
347 /* The instruction MUST be resolved, otherwise we run into
348 lazy loading troubles. Anyway, we should/can only replace
349 very VM-close functions. */
351 if (INSTRUCTION_IS_UNRESOLVED(iptr))
354 mr = iptr->sx.s23.s3.fmiref;
361 /* search the function table */
363 for (bte = builtintable_function; bte->fp != NULL; bte++) {
364 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
365 (mr->name == bte->name) &&
366 (mr->descriptor == bte->descriptor)) {
368 /* set the values in the instruction */
370 iptr->opc = bte->opcode;
371 iptr->sx.s23.s3.bte = bte;
372 if (bte->checkexception)
373 iptr->flags.bits |= INS_FLAG_CHECK;
375 iptr->flags.bits &= ~INS_FLAG_CHECK;
383 #endif /* defined(ENABLE_JIT) */
386 /*****************************************************************************
388 *****************************************************************************/
390 /* builtin_instanceof **********************************************************
392 Checks if an object is an instance of some given class (or subclass
393 of that class). If class is an interface, checks if the interface
396 Return value: 1 ... o is an instance of class or implements the interface
397 0 ... otherwise or if o == NULL
399 *******************************************************************************/
401 s4 builtin_instanceof(java_handle_t *o, classinfo *class)
406 return class_isanysubclass(o->vftbl->class, class);
411 /* builtin_checkcast ***********************************************************
413 The same as builtin_instanceof except that 1 is returned when o ==
416 *******************************************************************************/
418 s4 builtin_checkcast(java_handle_t *o, classinfo *class)
423 if (class_isanysubclass(o->vftbl->class, class))
430 /* builtin_descriptorscompatible ***********************************************
432 Checks if two array type descriptors are assignment compatible
434 Return value: 1 ... target = desc is possible
437 *******************************************************************************/
439 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
440 arraydescriptor *target)
445 if (desc->arraytype != target->arraytype)
448 if (desc->arraytype != ARRAYTYPE_OBJECT)
451 /* {both arrays are arrays of references} */
453 if (desc->dimension == target->dimension) {
454 /* an array which contains elements of interface types is
455 allowed to be casted to Object (JOWENN)*/
457 if ((desc->elementvftbl->baseval < 0) &&
458 (target->elementvftbl->baseval == 1))
461 return class_isanysubclass(desc->elementvftbl->class,
462 target->elementvftbl->class);
465 if (desc->dimension < target->dimension)
468 /* {desc has higher dimension than target} */
470 return class_isanysubclass(pseudo_class_Arraystub,
471 target->elementvftbl->class);
475 /* builtin_arraycheckcast ******************************************************
477 Checks if an object is really a subtype of the requested array
478 type. The object has to be an array to begin with. For simple
479 arrays (int, short, double, etc.) the types have to match exactly.
480 For arrays of objects, the type of elements in the array has to be
481 a subtype (or the same type) of the requested element type. For
482 arrays of arrays (which in turn can again be arrays of arrays), the
483 types at the lowest level have to satisfy the corresponding sub
486 *******************************************************************************/
488 s4 builtin_arraycheckcast(java_handle_t *o, classinfo *targetclass)
490 arraydescriptor *desc;
495 desc = o->vftbl->arraydesc;
500 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
504 s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass)
509 return builtin_arraycheckcast(o, targetclass);
513 /* builtin_throw_exception *****************************************************
515 Sets the exceptionptr with the thrown exception and prints some
516 debugging information. Called from asm_vm_call_method.
518 *******************************************************************************/
520 void *builtin_throw_exception(java_handle_t *xptr)
523 java_lang_Throwable *t;
530 t = (java_lang_Throwable *) xptr;
532 /* get detail message */
534 LLNI_field_get_ref(t, detailMessage, s);
536 /* calculate message length */
538 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
542 utf_bytes(xptr->vftbl->class->name);
544 logtextlen += strlen(": ") +
545 u2_utflength(LLNI_field_direct(s, value)->data
546 + LLNI_field_direct(s, offset),
547 LLNI_field_direct(s,count));
551 logtextlen += strlen("(nil)");
554 /* allocate memory */
556 dumpsize = dump_size();
558 logtext = DMNEW(char, logtextlen);
560 strcpy(logtext, "Builtin exception thrown: ");
563 utf_cat_classname(logtext, xptr->vftbl->class->name);
568 buf = javastring_tochar((java_handle_t *) s);
569 strcat(logtext, ": ");
570 strcat(logtext, buf);
571 MFREE(buf, char, strlen(buf) + 1);
575 strcat(logtext, "(nil)");
582 dump_release(dumpsize);
584 #endif /* !defined(NDEBUG) */
586 /* actually set the exception */
588 exceptions_set_exception(xptr);
590 /* Return a NULL pointer. This is required for vm_call_method to
591 check for an exception. This is for convenience. */
597 /* builtin_canstore ************************************************************
599 Checks, if an object can be stored in an array.
601 Return value: 1 ... possible
602 0 ... otherwise (throws an ArrayStoreException)
604 *******************************************************************************/
606 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
608 arraydescriptor *desc;
609 arraydescriptor *valuedesc;
610 vftbl_t *componentvftbl;
619 /* The following is guaranteed (by verifier checks):
621 * *) oa->...vftbl->arraydesc != NULL
622 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
623 * *) o->vftbl is not an interface vftbl
626 desc = oa->header.objheader.vftbl->arraydesc;
627 componentvftbl = desc->componentvftbl;
628 valuevftbl = o->vftbl;
629 valuedesc = valuevftbl->arraydesc;
631 if ((desc->dimension - 1) == 0) {
632 /* {oa is a one-dimensional array} */
633 /* {oa is an array of references} */
635 if (valuevftbl == componentvftbl)
638 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
640 baseval = componentvftbl->baseval;
643 /* an array of interface references */
645 result = ((valuevftbl->interfacetablelength > -baseval) &&
646 (valuevftbl->interfacetable[baseval] != NULL));
649 diffval = valuevftbl->baseval - componentvftbl->baseval;
650 result = diffval <= (uint32_t) componentvftbl->diffval;
653 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
655 else if (valuedesc == NULL) {
656 /* {oa has dimension > 1} */
657 /* {componentvftbl->arraydesc != NULL} */
659 /* check if o is an array */
664 /* {o is an array} */
666 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
669 /* if not possible, throw an exception */
672 exceptions_throw_arraystoreexception();
680 /* This is an optimized version where a is guaranteed to be one-dimensional */
681 s4 builtin_canstore_onedim (java_handle_objectarray_t *a, java_handle_t *o)
683 arraydescriptor *desc;
684 vftbl_t *elementvftbl;
693 /* The following is guaranteed (by verifier checks):
695 * *) a->...vftbl->arraydesc != NULL
696 * *) a->...vftbl->arraydesc->elementvftbl != NULL
697 * *) a->...vftbl->arraydesc->dimension == 1
698 * *) o->vftbl is not an interface vftbl
701 desc = a->header.objheader.vftbl->arraydesc;
702 elementvftbl = desc->elementvftbl;
703 valuevftbl = o->vftbl;
705 /* {a is a one-dimensional array} */
707 if (valuevftbl == elementvftbl)
710 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
712 baseval = elementvftbl->baseval;
715 /* an array of interface references */
716 result = ((valuevftbl->interfacetablelength > -baseval) &&
717 (valuevftbl->interfacetable[baseval] != NULL));
720 diffval = valuevftbl->baseval - elementvftbl->baseval;
721 result = diffval <= (uint32_t) elementvftbl->diffval;
724 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
730 /* This is an optimized version where a is guaranteed to be a
731 * one-dimensional array of a class type */
732 s4 builtin_canstore_onedim_class(java_handle_objectarray_t *a, java_handle_t *o)
734 vftbl_t *elementvftbl;
742 /* The following is guaranteed (by verifier checks):
744 * *) a->...vftbl->arraydesc != NULL
745 * *) a->...vftbl->arraydesc->elementvftbl != NULL
746 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
747 * *) a->...vftbl->arraydesc->dimension == 1
748 * *) o->vftbl is not an interface vftbl
751 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
752 valuevftbl = o->vftbl;
754 /* {a is a one-dimensional array} */
756 if (valuevftbl == elementvftbl)
759 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
761 diffval = valuevftbl->baseval - elementvftbl->baseval;
762 result = diffval <= (uint32_t) elementvftbl->diffval;
764 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
770 /* builtin_new *****************************************************************
772 Creates a new instance of class c on the heap.
774 Return value: pointer to the object or NULL if no memory is
777 *******************************************************************************/
779 java_handle_t *builtin_new(classinfo *c)
782 #if defined(ENABLE_RT_TIMING)
783 struct timespec time_start, time_end;
785 #if defined(ENABLE_CYCLES_STATS)
786 u8 cycles_start, cycles_end;
789 RT_TIMING_GET_TIME(time_start);
790 CYCLES_STATS_GET(cycles_start);
792 /* is the class loaded */
794 assert(c->state & CLASS_LOADED);
796 /* check if we can instantiate this class */
798 if (c->flags & ACC_ABSTRACT) {
799 exceptions_throw_instantiationerror(c);
803 /* is the class linked */
805 if (!(c->state & CLASS_LINKED))
809 if (!(c->state & CLASS_INITIALIZED)) {
812 log_message_class("Initialize class (from builtin_new): ", c);
815 if (!initialize_class(c))
819 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
827 #if defined(ENABLE_THREADS)
828 lock_init_object_lock(o);
831 CYCLES_STATS_GET(cycles_end);
832 RT_TIMING_GET_TIME(time_end);
834 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
835 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
841 /* builtin_newarray ************************************************************
843 Creates an array with the given vftbl on the heap. This function
844 takes as class argument an array class.
846 Return value: pointer to the array or NULL if no memory is available
848 *******************************************************************************/
850 java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
852 arraydescriptor *desc;
857 #if defined(ENABLE_RT_TIMING)
858 struct timespec time_start, time_end;
861 RT_TIMING_GET_TIME(time_start);
863 desc = arrayclass->vftbl->arraydesc;
864 dataoffset = desc->dataoffset;
865 componentsize = desc->componentsize;
868 exceptions_throw_negativearraysizeexception();
872 actualsize = dataoffset + size * componentsize;
874 /* check for overflow */
876 if (((u4) actualsize) < ((u4) size)) {
877 exceptions_throw_outofmemoryerror();
881 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
886 a->objheader.vftbl = arrayclass->vftbl;
888 #if defined(ENABLE_THREADS)
889 lock_init_object_lock(&a->objheader);
892 LLNI_array_size(a) = size;
894 RT_TIMING_GET_TIME(time_end);
895 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
901 /* builtin_anewarray ***********************************************************
903 Creates an array of references to the given class type on the heap.
905 Return value: pointer to the array or NULL if no memory is
908 *******************************************************************************/
910 java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
912 classinfo *arrayclass;
914 /* is class loaded */
916 assert(componentclass->state & CLASS_LOADED);
918 /* is class linked */
920 if (!(componentclass->state & CLASS_LINKED))
921 if (!link_class(componentclass))
924 arrayclass = class_array_of(componentclass, true);
929 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
933 /* builtin_newarray_boolean ****************************************************
935 Creates an array of bytes on the heap. The array is designated as
936 an array of booleans (important for casts)
938 Return value: pointer to the array or NULL if no memory is
941 *******************************************************************************/
943 java_handle_booleanarray_t *builtin_newarray_boolean(s4 size)
945 return (java_handle_booleanarray_t *)
946 builtin_newarray(size,
947 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
951 /* builtin_newarray_byte *******************************************************
953 Creates an array of 8 bit Integers on the heap.
955 Return value: pointer to the array or NULL if no memory is
958 *******************************************************************************/
960 java_handle_bytearray_t *builtin_newarray_byte(s4 size)
962 return (java_handle_bytearray_t *)
963 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
967 /* builtin_newarray_char *******************************************************
969 Creates an array of characters on the heap.
971 Return value: pointer to the array or NULL if no memory is
974 *******************************************************************************/
976 java_handle_chararray_t *builtin_newarray_char(s4 size)
978 return (java_handle_chararray_t *)
979 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
983 /* builtin_newarray_short ******************************************************
985 Creates an array of 16 bit Integers on the heap.
987 Return value: pointer to the array or NULL if no memory is
990 *******************************************************************************/
992 java_handle_shortarray_t *builtin_newarray_short(s4 size)
994 return (java_handle_shortarray_t *)
995 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
999 /* builtin_newarray_int ********************************************************
1001 Creates an array of 32 bit Integers on the heap.
1003 Return value: pointer to the array or NULL if no memory is
1006 *******************************************************************************/
1008 java_handle_intarray_t *builtin_newarray_int(s4 size)
1010 return (java_handle_intarray_t *)
1011 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1015 /* builtin_newarray_long *******************************************************
1017 Creates an array of 64 bit Integers on the heap.
1019 Return value: pointer to the array or NULL if no memory is
1022 *******************************************************************************/
1024 java_handle_longarray_t *builtin_newarray_long(s4 size)
1026 return (java_handle_longarray_t *)
1027 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1031 /* builtin_newarray_float ******************************************************
1033 Creates an array of 32 bit IEEE floats on the heap.
1035 Return value: pointer to the array or NULL if no memory is
1038 *******************************************************************************/
1040 java_handle_floatarray_t *builtin_newarray_float(s4 size)
1042 return (java_handle_floatarray_t *)
1043 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1047 /* builtin_newarray_double *****************************************************
1049 Creates an array of 64 bit IEEE floats on the heap.
1051 Return value: pointer to the array or NULL if no memory is
1054 *******************************************************************************/
1056 java_handle_doublearray_t *builtin_newarray_double(s4 size)
1058 return (java_handle_doublearray_t *)
1059 builtin_newarray(size,
1060 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1064 /* builtin_multianewarray_intern ***********************************************
1066 Creates a multi-dimensional array on the heap. The dimensions are
1067 passed in an array of longs.
1070 n.............number of dimensions to create
1071 arrayclass....the array class
1072 dims..........array containing the size of each dimension to create
1074 Return value: pointer to the array or NULL if no memory is
1077 ******************************************************************************/
1079 static java_handle_t *builtin_multianewarray_intern(int n,
1080 classinfo *arrayclass,
1085 classinfo *componentclass;
1088 /* create this dimension */
1090 size = (s4) dims[0];
1091 a = builtin_newarray(size, arrayclass);
1096 /* if this is the last dimension return */
1101 /* get the class of the components to create */
1103 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1105 /* The verifier guarantees that the dimension count is in the range. */
1107 /* create the component arrays */
1109 for (i = 0; i < size; i++) {
1111 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1112 /* we save an s4 to a s8 slot, 8-byte aligned */
1114 builtin_multianewarray_intern(n, componentclass, dims + 2);
1116 builtin_multianewarray_intern(n, componentclass, dims + 1);
1122 ((java_handle_objectarray_t *) a)->data[i] = (java_object_t *) ea;
1129 /* builtin_multianewarray ******************************************************
1131 Wrapper for builtin_multianewarray_intern which checks all
1132 dimensions before we start allocating.
1134 ******************************************************************************/
1136 java_handle_objectarray_t *builtin_multianewarray(int n, classinfo *arrayclass,
1142 /* check all dimensions before doing anything */
1144 for (i = 0; i < n; i++) {
1145 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1146 /* we save an s4 to a s8 slot, 8-byte aligned */
1147 size = (s4) dims[i * 2];
1149 size = (s4) dims[i];
1153 exceptions_throw_negativearraysizeexception();
1158 /* now call the real function */
1160 return builtin_multianewarray_intern(n, arrayclass, dims);
1164 /*****************************************************************************
1167 Various functions for printing a message at method entry or exit (for
1170 *****************************************************************************/
1172 #if !defined(NDEBUG)
1173 static s4 methodindent = 0;
1174 static u4 callcount = 0;
1176 java_handle_t *builtin_trace_exception(java_handle_t *xptr,
1186 #if defined(ENABLE_DEBUG_FILTER)
1187 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1190 #if defined(ENABLE_VMLOG)
1194 if (opt_verbosecall && indent)
1195 #if defined(__S390__)
1196 TRACEJAVACALLINDENT--;
1201 /* calculate message length */
1205 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1208 logtextlen = strlen("Some Throwable");
1211 logtextlen += strlen(" thrown in ");
1215 utf_bytes(m->class->name) +
1217 utf_bytes(m->name) +
1218 utf_bytes(m->descriptor) +
1219 strlen("(NOSYNC,NATIVE");
1221 #if SIZEOF_VOID_P == 8
1223 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1225 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1228 if (m->class->sourcefile == NULL)
1229 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1231 logtextlen += utf_bytes(m->class->sourcefile);
1233 logtextlen += strlen(":65536)");
1237 logtextlen += strlen("call_java_method");
1240 logtextlen += strlen("0");
1242 /* allocate memory */
1244 dumpsize = dump_size();
1246 logtext = DMNEW(char, logtextlen);
1249 strcpy(logtext, "Exception ");
1250 utf_cat_classname(logtext, xptr->vftbl->class->name);
1253 strcpy(logtext, "Some Throwable");
1256 strcat(logtext, " thrown in ");
1259 utf_cat_classname(logtext, m->class->name);
1260 strcat(logtext, ".");
1261 utf_cat(logtext, m->name);
1262 utf_cat(logtext, m->descriptor);
1264 if (m->flags & ACC_SYNCHRONIZED)
1265 strcat(logtext, "(SYNC");
1267 strcat(logtext, "(NOSYNC");
1269 if (m->flags & ACC_NATIVE) {
1270 strcat(logtext, ",NATIVE");
1274 #if SIZEOF_VOID_P == 8
1275 sprintf(logtext + strlen(logtext),
1276 ")(0x%016lx) at position 0x%016lx",
1277 (ptrint) code->entrypoint, (ptrint) pos);
1279 sprintf(logtext + strlen(logtext),
1280 ")(0x%08x) at position 0x%08x",
1281 (ptrint) code->entrypoint, (ptrint) pos);
1286 /* XXX preliminary: This should get the actual codeinfo */
1287 /* in which the exception happened. */
1290 #if SIZEOF_VOID_P == 8
1291 sprintf(logtext + strlen(logtext),
1292 ")(0x%016lx) at position 0x%016lx (",
1293 (ptrint) code->entrypoint, (ptrint) pos);
1295 sprintf(logtext + strlen(logtext),
1296 ")(0x%08x) at position 0x%08x (",
1297 (ptrint) code->entrypoint, (ptrint) pos);
1300 if (m->class->sourcefile == NULL)
1301 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1303 utf_cat(logtext, m->class->sourcefile);
1305 sprintf(logtext + strlen(logtext), ":%d)", 0);
1309 strcat(logtext, "call_java_method");
1313 /* release memory */
1315 dump_release(dumpsize);
1319 #endif /* !defined(NDEBUG) */
1322 /* builtin_print_argument ******************************************************
1324 Prints arguments and return values for the call trace.
1326 *******************************************************************************/
1328 #if !defined(NDEBUG)
1329 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1330 typedesc *paramtype, s8 value)
1338 switch (paramtype->type) {
1341 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1346 #if SIZEOF_VOID_P == 4
1347 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1349 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1354 #if defined(__S390__)
1356 /* The below won't work on S390 */
1360 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1365 #if SIZEOF_VOID_P == 4
1366 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1368 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1373 #if SIZEOF_VOID_P == 4
1374 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1376 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1379 /* cast to java.lang.Object */
1381 o = (java_handle_t *) (ptrint) value;
1383 /* check return argument for java.lang.Class or java.lang.String */
1386 if (o->vftbl->class == class_java_lang_String) {
1387 /* get java.lang.String object and the length of the
1390 u = javastring_toutf(o, false);
1392 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1394 /* realloc memory for string length */
1396 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1399 /* convert to utf8 string and strcat it to the logtext */
1401 strcat(logtext, " (String = \"");
1402 utf_cat(logtext, u);
1403 strcat(logtext, "\")");
1406 if (o->vftbl->class == class_java_lang_Class) {
1407 /* if the object returned is a java.lang.Class
1408 cast it to classinfo structure and get the name
1411 c = (classinfo *) o;
1416 /* if the object returned is not a java.lang.String or
1417 a java.lang.Class just print the name of the class */
1419 u = o->vftbl->class->name;
1422 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1424 /* realloc memory for string length */
1426 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1429 /* strcat to the logtext */
1431 strcat(logtext, " (Class = \"");
1432 utf_cat_classname(logtext, u);
1433 strcat(logtext, "\")");
1440 #endif /* !defined(NDEBUG) */
1442 /* builtin_verbosecall_enter ***************************************************
1444 Print method call with arguments for -verbose:call.
1446 *******************************************************************************/
1448 #if !defined(NDEBUG)
1450 #ifdef TRACE_ARGS_NUM
1451 void builtin_verbosecall_enter(s8 a0, s8 a1,
1452 # if TRACE_ARGS_NUM >= 4
1455 # if TRACE_ARGS_NUM >= 6
1458 # if TRACE_ARGS_NUM == 8
1470 #if defined(ENABLE_DEBUG_FILTER)
1471 if (! show_filters_test_verbosecall_enter(m)) return;
1474 #if defined(ENABLE_VMLOG)
1475 vmlog_cacao_enter_method(m);
1481 /* calculate message length */
1484 strlen("4294967295 ") +
1485 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1487 strlen("called: ") +
1488 utf_bytes(m->class->name) +
1490 utf_bytes(m->name) +
1491 utf_bytes(m->descriptor);
1493 /* Actually it's not possible to have all flags printed, but:
1498 strlen(" PRIVATE") +
1499 strlen(" PROTECTED") +
1502 strlen(" SYNCHRONIZED") +
1503 strlen(" VOLATILE") +
1504 strlen(" TRANSIENT") +
1506 strlen(" INTERFACE") +
1507 strlen(" ABSTRACT");
1509 /* add maximal argument length */
1513 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1514 strlen("...(255)") +
1517 /* allocate memory */
1519 dumpsize = dump_size();
1521 logtext = DMNEW(char, logtextlen);
1525 sprintf(logtext, "%10d ", callcount);
1526 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1528 pos = strlen(logtext);
1530 for (i = 0; i < methodindent; i++)
1531 logtext[pos++] = '\t';
1533 strcpy(logtext + pos, "called: ");
1535 utf_cat_classname(logtext, m->class->name);
1536 strcat(logtext, ".");
1537 utf_cat(logtext, m->name);
1538 utf_cat(logtext, m->descriptor);
1540 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1541 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1542 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1543 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1544 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1545 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1546 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1547 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1548 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1549 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1550 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1552 strcat(logtext, "(");
1554 if (md->paramcount >= 1) {
1555 logtext = builtin_print_argument(logtext, &logtextlen,
1556 &md->paramtypes[0], a0);
1559 if (md->paramcount >= 2) {
1560 strcat(logtext, ", ");
1562 logtext = builtin_print_argument(logtext, &logtextlen,
1563 &md->paramtypes[1], a1);
1566 #if TRACE_ARGS_NUM >= 4
1567 if (md->paramcount >= 3) {
1568 strcat(logtext, ", ");
1570 logtext = builtin_print_argument(logtext, &logtextlen,
1571 &md->paramtypes[2], a2);
1574 if (md->paramcount >= 4) {
1575 strcat(logtext, ", ");
1577 logtext = builtin_print_argument(logtext, &logtextlen,
1578 &md->paramtypes[3], a3);
1582 #if TRACE_ARGS_NUM >= 6
1583 if (md->paramcount >= 5) {
1584 strcat(logtext, ", ");
1586 logtext = builtin_print_argument(logtext, &logtextlen,
1587 &md->paramtypes[4], a4);
1590 if (md->paramcount >= 6) {
1591 strcat(logtext, ", ");
1593 logtext = builtin_print_argument(logtext, &logtextlen,
1594 &md->paramtypes[5], a5);
1598 #if TRACE_ARGS_NUM == 8
1599 if (md->paramcount >= 7) {
1600 strcat(logtext, ", ");
1602 logtext = builtin_print_argument(logtext, &logtextlen,
1603 &md->paramtypes[6], a6);
1606 if (md->paramcount >= 8) {
1607 strcat(logtext, ", ");
1609 logtext = builtin_print_argument(logtext, &logtextlen,
1610 &md->paramtypes[7], a7);
1614 if (md->paramcount > 8) {
1615 sprintf(logtext + strlen(logtext), ", ...(%d)",
1616 md->paramcount - TRACE_ARGS_NUM);
1619 strcat(logtext, ")");
1623 /* release memory */
1625 dump_release(dumpsize);
1631 #endif /* !defined(NDEBUG) */
1634 /* builtin_verbosecall_exit ****************************************************
1636 Print method exit for -verbose:call.
1638 *******************************************************************************/
1640 #if !defined(NDEBUG)
1641 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1651 #if defined(ENABLE_DEBUG_FILTER)
1652 if (! show_filters_test_verbosecall_exit(m)) return;
1655 #if defined(ENABLE_VMLOG)
1656 vmlog_cacao_leave_method(m);
1662 /* calculate message length */
1665 strlen("4294967295 ") +
1666 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1668 strlen("finished: ") +
1669 utf_bytes(m->class->name) +
1671 utf_bytes(m->name) +
1672 utf_bytes(m->descriptor) +
1673 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1675 /* add maximal argument length */
1677 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1679 /* allocate memory */
1681 dumpsize = dump_size();
1683 logtext = DMNEW(char, logtextlen);
1685 /* outdent the log message */
1690 log_text("WARNING: unmatched methodindent--");
1692 /* generate the message */
1694 sprintf(logtext, " ");
1695 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1697 pos = strlen(logtext);
1699 for (i = 0; i < methodindent; i++)
1700 logtext[pos++] = '\t';
1702 strcpy(logtext + pos, "finished: ");
1703 utf_cat_classname(logtext, m->class->name);
1704 strcat(logtext, ".");
1705 utf_cat(logtext, m->name);
1706 utf_cat(logtext, m->descriptor);
1708 if (!IS_VOID_TYPE(md->returntype.type)) {
1709 strcat(logtext, "->");
1711 switch (md->returntype.type) {
1728 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1733 /* release memory */
1735 dump_release(dumpsize);
1738 #endif /* !defined(NDEBUG) */
1741 #if defined(ENABLE_CYCLES_STATS)
1742 void builtin_print_cycles_stats(FILE *file)
1744 fprintf(file,"builtin cylce count statistics:\n");
1746 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1747 CYCLES_STATS_PRINT(builtin_new ,file);
1751 #endif /* defined(ENABLE_CYCLES_STATS) */
1754 /*****************************************************************************
1755 MISCELLANEOUS HELPER FUNCTIONS
1756 *****************************************************************************/
1760 /*********** Functions for integer divisions *****************************
1762 On some systems (eg. DEC ALPHA), integer division is not supported by the
1763 CPU. These helper functions implement the missing functionality.
1765 ******************************************************************************/
1767 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1768 s4 builtin_idiv(s4 a, s4 b)
1777 s4 builtin_irem(s4 a, s4 b)
1785 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1788 /* functions for long arithmetics **********************************************
1790 On systems where 64 bit Integers are not supported by the CPU,
1791 these functions are needed.
1793 ******************************************************************************/
1795 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1796 s8 builtin_ladd(s8 a, s8 b)
1809 s8 builtin_lsub(s8 a, s8 b)
1822 s8 builtin_lneg(s8 a)
1834 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1837 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1838 s8 builtin_lmul(s8 a, s8 b)
1850 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1853 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1854 s8 builtin_ldiv(s8 a, s8 b)
1867 s8 builtin_lrem(s8 a, s8 b)
1879 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1882 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1883 s8 builtin_lshl(s8 a, s4 b)
1896 s8 builtin_lshr(s8 a, s4 b)
1909 s8 builtin_lushr(s8 a, s4 b)
1914 c = ((u8) a) >> (b & 63);
1921 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1924 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1925 s8 builtin_land(s8 a, s8 b)
1938 s8 builtin_lor(s8 a, s8 b)
1951 s8 builtin_lxor(s8 a, s8 b)
1963 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1966 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1967 s4 builtin_lcmp(s8 a, s8 b)
1981 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1984 /* functions for unsupported floating instructions ****************************/
1986 /* used to convert FLT_xxx defines into float values */
1988 static inline float intBitsToFloat(s4 i)
1997 /* used to convert DBL_xxx defines into double values */
1999 static inline float longBitsToDouble(s8 l)
2009 float builtin_fadd(float a, float b)
2011 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2012 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2023 if (copysignf(1.0, a) == copysignf(1.0, b))
2026 return intBitsToFloat(FLT_NAN);
2032 float builtin_fsub(float a, float b)
2034 return builtin_fadd(a, builtin_fneg(b));
2038 float builtin_fmul(float a, float b)
2040 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2041 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2043 if (finitef(b)) return a * b;
2045 if (a == 0) return intBitsToFloat(FLT_NAN);
2046 else return copysignf(b, copysignf(1.0, b)*a);
2051 if (b == 0) return intBitsToFloat(FLT_NAN);
2052 else return copysignf(a, copysignf(1.0, a)*b);
2055 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2061 /* builtin_ddiv ****************************************************************
2063 Implementation as described in VM Spec.
2065 *******************************************************************************/
2067 float builtin_fdiv(float a, float b)
2071 /* If neither value1' nor value2' is NaN, the sign of the result */
2072 /* is positive if both values have the same sign, negative if the */
2073 /* values have different signs. */
2079 /* If either value1' or value2' is NaN, the result is NaN. */
2081 return intBitsToFloat(FLT_NAN);
2084 /* Division of a finite value by an infinity results in a */
2085 /* signed zero, with the sign-producing rule just given. */
2087 /* is sign equal? */
2089 if (copysignf(1.0, a) == copysignf(1.0, b))
2098 /* If either value1' or value2' is NaN, the result is NaN. */
2100 return intBitsToFloat(FLT_NAN);
2102 } else if (finitef(b)) {
2103 /* Division of an infinity by a finite value results in a signed */
2104 /* infinity, with the sign-producing rule just given. */
2106 /* is sign equal? */
2108 if (copysignf(1.0, a) == copysignf(1.0, b))
2109 return intBitsToFloat(FLT_POSINF);
2111 return intBitsToFloat(FLT_NEGINF);
2114 /* Division of an infinity by an infinity results in NaN. */
2116 return intBitsToFloat(FLT_NAN);
2122 float builtin_fneg(float a)
2124 if (isnanf(a)) return a;
2126 if (finitef(a)) return -a;
2127 else return copysignf(a, -copysignf(1.0, a));
2130 #endif /* !SUPPORT_FLOAT */
2133 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2134 s4 builtin_fcmpl(float a, float b)
2142 if (!finitef(a) || !finitef(b)) {
2143 a = finitef(a) ? 0 : copysignf(1.0, a);
2144 b = finitef(b) ? 0 : copysignf(1.0, b);
2157 s4 builtin_fcmpg(float a, float b)
2159 if (isnanf(a)) return 1;
2160 if (isnanf(b)) return 1;
2161 if (!finitef(a) || !finitef(b)) {
2162 a = finitef(a) ? 0 : copysignf(1.0, a);
2163 b = finitef(b) ? 0 : copysignf(1.0, b);
2165 if (a > b) return 1;
2166 if (a == b) return 0;
2169 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2172 float builtin_frem(float a, float b)
2178 /* functions for unsupported double instructions ******************************/
2181 double builtin_dadd(double a, double b)
2183 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2184 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2186 if (finite(b)) return a + b;
2190 if (finite(b)) return a;
2192 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2193 else return longBitsToDouble(DBL_NAN);
2199 double builtin_dsub(double a, double b)
2201 return builtin_dadd(a, builtin_dneg(b));
2205 double builtin_dmul(double a, double b)
2207 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2208 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2210 if (finite(b)) return a * b;
2212 if (a == 0) return longBitsToDouble(DBL_NAN);
2213 else return copysign(b, copysign(1.0, b) * a);
2218 if (b == 0) return longBitsToDouble(DBL_NAN);
2219 else return copysign(a, copysign(1.0, a) * b);
2222 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2228 /* builtin_ddiv ****************************************************************
2230 Implementation as described in VM Spec.
2232 *******************************************************************************/
2234 double builtin_ddiv(double a, double b)
2238 /* If neither value1' nor value2' is NaN, the sign of the result */
2239 /* is positive if both values have the same sign, negative if the */
2240 /* values have different signs. */
2246 /* If either value1' or value2' is NaN, the result is NaN. */
2248 return longBitsToDouble(DBL_NAN);
2251 /* Division of a finite value by an infinity results in a */
2252 /* signed zero, with the sign-producing rule just given. */
2254 /* is sign equal? */
2256 if (copysign(1.0, a) == copysign(1.0, b))
2265 /* If either value1' or value2' is NaN, the result is NaN. */
2267 return longBitsToDouble(DBL_NAN);
2269 } else if (finite(b)) {
2270 /* Division of an infinity by a finite value results in a signed */
2271 /* infinity, with the sign-producing rule just given. */
2273 /* is sign equal? */
2275 if (copysign(1.0, a) == copysign(1.0, b))
2276 return longBitsToDouble(DBL_POSINF);
2278 return longBitsToDouble(DBL_NEGINF);
2281 /* Division of an infinity by an infinity results in NaN. */
2283 return longBitsToDouble(DBL_NAN);
2289 /* builtin_dneg ****************************************************************
2291 Implemented as described in VM Spec.
2293 *******************************************************************************/
2295 double builtin_dneg(double a)
2298 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2305 /* If the operand is a zero, the result is the zero of opposite */
2311 /* If the operand is an infinity, the result is the infinity of */
2312 /* opposite sign. */
2314 return copysign(a, -copysign(1.0, a));
2318 #endif /* !SUPPORT_DOUBLE */
2321 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2322 s4 builtin_dcmpl(double a, double b)
2330 if (!finite(a) || !finite(b)) {
2331 a = finite(a) ? 0 : copysign(1.0, a);
2332 b = finite(b) ? 0 : copysign(1.0, b);
2345 s4 builtin_dcmpg(double a, double b)
2353 if (!finite(a) || !finite(b)) {
2354 a = finite(a) ? 0 : copysign(1.0, a);
2355 b = finite(b) ? 0 : copysign(1.0, b);
2366 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2369 double builtin_drem(double a, double b)
2375 /* conversion operations ******************************************************/
2378 s8 builtin_i2l(s4 i)
2390 s4 builtin_l2i(s8 l)
2401 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2402 float builtin_i2f(s4 a)
2404 float f = (float) a;
2407 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2410 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2411 double builtin_i2d(s4 a)
2413 double d = (double) a;
2416 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2419 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2420 float builtin_l2f(s8 a)
2423 float f = (float) a;
2429 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2432 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2433 double builtin_l2d(s8 a)
2436 double d = (double) a;
2442 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2445 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2446 s4 builtin_f2i(float a)
2450 i = builtin_d2i((double) a);
2461 if (a < (-2147483648))
2462 return (-2147483648);
2465 f = copysignf((float) 1.0, a);
2468 return (-2147483648); */
2470 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2473 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2474 s8 builtin_f2l(float a)
2478 l = builtin_d2l((double) a);
2485 if (a > 9223372036854775807L)
2486 return 9223372036854775807L;
2487 if (a < (-9223372036854775808L))
2488 return (-9223372036854775808L);
2493 f = copysignf((float) 1.0, a);
2495 return 9223372036854775807L;
2496 return (-9223372036854775808L); */
2498 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2501 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2502 s4 builtin_d2i(double a)
2507 if (a >= 2147483647)
2509 if (a <= (-2147483647-1))
2510 return (-2147483647-1);
2515 d = copysign(1.0, a);
2518 return (-2147483647-1);
2520 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2523 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2524 s8 builtin_d2l(double a)
2529 if (a >= 9223372036854775807LL)
2530 return 9223372036854775807LL;
2531 if (a <= (-9223372036854775807LL-1))
2532 return (-9223372036854775807LL-1);
2537 d = copysign(1.0, a);
2539 return 9223372036854775807LL;
2540 return (-9223372036854775807LL-1);
2542 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2545 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2546 double builtin_f2d(float a)
2548 if (finitef(a)) return (double) a;
2551 return longBitsToDouble(DBL_NAN);
2553 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2557 float builtin_d2f(double a)
2563 return intBitsToFloat(FLT_NAN);
2565 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2568 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2571 /* builtin_arraycopy ***********************************************************
2573 Builtin for java.lang.System.arraycopy.
2575 ATTENTION: This builtin function returns a boolean value to signal
2576 the ICMD_BUILTIN if there was an exception.
2578 *******************************************************************************/
2580 bool builtin_arraycopy(java_handle_t *src, s4 srcStart,
2581 java_handle_t *dest, s4 destStart, s4 len)
2583 arraydescriptor *sdesc;
2584 arraydescriptor *ddesc;
2587 if ((src == NULL) || (dest == NULL)) {
2588 exceptions_throw_nullpointerexception();
2592 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2593 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2595 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2596 exceptions_throw_arraystoreexception();
2600 /* we try to throw exception with the same message as SUN does */
2602 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2603 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2604 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2605 exceptions_throw_arrayindexoutofboundsexception();
2609 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2610 /* We copy primitive values or references of exactly the same type */
2612 s4 dataoffset = sdesc->dataoffset;
2613 s4 componentsize = sdesc->componentsize;
2615 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2616 ((u1 *) src) + dataoffset + componentsize * srcStart,
2617 (size_t) len * componentsize);
2620 /* We copy references of different type */
2622 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2623 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2625 if (destStart <= srcStart) {
2626 for (i = 0; i < len; i++) {
2627 java_handle_t *o = oas->data[srcStart + i];
2629 if (!builtin_canstore(oad, o))
2632 oad->data[destStart + i] = o;
2636 /* XXX this does not completely obey the specification!
2637 If an exception is thrown only the elements above the
2638 current index have been copied. The specification
2639 requires that only the elements *below* the current
2640 index have been copied before the throw. */
2642 for (i = len - 1; i >= 0; i--) {
2643 java_handle_t *o = oas->data[srcStart + i];
2645 if (!builtin_canstore(oad, o))
2648 oad->data[destStart + i] = o;
2657 /* builtin_nanotime ************************************************************
2659 Return the current time in nanoseconds.
2661 *******************************************************************************/
2663 s8 builtin_nanotime(void)
2668 if (gettimeofday(&tv, NULL) == -1)
2669 vm_abort("gettimeofday failed: %s", strerror(errno));
2671 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2673 return usecs * 1000;
2677 /* builtin_currenttimemillis ***************************************************
2679 Return the current time in milliseconds.
2681 *******************************************************************************/
2683 s8 builtin_currenttimemillis(void)
2687 msecs = builtin_nanotime() / 1000 / 1000;
2693 /* builtin_clone ***************************************************************
2695 Function for cloning objects or arrays.
2697 *******************************************************************************/
2699 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2701 arraydescriptor *ad;
2705 java_handle_t *co; /* cloned object header */
2707 /* get the array descriptor */
2709 ad = o->vftbl->arraydesc;
2711 /* we are cloning an array */
2714 ah = (java_handle_t *) o;
2716 size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah);
2718 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2723 MCOPY(co, o, u1, size);
2725 #if defined(ENABLE_GC_CACAO)
2726 heap_init_objectheader(co, size);
2729 #if defined(ENABLE_THREADS)
2730 lock_init_object_lock(co);
2736 /* we are cloning a non-array */
2738 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2739 exceptions_throw_clonenotsupportedexception();
2743 /* get the class of the object */
2745 c = o->vftbl->class;
2747 /* create new object */
2749 co = builtin_new(c);
2754 MCOPY(co, o, u1, c->instancesize);
2756 #if defined(ENABLE_GC_CACAO)
2757 heap_init_objectheader(co, c->instancesize);
2760 #if defined(ENABLE_THREADS)
2761 lock_init_object_lock(co);
2767 #if defined(ENABLE_VMLOG)
2769 #include <vmlog_cacao.c>
2774 * These are local overrides for various environment variables in Emacs.
2775 * Please do not remove this and leave it at the end of the file, where
2776 * Emacs will automagically detect them.
2777 * ---------------------------------------------------------------------
2780 * indent-tabs-mode: t
2784 * vim:noexpandtab:sw=4:ts=4: