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 8277 2007-08-08 16:42:11Z michi $
49 #include "fdlibm/fdlibm.h"
50 #if defined(__CYGWIN__) && defined(Bias)
54 #include "mm/gc-common.h"
55 #include "mm/memory.h"
57 #include "native/jni.h"
58 #include "native/include/java_lang_String.h"
59 #include "native/include/java_lang_Throwable.h"
61 #include "threads/lock-common.h"
63 #include "toolbox/logging.h"
64 #include "toolbox/util.h"
66 #include "vm/builtin.h"
67 #include "vm/cycles-stats.h"
68 #include "vm/exceptions.h"
69 #include "vm/global.h"
70 #include "vm/initialize.h"
71 #include "vm/stringlocal.h"
73 #include "vm/jit/asmpart.h"
75 #include "vmcore/class.h"
76 #include "vmcore/linker.h"
77 #include "vmcore/loader.h"
78 #include "vmcore/options.h"
79 #include "vmcore/primitive.h"
80 #include "vmcore/rt-timing.h"
82 #if defined(ENABLE_VMLOG)
83 #include <vmlog_cacao.h>
86 #if defined(ENABLE_DEBUG_FILTER)
87 # include "vm/jit/show.h"
90 /* include builtin tables *****************************************************/
92 #include "vm/builtintable.inc"
95 CYCLES_STATS_DECLARE(builtin_new ,100,5)
96 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
98 /* builtintable_init ***********************************************************
100 Parse the descriptors of builtin functions and create the parsed
103 *******************************************************************************/
105 static bool builtintable_init(void)
107 descriptor_pool *descpool;
109 builtintable_entry *bte;
111 /* mark start of dump memory area */
113 dumpsize = dump_size();
115 /* create a new descriptor pool */
117 descpool = descriptor_pool_new(class_java_lang_Object);
119 /* add some entries we need */
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
124 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
127 /* first add all descriptors to the pool */
129 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
130 /* create a utf8 string from descriptor */
132 bte->descriptor = utf_new_char(bte->cdescriptor);
134 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
135 /* release dump area */
137 dump_release(dumpsize);
143 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
144 bte->descriptor = utf_new_char(bte->cdescriptor);
146 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
147 dump_release(dumpsize);
152 for (bte = builtintable_function; bte->fp != NULL; bte++) {
153 bte->classname = utf_new_char(bte->cclassname);
154 bte->name = utf_new_char(bte->cname);
155 bte->descriptor = utf_new_char(bte->cdescriptor);
157 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
158 dump_release(dumpsize);
163 /* create the class reference table */
165 (void) descriptor_pool_create_classrefs(descpool, NULL);
167 /* allocate space for the parsed descriptors */
169 descriptor_pool_alloc_parsed_descriptors(descpool);
171 /* Now parse all descriptors. NOTE: builtin-functions are treated
172 like static methods (no `this' pointer). */
174 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
176 descriptor_pool_parse_method_descriptor(descpool,
178 ACC_STATIC | ACC_METHOD_BUILTIN,
182 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
184 descriptor_pool_parse_method_descriptor(descpool,
186 ACC_STATIC | ACC_METHOD_BUILTIN,
190 for (bte = builtintable_function; bte->fp != NULL; bte++) {
192 descriptor_pool_parse_method_descriptor(descpool,
194 ACC_STATIC | ACC_METHOD_BUILTIN,
198 /* release dump area */
200 dump_release(dumpsize);
206 /* builtintable_comparator *****************************************************
208 qsort comparator for the automatic builtin table.
210 *******************************************************************************/
212 static int builtintable_comparator(const void *a, const void *b)
214 builtintable_entry *bte1;
215 builtintable_entry *bte2;
217 bte1 = (builtintable_entry *) a;
218 bte2 = (builtintable_entry *) b;
220 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
224 /* builtintable_sort_automatic *************************************************
226 Sorts the automatic builtin table.
228 *******************************************************************************/
230 static void builtintable_sort_automatic(void)
234 /* calculate table size statically (`- 1' comment see builtintable.inc) */
236 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
238 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
239 builtintable_comparator);
243 /* builtin_init ****************************************************************
245 Initialize the global table of builtin functions.
247 *******************************************************************************/
249 bool builtin_init(void)
251 /* initialize the builtin tables */
253 if (!builtintable_init())
256 /* sort builtin tables */
258 builtintable_sort_automatic();
264 /* builtintable_get_internal ***************************************************
266 Finds an entry in the builtintable for internal functions and
267 returns the a pointer to the structure.
269 *******************************************************************************/
271 builtintable_entry *builtintable_get_internal(functionptr fp)
273 builtintable_entry *bte;
275 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
284 /* builtintable_get_automatic **************************************************
286 Finds an entry in the builtintable for functions which are replaced
287 automatically and returns the a pointer to the structure.
289 *******************************************************************************/
291 builtintable_entry *builtintable_get_automatic(s4 opcode)
293 builtintable_entry *first;
294 builtintable_entry *last;
295 builtintable_entry *middle;
299 /* calculate table size statically (`- 1' comment see builtintable.inc) */
301 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
303 first = builtintable_automatic;
304 last = builtintable_automatic + entries;
306 while (entries > 0) {
308 middle = first + half;
310 if (middle->opcode < opcode) {
317 return (first != last ? first : NULL);
321 /* builtintable_replace_function ***********************************************
325 *******************************************************************************/
327 #if defined(ENABLE_JIT)
328 bool builtintable_replace_function(void *iptr_)
331 builtintable_entry *bte;
334 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
336 /* get name and descriptor of the function */
339 case ICMD_INVOKESTATIC:
340 /* The instruction MUST be resolved, otherwise we run into
341 lazy loading troubles. Anyway, we should/can only replace
342 very VM-close functions. */
344 if (INSTRUCTION_IS_UNRESOLVED(iptr))
347 mr = iptr->sx.s23.s3.fmiref;
354 /* search the function table */
356 for (bte = builtintable_function; bte->fp != NULL; bte++) {
357 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
358 (mr->name == bte->name) &&
359 (mr->descriptor == bte->descriptor)) {
361 /* set the values in the instruction */
363 iptr->opc = bte->opcode;
364 iptr->sx.s23.s3.bte = bte;
365 if (bte->checkexception)
366 iptr->flags.bits |= INS_FLAG_CHECK;
368 iptr->flags.bits &= ~INS_FLAG_CHECK;
376 #endif /* defined(ENABLE_JIT) */
379 /*****************************************************************************
381 *****************************************************************************/
383 /* builtin_instanceof **********************************************************
385 Checks if an object is an instance of some given class (or subclass
386 of that class). If class is an interface, checks if the interface
389 Return value: 1 ... o is an instance of class or implements the interface
390 0 ... otherwise or if o == NULL
392 *******************************************************************************/
394 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
399 return class_isanysubclass(o->vftbl->class, class);
404 /* builtin_checkcast ***********************************************************
406 The same as builtin_instanceof except that 1 is returned when o ==
409 *******************************************************************************/
411 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
416 if (class_isanysubclass(o->vftbl->class, class))
423 /* builtin_descriptorscompatible ***********************************************
425 Checks if two array type descriptors are assignment compatible
427 Return value: 1 ... target = desc is possible
430 *******************************************************************************/
432 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
433 arraydescriptor *target)
438 if (desc->arraytype != target->arraytype)
441 if (desc->arraytype != ARRAYTYPE_OBJECT)
444 /* {both arrays are arrays of references} */
446 if (desc->dimension == target->dimension) {
447 /* an array which contains elements of interface types is
448 allowed to be casted to Object (JOWENN)*/
450 if ((desc->elementvftbl->baseval < 0) &&
451 (target->elementvftbl->baseval == 1))
454 return class_isanysubclass(desc->elementvftbl->class,
455 target->elementvftbl->class);
458 if (desc->dimension < target->dimension)
461 /* {desc has higher dimension than target} */
463 return class_isanysubclass(pseudo_class_Arraystub,
464 target->elementvftbl->class);
468 /* builtin_arraycheckcast ******************************************************
470 Checks if an object is really a subtype of the requested array
471 type. The object has to be an array to begin with. For simple
472 arrays (int, short, double, etc.) the types have to match exactly.
473 For arrays of objects, the type of elements in the array has to be
474 a subtype (or the same type) of the requested element type. For
475 arrays of arrays (which in turn can again be arrays of arrays), the
476 types at the lowest level have to satisfy the corresponding sub
479 *******************************************************************************/
481 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
483 arraydescriptor *desc;
488 desc = o->vftbl->arraydesc;
493 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
497 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
502 return builtin_arraycheckcast(o, targetclass);
506 /* builtin_throw_exception *****************************************************
508 Sets the exceptionptr with the thrown exception and prints some
509 debugging information. Called from asm_vm_call_method.
511 *******************************************************************************/
513 void *builtin_throw_exception(java_objectheader *xptr)
516 java_lang_Throwable *t;
522 t = (java_lang_Throwable *) xptr;
524 /* calculate message length */
526 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
530 utf_bytes(xptr->vftbl->class->name);
531 if (t->detailMessage) {
532 logtextlen += strlen(": ") +
533 u2_utflength(t->detailMessage->value->data
534 + t->detailMessage->offset,
535 t->detailMessage->count);
539 logtextlen += strlen("(nil)");
542 /* allocate memory */
544 dumpsize = dump_size();
546 logtext = DMNEW(char, logtextlen);
548 strcpy(logtext, "Builtin exception thrown: ");
551 utf_cat_classname(logtext, xptr->vftbl->class->name);
553 if (t->detailMessage) {
556 buf = javastring_tochar((java_objectheader *) t->detailMessage);
557 strcat(logtext, ": ");
558 strcat(logtext, buf);
559 MFREE(buf, char, strlen(buf) + 1);
563 strcat(logtext, "(nil)");
570 dump_release(dumpsize);
572 #endif /* !defined(NDEBUG) */
574 /* actually set the exception */
576 exceptions_set_exception(xptr);
578 /* Return a NULL pointer. This is required for vm_call_method to
579 check for an exception. This is for convenience. */
585 /* builtin_canstore ************************************************************
587 Checks, if an object can be stored in an array.
589 Return value: 1 ... possible
590 0 ... otherwise (throws an ArrayStoreException)
592 *******************************************************************************/
594 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
596 arraydescriptor *desc;
597 arraydescriptor *valuedesc;
598 vftbl_t *componentvftbl;
607 /* The following is guaranteed (by verifier checks):
609 * *) oa->...vftbl->arraydesc != NULL
610 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
611 * *) o->vftbl is not an interface vftbl
614 desc = oa->header.objheader.vftbl->arraydesc;
615 componentvftbl = desc->componentvftbl;
616 valuevftbl = o->vftbl;
617 valuedesc = valuevftbl->arraydesc;
619 if ((desc->dimension - 1) == 0) {
620 /* {oa is a one-dimensional array} */
621 /* {oa is an array of references} */
623 if (valuevftbl == componentvftbl)
626 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
628 baseval = componentvftbl->baseval;
631 /* an array of interface references */
633 result = ((valuevftbl->interfacetablelength > -baseval) &&
634 (valuevftbl->interfacetable[baseval] != NULL));
637 diffval = valuevftbl->baseval - componentvftbl->baseval;
638 result = diffval <= (uint32_t) componentvftbl->diffval;
641 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
643 else if (valuedesc == NULL) {
644 /* {oa has dimension > 1} */
645 /* {componentvftbl->arraydesc != NULL} */
647 /* check if o is an array */
652 /* {o is an array} */
654 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
657 /* if not possible, throw an exception */
660 exceptions_throw_arraystoreexception();
668 /* This is an optimized version where a is guaranteed to be one-dimensional */
669 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
671 arraydescriptor *desc;
672 vftbl_t *elementvftbl;
681 /* The following is guaranteed (by verifier checks):
683 * *) a->...vftbl->arraydesc != NULL
684 * *) a->...vftbl->arraydesc->elementvftbl != NULL
685 * *) a->...vftbl->arraydesc->dimension == 1
686 * *) o->vftbl is not an interface vftbl
689 desc = a->header.objheader.vftbl->arraydesc;
690 elementvftbl = desc->elementvftbl;
691 valuevftbl = o->vftbl;
693 /* {a is a one-dimensional array} */
695 if (valuevftbl == elementvftbl)
698 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
700 baseval = elementvftbl->baseval;
703 /* an array of interface references */
704 result = ((valuevftbl->interfacetablelength > -baseval) &&
705 (valuevftbl->interfacetable[baseval] != NULL));
708 diffval = valuevftbl->baseval - elementvftbl->baseval;
709 result = diffval <= (uint32_t) elementvftbl->diffval;
712 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
718 /* This is an optimized version where a is guaranteed to be a
719 * one-dimensional array of a class type */
720 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
722 vftbl_t *elementvftbl;
730 /* The following is guaranteed (by verifier checks):
732 * *) a->...vftbl->arraydesc != NULL
733 * *) a->...vftbl->arraydesc->elementvftbl != NULL
734 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
735 * *) a->...vftbl->arraydesc->dimension == 1
736 * *) o->vftbl is not an interface vftbl
739 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
740 valuevftbl = o->vftbl;
742 /* {a is a one-dimensional array} */
744 if (valuevftbl == elementvftbl)
747 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
749 diffval = valuevftbl->baseval - elementvftbl->baseval;
750 result = diffval <= (uint32_t) elementvftbl->diffval;
752 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
758 /* builtin_new *****************************************************************
760 Creates a new instance of class c on the heap.
762 Return value: pointer to the object or NULL if no memory is
765 *******************************************************************************/
767 java_objectheader *builtin_new(classinfo *c)
769 java_objectheader *o;
770 #if defined(ENABLE_RT_TIMING)
771 struct timespec time_start, time_end;
773 #if defined(ENABLE_CYCLES_STATS)
774 u8 cycles_start, cycles_end;
777 RT_TIMING_GET_TIME(time_start);
778 CYCLES_STATS_GET(cycles_start);
780 /* is the class loaded */
782 assert(c->state & CLASS_LOADED);
784 /* check if we can instantiate this class */
786 if (c->flags & ACC_ABSTRACT) {
787 exceptions_throw_instantiationerror(c);
791 /* is the class linked */
793 if (!(c->state & CLASS_LINKED))
797 if (!(c->state & CLASS_INITIALIZED)) {
800 log_message_class("Initialize class (from builtin_new): ", c);
803 if (!initialize_class(c))
807 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
815 #if defined(ENABLE_THREADS)
816 lock_init_object_lock(o);
819 CYCLES_STATS_GET(cycles_end);
820 RT_TIMING_GET_TIME(time_end);
822 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
823 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
829 /* builtin_newarray ************************************************************
831 Creates an array with the given vftbl on the heap. This function
832 takes as class argument an array class.
834 Return value: pointer to the array or NULL if no memory is available
836 *******************************************************************************/
838 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
840 arraydescriptor *desc;
845 #if defined(ENABLE_RT_TIMING)
846 struct timespec time_start, time_end;
849 RT_TIMING_GET_TIME(time_start);
851 desc = arrayclass->vftbl->arraydesc;
852 dataoffset = desc->dataoffset;
853 componentsize = desc->componentsize;
856 exceptions_throw_negativearraysizeexception();
860 actualsize = dataoffset + size * componentsize;
862 /* check for overflow */
864 if (((u4) actualsize) < ((u4) size)) {
865 exceptions_throw_outofmemoryerror();
869 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
874 a->objheader.vftbl = arrayclass->vftbl;
876 #if defined(ENABLE_THREADS)
877 lock_init_object_lock(&a->objheader);
882 RT_TIMING_GET_TIME(time_end);
883 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
889 /* builtin_anewarray ***********************************************************
891 Creates an array of references to the given class type on the heap.
893 Return value: pointer to the array or NULL if no memory is
896 *******************************************************************************/
898 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
900 classinfo *arrayclass;
902 /* is class loaded */
904 assert(componentclass->state & CLASS_LOADED);
906 /* is class linked */
908 if (!(componentclass->state & CLASS_LINKED))
909 if (!link_class(componentclass))
912 arrayclass = class_array_of(componentclass, true);
917 return (java_objectarray *) builtin_newarray(size, arrayclass);
921 /* builtin_newarray_boolean ****************************************************
923 Creates an array of bytes on the heap. The array is designated as
924 an array of booleans (important for casts)
926 Return value: pointer to the array or NULL if no memory is
929 *******************************************************************************/
931 java_booleanarray *builtin_newarray_boolean(s4 size)
933 return (java_booleanarray *)
934 builtin_newarray(size,
935 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
939 /* builtin_newarray_byte *******************************************************
941 Creates an array of 8 bit Integers on the heap.
943 Return value: pointer to the array or NULL if no memory is
946 *******************************************************************************/
948 java_bytearray *builtin_newarray_byte(s4 size)
950 return (java_bytearray *)
951 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
955 /* builtin_newarray_char *******************************************************
957 Creates an array of characters on the heap.
959 Return value: pointer to the array or NULL if no memory is
962 *******************************************************************************/
964 java_chararray *builtin_newarray_char(s4 size)
966 return (java_chararray *)
967 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
971 /* builtin_newarray_short ******************************************************
973 Creates an array of 16 bit Integers on the heap.
975 Return value: pointer to the array or NULL if no memory is
978 *******************************************************************************/
980 java_shortarray *builtin_newarray_short(s4 size)
982 return (java_shortarray *)
983 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
987 /* builtin_newarray_int ********************************************************
989 Creates an array of 32 bit Integers on the heap.
991 Return value: pointer to the array or NULL if no memory is
994 *******************************************************************************/
996 java_intarray *builtin_newarray_int(s4 size)
998 return (java_intarray *)
999 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1003 /* builtin_newarray_long *******************************************************
1005 Creates an array of 64 bit Integers on the heap.
1007 Return value: pointer to the array or NULL if no memory is
1010 *******************************************************************************/
1012 java_longarray *builtin_newarray_long(s4 size)
1014 return (java_longarray *)
1015 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1019 /* builtin_newarray_float ******************************************************
1021 Creates an array of 32 bit IEEE floats on the heap.
1023 Return value: pointer to the array or NULL if no memory is
1026 *******************************************************************************/
1028 java_floatarray *builtin_newarray_float(s4 size)
1030 return (java_floatarray *)
1031 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1035 /* builtin_newarray_double *****************************************************
1037 Creates an array of 64 bit IEEE floats on the heap.
1039 Return value: pointer to the array or NULL if no memory is
1042 *******************************************************************************/
1044 java_doublearray *builtin_newarray_double(s4 size)
1046 return (java_doublearray *)
1047 builtin_newarray(size,
1048 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1052 /* builtin_multianewarray_intern ***********************************************
1054 Creates a multi-dimensional array on the heap. The dimensions are
1055 passed in an array of longs.
1058 n.............number of dimensions to create
1059 arrayclass....the array class
1060 dims..........array containing the size of each dimension to create
1062 Return value: pointer to the array or NULL if no memory is
1065 ******************************************************************************/
1067 static java_arrayheader *builtin_multianewarray_intern(int n,
1068 classinfo *arrayclass,
1072 java_arrayheader *a;
1073 classinfo *componentclass;
1076 /* create this dimension */
1078 size = (s4) dims[0];
1079 a = builtin_newarray(size, arrayclass);
1084 /* if this is the last dimension return */
1089 /* get the class of the components to create */
1091 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1093 /* The verifier guarantees that the dimension count is in the range. */
1095 /* create the component arrays */
1097 for (i = 0; i < size; i++) {
1098 java_arrayheader *ea =
1099 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1100 /* we save an s4 to a s8 slot, 8-byte aligned */
1102 builtin_multianewarray_intern(n, componentclass, dims + 2);
1104 builtin_multianewarray_intern(n, componentclass, dims + 1);
1110 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1117 /* builtin_multianewarray ******************************************************
1119 Wrapper for builtin_multianewarray_intern which checks all
1120 dimensions before we start allocating.
1122 ******************************************************************************/
1124 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1130 /* check all dimensions before doing anything */
1132 for (i = 0; i < n; i++) {
1133 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1134 /* we save an s4 to a s8 slot, 8-byte aligned */
1135 size = (s4) dims[i * 2];
1137 size = (s4) dims[i];
1141 exceptions_throw_negativearraysizeexception();
1146 /* now call the real function */
1148 return builtin_multianewarray_intern(n, arrayclass, dims);
1152 /*****************************************************************************
1155 Various functions for printing a message at method entry or exit (for
1158 *****************************************************************************/
1160 #if !defined(NDEBUG)
1161 static s4 methodindent = 0;
1162 static u4 callcount = 0;
1164 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1174 #if defined(ENABLE_DEBUG_FILTER)
1175 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1178 #if defined(ENABLE_VMLOG)
1182 if (opt_verbosecall && indent)
1185 /* calculate message length */
1189 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1192 logtextlen = strlen("Some Throwable");
1195 logtextlen += strlen(" thrown in ");
1199 utf_bytes(m->class->name) +
1201 utf_bytes(m->name) +
1202 utf_bytes(m->descriptor) +
1203 strlen("(NOSYNC,NATIVE");
1205 #if SIZEOF_VOID_P == 8
1207 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1209 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1212 if (m->class->sourcefile == NULL)
1213 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1215 logtextlen += utf_bytes(m->class->sourcefile);
1217 logtextlen += strlen(":65536)");
1221 logtextlen += strlen("call_java_method");
1224 logtextlen += strlen("0");
1226 /* allocate memory */
1228 dumpsize = dump_size();
1230 logtext = DMNEW(char, logtextlen);
1233 strcpy(logtext, "Exception ");
1234 utf_cat_classname(logtext, xptr->vftbl->class->name);
1237 strcpy(logtext, "Some Throwable");
1240 strcat(logtext, " thrown in ");
1243 utf_cat_classname(logtext, m->class->name);
1244 strcat(logtext, ".");
1245 utf_cat(logtext, m->name);
1246 utf_cat(logtext, m->descriptor);
1248 if (m->flags & ACC_SYNCHRONIZED)
1249 strcat(logtext, "(SYNC");
1251 strcat(logtext, "(NOSYNC");
1253 if (m->flags & ACC_NATIVE) {
1254 strcat(logtext, ",NATIVE");
1258 #if SIZEOF_VOID_P == 8
1259 sprintf(logtext + strlen(logtext),
1260 ")(0x%016lx) at position 0x%016lx",
1261 (ptrint) code->entrypoint, (ptrint) pos);
1263 sprintf(logtext + strlen(logtext),
1264 ")(0x%08x) at position 0x%08x",
1265 (ptrint) code->entrypoint, (ptrint) pos);
1270 /* XXX preliminary: This should get the actual codeinfo */
1271 /* in which the exception happened. */
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);
1284 if (m->class->sourcefile == NULL)
1285 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1287 utf_cat(logtext, m->class->sourcefile);
1289 sprintf(logtext + strlen(logtext), ":%d)", 0);
1293 strcat(logtext, "call_java_method");
1297 /* release memory */
1299 dump_release(dumpsize);
1303 #endif /* !defined(NDEBUG) */
1306 /* builtin_print_argument ******************************************************
1308 Prints arguments and return values for the call trace.
1310 *******************************************************************************/
1312 #if !defined(NDEBUG)
1313 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1314 typedesc *paramtype, s8 value)
1317 java_objectheader *o;
1322 switch (paramtype->type) {
1325 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1330 #if SIZEOF_VOID_P == 4
1331 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1333 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1338 #if defined(__S390__)
1340 /* The below won't work on S390 */
1344 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1349 #if SIZEOF_VOID_P == 4
1350 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1352 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1357 #if SIZEOF_VOID_P == 4
1358 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1360 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1363 /* cast to java.lang.Object */
1365 o = (java_objectheader *) (ptrint) value;
1367 /* check return argument for java.lang.Class or java.lang.String */
1370 if (o->vftbl->class == class_java_lang_String) {
1371 /* get java.lang.String object and the length of the
1374 u = javastring_toutf(o, false);
1376 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1378 /* realloc memory for string length */
1380 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1383 /* convert to utf8 string and strcat it to the logtext */
1385 strcat(logtext, " (String = \"");
1386 utf_cat(logtext, u);
1387 strcat(logtext, "\")");
1390 if (o->vftbl->class == class_java_lang_Class) {
1391 /* if the object returned is a java.lang.Class
1392 cast it to classinfo structure and get the name
1395 c = (classinfo *) o;
1400 /* if the object returned is not a java.lang.String or
1401 a java.lang.Class just print the name of the class */
1403 u = o->vftbl->class->name;
1406 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1408 /* realloc memory for string length */
1410 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1413 /* strcat to the logtext */
1415 strcat(logtext, " (Class = \"");
1416 utf_cat_classname(logtext, u);
1417 strcat(logtext, "\")");
1424 #endif /* !defined(NDEBUG) */
1426 /* builtin_verbosecall_enter ***************************************************
1428 Print method call with arguments for -verbose:call.
1430 *******************************************************************************/
1432 #if !defined(NDEBUG)
1434 #ifdef TRACE_ARGS_NUM
1435 void builtin_verbosecall_enter(s8 a0, s8 a1,
1436 # if TRACE_ARGS_NUM >= 4
1439 # if TRACE_ARGS_NUM >= 6
1442 # if TRACE_ARGS_NUM == 8
1454 #if defined(ENABLE_DEBUG_FILTER)
1455 if (! show_filters_test_verbosecall_enter(m)) return;
1458 #if defined(ENABLE_VMLOG)
1459 vmlog_cacao_enter_method(m);
1465 /* calculate message length */
1468 strlen("4294967295 ") +
1469 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1471 strlen("called: ") +
1472 utf_bytes(m->class->name) +
1474 utf_bytes(m->name) +
1475 utf_bytes(m->descriptor);
1477 /* Actually it's not possible to have all flags printed, but:
1482 strlen(" PRIVATE") +
1483 strlen(" PROTECTED") +
1486 strlen(" SYNCHRONIZED") +
1487 strlen(" VOLATILE") +
1488 strlen(" TRANSIENT") +
1490 strlen(" INTERFACE") +
1491 strlen(" ABSTRACT");
1493 /* add maximal argument length */
1497 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1498 strlen("...(255)") +
1501 /* allocate memory */
1503 dumpsize = dump_size();
1505 logtext = DMNEW(char, logtextlen);
1509 sprintf(logtext, "%10d ", callcount);
1510 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1512 pos = strlen(logtext);
1514 for (i = 0; i < methodindent; i++)
1515 logtext[pos++] = '\t';
1517 strcpy(logtext + pos, "called: ");
1519 utf_cat_classname(logtext, m->class->name);
1520 strcat(logtext, ".");
1521 utf_cat(logtext, m->name);
1522 utf_cat(logtext, m->descriptor);
1524 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1525 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1526 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1527 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1528 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1529 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1530 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1531 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1532 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1533 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1534 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1536 strcat(logtext, "(");
1538 if (md->paramcount >= 1) {
1539 logtext = builtin_print_argument(logtext, &logtextlen,
1540 &md->paramtypes[0], a0);
1543 if (md->paramcount >= 2) {
1544 strcat(logtext, ", ");
1546 logtext = builtin_print_argument(logtext, &logtextlen,
1547 &md->paramtypes[1], a1);
1550 #if TRACE_ARGS_NUM >= 4
1551 if (md->paramcount >= 3) {
1552 strcat(logtext, ", ");
1554 logtext = builtin_print_argument(logtext, &logtextlen,
1555 &md->paramtypes[2], a2);
1558 if (md->paramcount >= 4) {
1559 strcat(logtext, ", ");
1561 logtext = builtin_print_argument(logtext, &logtextlen,
1562 &md->paramtypes[3], a3);
1566 #if TRACE_ARGS_NUM >= 6
1567 if (md->paramcount >= 5) {
1568 strcat(logtext, ", ");
1570 logtext = builtin_print_argument(logtext, &logtextlen,
1571 &md->paramtypes[4], a4);
1574 if (md->paramcount >= 6) {
1575 strcat(logtext, ", ");
1577 logtext = builtin_print_argument(logtext, &logtextlen,
1578 &md->paramtypes[5], a5);
1582 #if TRACE_ARGS_NUM == 8
1583 if (md->paramcount >= 7) {
1584 strcat(logtext, ", ");
1586 logtext = builtin_print_argument(logtext, &logtextlen,
1587 &md->paramtypes[6], a6);
1590 if (md->paramcount >= 8) {
1591 strcat(logtext, ", ");
1593 logtext = builtin_print_argument(logtext, &logtextlen,
1594 &md->paramtypes[7], a7);
1598 if (md->paramcount > 8) {
1599 sprintf(logtext + strlen(logtext), ", ...(%d)",
1600 md->paramcount - TRACE_ARGS_NUM);
1603 strcat(logtext, ")");
1607 /* release memory */
1609 dump_release(dumpsize);
1615 #endif /* !defined(NDEBUG) */
1618 /* builtin_verbosecall_exit ****************************************************
1620 Print method exit for -verbose:call.
1622 *******************************************************************************/
1624 #if !defined(NDEBUG)
1625 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1635 #if defined(ENABLE_DEBUG_FILTER)
1636 if (! show_filters_test_verbosecall_exit(m)) return;
1639 #if defined(ENABLE_VMLOG)
1640 vmlog_cacao_leave_method(m);
1646 /* calculate message length */
1649 strlen("4294967295 ") +
1650 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1652 strlen("finished: ") +
1653 utf_bytes(m->class->name) +
1655 utf_bytes(m->name) +
1656 utf_bytes(m->descriptor) +
1657 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1659 /* add maximal argument length */
1661 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1663 /* allocate memory */
1665 dumpsize = dump_size();
1667 logtext = DMNEW(char, logtextlen);
1669 /* outdent the log message */
1674 log_text("WARNING: unmatched methodindent--");
1676 /* generate the message */
1678 sprintf(logtext, " ");
1679 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1681 pos = strlen(logtext);
1683 for (i = 0; i < methodindent; i++)
1684 logtext[pos++] = '\t';
1686 strcpy(logtext + pos, "finished: ");
1687 utf_cat_classname(logtext, m->class->name);
1688 strcat(logtext, ".");
1689 utf_cat(logtext, m->name);
1690 utf_cat(logtext, m->descriptor);
1692 if (!IS_VOID_TYPE(md->returntype.type)) {
1693 strcat(logtext, "->");
1695 switch (md->returntype.type) {
1712 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1717 /* release memory */
1719 dump_release(dumpsize);
1722 #endif /* !defined(NDEBUG) */
1725 #if defined(ENABLE_CYCLES_STATS)
1726 void builtin_print_cycles_stats(FILE *file)
1728 fprintf(file,"builtin cylce count statistics:\n");
1730 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1731 CYCLES_STATS_PRINT(builtin_new ,file);
1735 #endif /* defined(ENABLE_CYCLES_STATS) */
1738 /*****************************************************************************
1739 MISCELLANEOUS HELPER FUNCTIONS
1740 *****************************************************************************/
1744 /*********** Functions for integer divisions *****************************
1746 On some systems (eg. DEC ALPHA), integer division is not supported by the
1747 CPU. These helper functions implement the missing functionality.
1749 ******************************************************************************/
1751 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1752 s4 builtin_idiv(s4 a, s4 b)
1761 s4 builtin_irem(s4 a, s4 b)
1769 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1772 /* functions for long arithmetics **********************************************
1774 On systems where 64 bit Integers are not supported by the CPU,
1775 these functions are needed.
1777 ******************************************************************************/
1779 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1780 s8 builtin_ladd(s8 a, s8 b)
1793 s8 builtin_lsub(s8 a, s8 b)
1806 s8 builtin_lneg(s8 a)
1818 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1821 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1822 s8 builtin_lmul(s8 a, s8 b)
1834 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1837 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1838 s8 builtin_ldiv(s8 a, s8 b)
1851 s8 builtin_lrem(s8 a, s8 b)
1863 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1866 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1867 s8 builtin_lshl(s8 a, s4 b)
1880 s8 builtin_lshr(s8 a, s4 b)
1893 s8 builtin_lushr(s8 a, s4 b)
1898 c = ((u8) a) >> (b & 63);
1905 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1908 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1909 s8 builtin_land(s8 a, s8 b)
1922 s8 builtin_lor(s8 a, s8 b)
1935 s8 builtin_lxor(s8 a, s8 b)
1947 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1950 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1951 s4 builtin_lcmp(s8 a, s8 b)
1965 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1968 /* functions for unsupported floating instructions ****************************/
1970 /* used to convert FLT_xxx defines into float values */
1972 static inline float intBitsToFloat(s4 i)
1981 /* used to convert DBL_xxx defines into double values */
1983 static inline float longBitsToDouble(s8 l)
1993 float builtin_fadd(float a, float b)
1995 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1996 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2007 if (copysignf(1.0, a) == copysignf(1.0, b))
2010 return intBitsToFloat(FLT_NAN);
2016 float builtin_fsub(float a, float b)
2018 return builtin_fadd(a, builtin_fneg(b));
2022 float builtin_fmul(float a, float b)
2024 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2025 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2027 if (finitef(b)) return a * b;
2029 if (a == 0) return intBitsToFloat(FLT_NAN);
2030 else return copysignf(b, copysignf(1.0, b)*a);
2035 if (b == 0) return intBitsToFloat(FLT_NAN);
2036 else return copysignf(a, copysignf(1.0, a)*b);
2039 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2045 /* builtin_ddiv ****************************************************************
2047 Implementation as described in VM Spec.
2049 *******************************************************************************/
2051 float builtin_fdiv(float a, float b)
2055 /* If neither value1' nor value2' is NaN, the sign of the result */
2056 /* is positive if both values have the same sign, negative if the */
2057 /* values have different signs. */
2063 /* If either value1' or value2' is NaN, the result is NaN. */
2065 return intBitsToFloat(FLT_NAN);
2068 /* Division of a finite value by an infinity results in a */
2069 /* signed zero, with the sign-producing rule just given. */
2071 /* is sign equal? */
2073 if (copysignf(1.0, a) == copysignf(1.0, b))
2082 /* If either value1' or value2' is NaN, the result is NaN. */
2084 return intBitsToFloat(FLT_NAN);
2086 } else if (finitef(b)) {
2087 /* Division of an infinity by a finite value results in a signed */
2088 /* infinity, with the sign-producing rule just given. */
2090 /* is sign equal? */
2092 if (copysignf(1.0, a) == copysignf(1.0, b))
2093 return intBitsToFloat(FLT_POSINF);
2095 return intBitsToFloat(FLT_NEGINF);
2098 /* Division of an infinity by an infinity results in NaN. */
2100 return intBitsToFloat(FLT_NAN);
2106 float builtin_fneg(float a)
2108 if (isnanf(a)) return a;
2110 if (finitef(a)) return -a;
2111 else return copysignf(a, -copysignf(1.0, a));
2114 #endif /* !SUPPORT_FLOAT */
2117 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2118 s4 builtin_fcmpl(float a, float b)
2126 if (!finitef(a) || !finitef(b)) {
2127 a = finitef(a) ? 0 : copysignf(1.0, a);
2128 b = finitef(b) ? 0 : copysignf(1.0, b);
2141 s4 builtin_fcmpg(float a, float b)
2143 if (isnanf(a)) return 1;
2144 if (isnanf(b)) return 1;
2145 if (!finitef(a) || !finitef(b)) {
2146 a = finitef(a) ? 0 : copysignf(1.0, a);
2147 b = finitef(b) ? 0 : copysignf(1.0, b);
2149 if (a > b) return 1;
2150 if (a == b) return 0;
2153 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2156 float builtin_frem(float a, float b)
2162 /* functions for unsupported double instructions ******************************/
2165 double builtin_dadd(double a, double b)
2167 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2168 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2170 if (finite(b)) return a + b;
2174 if (finite(b)) return a;
2176 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2177 else return longBitsToDouble(DBL_NAN);
2183 double builtin_dsub(double a, double b)
2185 return builtin_dadd(a, builtin_dneg(b));
2189 double builtin_dmul(double a, double b)
2191 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2192 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2194 if (finite(b)) return a * b;
2196 if (a == 0) return longBitsToDouble(DBL_NAN);
2197 else return copysign(b, copysign(1.0, b) * a);
2202 if (b == 0) return longBitsToDouble(DBL_NAN);
2203 else return copysign(a, copysign(1.0, a) * b);
2206 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2212 /* builtin_ddiv ****************************************************************
2214 Implementation as described in VM Spec.
2216 *******************************************************************************/
2218 double builtin_ddiv(double a, double b)
2222 /* If neither value1' nor value2' is NaN, the sign of the result */
2223 /* is positive if both values have the same sign, negative if the */
2224 /* values have different signs. */
2230 /* If either value1' or value2' is NaN, the result is NaN. */
2232 return longBitsToDouble(DBL_NAN);
2235 /* Division of a finite value by an infinity results in a */
2236 /* signed zero, with the sign-producing rule just given. */
2238 /* is sign equal? */
2240 if (copysign(1.0, a) == copysign(1.0, b))
2249 /* If either value1' or value2' is NaN, the result is NaN. */
2251 return longBitsToDouble(DBL_NAN);
2253 } else if (finite(b)) {
2254 /* Division of an infinity by a finite value results in a signed */
2255 /* infinity, with the sign-producing rule just given. */
2257 /* is sign equal? */
2259 if (copysign(1.0, a) == copysign(1.0, b))
2260 return longBitsToDouble(DBL_POSINF);
2262 return longBitsToDouble(DBL_NEGINF);
2265 /* Division of an infinity by an infinity results in NaN. */
2267 return longBitsToDouble(DBL_NAN);
2273 /* builtin_dneg ****************************************************************
2275 Implemented as described in VM Spec.
2277 *******************************************************************************/
2279 double builtin_dneg(double a)
2282 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2289 /* If the operand is a zero, the result is the zero of opposite */
2295 /* If the operand is an infinity, the result is the infinity of */
2296 /* opposite sign. */
2298 return copysign(a, -copysign(1.0, a));
2302 #endif /* !SUPPORT_DOUBLE */
2305 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2306 s4 builtin_dcmpl(double a, double b)
2314 if (!finite(a) || !finite(b)) {
2315 a = finite(a) ? 0 : copysign(1.0, a);
2316 b = finite(b) ? 0 : copysign(1.0, b);
2329 s4 builtin_dcmpg(double a, double b)
2337 if (!finite(a) || !finite(b)) {
2338 a = finite(a) ? 0 : copysign(1.0, a);
2339 b = finite(b) ? 0 : copysign(1.0, b);
2350 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2353 double builtin_drem(double a, double b)
2359 /* conversion operations ******************************************************/
2362 s8 builtin_i2l(s4 i)
2374 s4 builtin_l2i(s8 l)
2385 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2386 float builtin_i2f(s4 a)
2388 float f = (float) a;
2391 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2394 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2395 double builtin_i2d(s4 a)
2397 double d = (double) a;
2400 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2403 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2404 float builtin_l2f(s8 a)
2407 float f = (float) a;
2413 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2416 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2417 double builtin_l2d(s8 a)
2420 double d = (double) a;
2426 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2429 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2430 s4 builtin_f2i(float a)
2434 i = builtin_d2i((double) a);
2445 if (a < (-2147483648))
2446 return (-2147483648);
2449 f = copysignf((float) 1.0, a);
2452 return (-2147483648); */
2454 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2457 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2458 s8 builtin_f2l(float a)
2462 l = builtin_d2l((double) a);
2469 if (a > 9223372036854775807L)
2470 return 9223372036854775807L;
2471 if (a < (-9223372036854775808L))
2472 return (-9223372036854775808L);
2477 f = copysignf((float) 1.0, a);
2479 return 9223372036854775807L;
2480 return (-9223372036854775808L); */
2482 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2485 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2486 s4 builtin_d2i(double a)
2491 if (a >= 2147483647)
2493 if (a <= (-2147483647-1))
2494 return (-2147483647-1);
2499 d = copysign(1.0, a);
2502 return (-2147483647-1);
2504 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2507 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2508 s8 builtin_d2l(double a)
2513 if (a >= 9223372036854775807LL)
2514 return 9223372036854775807LL;
2515 if (a <= (-9223372036854775807LL-1))
2516 return (-9223372036854775807LL-1);
2521 d = copysign(1.0, a);
2523 return 9223372036854775807LL;
2524 return (-9223372036854775807LL-1);
2526 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2529 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2530 double builtin_f2d(float a)
2532 if (finitef(a)) return (double) a;
2535 return longBitsToDouble(DBL_NAN);
2537 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2541 float builtin_d2f(double a)
2547 return intBitsToFloat(FLT_NAN);
2549 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2552 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2555 /* builtin_arraycopy ***********************************************************
2557 Builtin for java.lang.System.arraycopy.
2559 ATTENTION: This builtin function returns a boolean value to signal
2560 the ICMD_BUILTIN if there was an exception.
2562 *******************************************************************************/
2564 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2565 java_arrayheader *dest, s4 destStart, s4 len)
2567 arraydescriptor *sdesc;
2568 arraydescriptor *ddesc;
2571 if ((src == NULL) || (dest == NULL)) {
2572 exceptions_throw_nullpointerexception();
2576 sdesc = src->objheader.vftbl->arraydesc;
2577 ddesc = dest->objheader.vftbl->arraydesc;
2579 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2580 exceptions_throw_arraystoreexception();
2584 /* we try to throw exception with the same message as SUN does */
2586 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2587 (srcStart + len < 0) || (srcStart + len > src->size) ||
2588 (destStart + len < 0) || (destStart + len > dest->size)) {
2589 exceptions_throw_arrayindexoutofboundsexception();
2593 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2594 /* We copy primitive values or references of exactly the same type */
2596 s4 dataoffset = sdesc->dataoffset;
2597 s4 componentsize = sdesc->componentsize;
2599 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2600 ((u1 *) src) + dataoffset + componentsize * srcStart,
2601 (size_t) len * componentsize);
2604 /* We copy references of different type */
2606 java_objectarray *oas = (java_objectarray *) src;
2607 java_objectarray *oad = (java_objectarray *) dest;
2609 if (destStart <= srcStart) {
2610 for (i = 0; i < len; i++) {
2611 java_objectheader *o = oas->data[srcStart + i];
2613 if (!builtin_canstore(oad, o))
2616 oad->data[destStart + i] = o;
2620 /* XXX this does not completely obey the specification!
2621 If an exception is thrown only the elements above the
2622 current index have been copied. The specification
2623 requires that only the elements *below* the current
2624 index have been copied before the throw. */
2626 for (i = len - 1; i >= 0; i--) {
2627 java_objectheader *o = oas->data[srcStart + i];
2629 if (!builtin_canstore(oad, o))
2632 oad->data[destStart + i] = o;
2641 /* builtin_nanotime ************************************************************
2643 Return the current time in nanoseconds.
2645 *******************************************************************************/
2647 s8 builtin_nanotime(void)
2652 if (gettimeofday(&tv, NULL) == -1)
2653 vm_abort("gettimeofday failed: %s", strerror(errno));
2655 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2657 return usecs * 1000;
2661 /* builtin_currenttimemillis ***************************************************
2663 Return the current time in milliseconds.
2665 *******************************************************************************/
2667 s8 builtin_currenttimemillis(void)
2671 msecs = builtin_nanotime() / 1000 / 1000;
2677 /* builtin_clone ***************************************************************
2679 Function for cloning objects or arrays.
2681 *******************************************************************************/
2683 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2685 arraydescriptor *ad;
2686 java_arrayheader *ah;
2689 java_objectheader *co; /* cloned object header */
2691 /* get the array descriptor */
2693 ad = o->vftbl->arraydesc;
2695 /* we are cloning an array */
2698 ah = (java_arrayheader *) o;
2700 size = ad->dataoffset + ad->componentsize * ah->size;
2702 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2707 MCOPY(co, o, u1, size);
2709 #if defined(ENABLE_GC_CACAO)
2710 heap_init_objectheader(co, size);
2713 #if defined(ENABLE_THREADS)
2714 lock_init_object_lock(co);
2720 /* we are cloning a non-array */
2722 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2723 exceptions_throw_clonenotsupportedexception();
2727 /* get the class of the object */
2729 c = o->vftbl->class;
2731 /* create new object */
2733 co = builtin_new(c);
2738 MCOPY(co, o, u1, c->instancesize);
2740 #if defined(ENABLE_GC_CACAO)
2741 heap_init_objectheader(co, c->instancesize);
2744 #if defined(ENABLE_THREADS)
2745 lock_init_object_lock(co);
2751 #if defined(ENABLE_VMLOG)
2753 #include <vmlog_cacao.c>
2758 * These are local overrides for various environment variables in Emacs.
2759 * Please do not remove this and leave it at the end of the file, where
2760 * Emacs will automagically detect them.
2761 * ---------------------------------------------------------------------
2764 * indent-tabs-mode: t
2768 * vim:noexpandtab:sw=4:ts=4: