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 8273 2007-08-08 15:33:15Z twisti $
49 #include "fdlibm/fdlibm.h"
50 #if defined(__CYGWIN__) && defined(Bias)
54 #include "mm/gc-common.h"
55 #include "mm/memory.h"
57 #include "native/jni.h"
58 #include "native/include/java_lang_String.h"
59 #include "native/include/java_lang_Throwable.h"
61 #include "threads/lock-common.h"
63 #include "toolbox/logging.h"
64 #include "toolbox/util.h"
66 #include "vm/builtin.h"
67 #include "vm/cycles-stats.h"
68 #include "vm/exceptions.h"
69 #include "vm/global.h"
70 #include "vm/initialize.h"
71 #include "vm/stringlocal.h"
73 #include "vm/jit/asmpart.h"
75 #include "vmcore/class.h"
76 #include "vmcore/loader.h"
77 #include "vmcore/options.h"
78 #include "vmcore/primitive.h"
79 #include "vmcore/rt-timing.h"
81 #if defined(ENABLE_VMLOG)
82 #include <vmlog_cacao.h>
85 #if defined(ENABLE_DEBUG_FILTER)
86 # include "vm/jit/show.h"
89 /* include builtin tables *****************************************************/
91 #include "vm/builtintable.inc"
94 CYCLES_STATS_DECLARE(builtin_new ,100,5)
95 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
97 /* builtintable_init ***********************************************************
99 Parse the descriptors of builtin functions and create the parsed
102 *******************************************************************************/
104 static bool builtintable_init(void)
106 descriptor_pool *descpool;
108 builtintable_entry *bte;
110 /* mark start of dump memory area */
112 dumpsize = dump_size();
114 /* create a new descriptor pool */
116 descpool = descriptor_pool_new(class_java_lang_Object);
118 /* add some entries we need */
120 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
123 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
126 /* first add all descriptors to the pool */
128 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
129 /* create a utf8 string from descriptor */
131 bte->descriptor = utf_new_char(bte->cdescriptor);
133 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
134 /* release dump area */
136 dump_release(dumpsize);
142 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
143 bte->descriptor = utf_new_char(bte->cdescriptor);
145 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
146 dump_release(dumpsize);
151 for (bte = builtintable_function; bte->fp != NULL; bte++) {
152 bte->classname = utf_new_char(bte->cclassname);
153 bte->name = utf_new_char(bte->cname);
154 bte->descriptor = utf_new_char(bte->cdescriptor);
156 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
157 dump_release(dumpsize);
162 /* create the class reference table */
164 (void) descriptor_pool_create_classrefs(descpool, NULL);
166 /* allocate space for the parsed descriptors */
168 descriptor_pool_alloc_parsed_descriptors(descpool);
170 /* Now parse all descriptors. NOTE: builtin-functions are treated
171 like static methods (no `this' pointer). */
173 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
175 descriptor_pool_parse_method_descriptor(descpool,
177 ACC_STATIC | ACC_METHOD_BUILTIN,
181 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
183 descriptor_pool_parse_method_descriptor(descpool,
185 ACC_STATIC | ACC_METHOD_BUILTIN,
189 for (bte = builtintable_function; bte->fp != NULL; bte++) {
191 descriptor_pool_parse_method_descriptor(descpool,
193 ACC_STATIC | ACC_METHOD_BUILTIN,
197 /* release dump area */
199 dump_release(dumpsize);
205 /* builtintable_comparator *****************************************************
207 qsort comparator for the automatic builtin table.
209 *******************************************************************************/
211 static int builtintable_comparator(const void *a, const void *b)
213 builtintable_entry *bte1;
214 builtintable_entry *bte2;
216 bte1 = (builtintable_entry *) a;
217 bte2 = (builtintable_entry *) b;
219 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
223 /* builtintable_sort_automatic *************************************************
225 Sorts the automatic builtin table.
227 *******************************************************************************/
229 static void builtintable_sort_automatic(void)
233 /* calculate table size statically (`- 1' comment see builtintable.inc) */
235 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
237 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
238 builtintable_comparator);
242 /* builtin_init ****************************************************************
244 Initialize the global table of builtin functions.
246 *******************************************************************************/
248 bool builtin_init(void)
250 /* initialize the builtin tables */
252 if (!builtintable_init())
255 /* sort builtin tables */
257 builtintable_sort_automatic();
263 /* builtintable_get_internal ***************************************************
265 Finds an entry in the builtintable for internal functions and
266 returns the a pointer to the structure.
268 *******************************************************************************/
270 builtintable_entry *builtintable_get_internal(functionptr fp)
272 builtintable_entry *bte;
274 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
283 /* builtintable_get_automatic **************************************************
285 Finds an entry in the builtintable for functions which are replaced
286 automatically and returns the a pointer to the structure.
288 *******************************************************************************/
290 builtintable_entry *builtintable_get_automatic(s4 opcode)
292 builtintable_entry *first;
293 builtintable_entry *last;
294 builtintable_entry *middle;
298 /* calculate table size statically (`- 1' comment see builtintable.inc) */
300 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
302 first = builtintable_automatic;
303 last = builtintable_automatic + entries;
305 while (entries > 0) {
307 middle = first + half;
309 if (middle->opcode < opcode) {
316 return (first != last ? first : NULL);
320 /* builtintable_replace_function ***********************************************
324 *******************************************************************************/
326 #if defined(ENABLE_JIT)
327 bool builtintable_replace_function(void *iptr_)
330 builtintable_entry *bte;
333 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
335 /* get name and descriptor of the function */
338 case ICMD_INVOKESTATIC:
339 /* The instruction MUST be resolved, otherwise we run into
340 lazy loading troubles. Anyway, we should/can only replace
341 very VM-close functions. */
343 if (INSTRUCTION_IS_UNRESOLVED(iptr))
346 mr = iptr->sx.s23.s3.fmiref;
353 /* search the function table */
355 for (bte = builtintable_function; bte->fp != NULL; bte++) {
356 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
357 (mr->name == bte->name) &&
358 (mr->descriptor == bte->descriptor)) {
360 /* set the values in the instruction */
362 iptr->opc = bte->opcode;
363 iptr->sx.s23.s3.bte = bte;
364 if (bte->checkexception)
365 iptr->flags.bits |= INS_FLAG_CHECK;
367 iptr->flags.bits &= ~INS_FLAG_CHECK;
375 #endif /* defined(ENABLE_JIT) */
378 /*****************************************************************************
380 *****************************************************************************/
382 /* builtin_instanceof **********************************************************
384 Checks if an object is an instance of some given class (or subclass
385 of that class). If class is an interface, checks if the interface
388 Return value: 1 ... o is an instance of class or implements the interface
389 0 ... otherwise or if o == NULL
391 *******************************************************************************/
393 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
398 return class_isanysubclass(o->vftbl->class, class);
403 /* builtin_checkcast ***********************************************************
405 The same as builtin_instanceof except that 1 is returned when o ==
408 *******************************************************************************/
410 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
415 if (class_isanysubclass(o->vftbl->class, class))
422 /* builtin_descriptorscompatible ***********************************************
424 Checks if two array type descriptors are assignment compatible
426 Return value: 1 ... target = desc is possible
429 *******************************************************************************/
431 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
432 arraydescriptor *target)
437 if (desc->arraytype != target->arraytype)
440 if (desc->arraytype != ARRAYTYPE_OBJECT)
443 /* {both arrays are arrays of references} */
445 if (desc->dimension == target->dimension) {
446 /* an array which contains elements of interface types is
447 allowed to be casted to Object (JOWENN)*/
449 if ((desc->elementvftbl->baseval < 0) &&
450 (target->elementvftbl->baseval == 1))
453 return class_isanysubclass(desc->elementvftbl->class,
454 target->elementvftbl->class);
457 if (desc->dimension < target->dimension)
460 /* {desc has higher dimension than target} */
462 return class_isanysubclass(pseudo_class_Arraystub,
463 target->elementvftbl->class);
467 /* builtin_arraycheckcast ******************************************************
469 Checks if an object is really a subtype of the requested array
470 type. The object has to be an array to begin with. For simple
471 arrays (int, short, double, etc.) the types have to match exactly.
472 For arrays of objects, the type of elements in the array has to be
473 a subtype (or the same type) of the requested element type. For
474 arrays of arrays (which in turn can again be arrays of arrays), the
475 types at the lowest level have to satisfy the corresponding sub
478 *******************************************************************************/
480 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
482 arraydescriptor *desc;
487 desc = o->vftbl->arraydesc;
492 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
496 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
501 return builtin_arraycheckcast(o, targetclass);
505 /* builtin_throw_exception *****************************************************
507 Sets the exceptionptr with the thrown exception and prints some
508 debugging information. Called from asm_vm_call_method.
510 *******************************************************************************/
512 void *builtin_throw_exception(java_objectheader *xptr)
515 java_lang_Throwable *t;
521 t = (java_lang_Throwable *) xptr;
523 /* calculate message length */
525 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
529 utf_bytes(xptr->vftbl->class->name);
530 if (t->detailMessage) {
531 logtextlen += strlen(": ") +
532 u2_utflength(t->detailMessage->value->data
533 + t->detailMessage->offset,
534 t->detailMessage->count);
538 logtextlen += strlen("(nil)");
541 /* allocate memory */
543 dumpsize = dump_size();
545 logtext = DMNEW(char, logtextlen);
547 strcpy(logtext, "Builtin exception thrown: ");
550 utf_cat_classname(logtext, xptr->vftbl->class->name);
552 if (t->detailMessage) {
555 buf = javastring_tochar((java_objectheader *) t->detailMessage);
556 strcat(logtext, ": ");
557 strcat(logtext, buf);
558 MFREE(buf, char, strlen(buf) + 1);
562 strcat(logtext, "(nil)");
569 dump_release(dumpsize);
571 #endif /* !defined(NDEBUG) */
573 /* actually set the exception */
575 exceptions_set_exception(xptr);
577 /* Return a NULL pointer. This is required for vm_call_method to
578 check for an exception. This is for convenience. */
584 /* builtin_canstore ************************************************************
586 Checks, if an object can be stored in an array.
588 Return value: 1 ... possible
589 0 ... otherwise (throws an ArrayStoreException)
591 *******************************************************************************/
593 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
595 arraydescriptor *desc;
596 arraydescriptor *valuedesc;
597 vftbl_t *componentvftbl;
606 /* The following is guaranteed (by verifier checks):
608 * *) oa->...vftbl->arraydesc != NULL
609 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
610 * *) o->vftbl is not an interface vftbl
613 desc = oa->header.objheader.vftbl->arraydesc;
614 componentvftbl = desc->componentvftbl;
615 valuevftbl = o->vftbl;
616 valuedesc = valuevftbl->arraydesc;
618 if ((desc->dimension - 1) == 0) {
619 /* {oa is a one-dimensional array} */
620 /* {oa is an array of references} */
622 if (valuevftbl == componentvftbl)
625 /* XXX TODO Fix me with a lock. */
626 /* ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues); */
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 else if (valuedesc == NULL) {
642 /* {oa has dimension > 1} */
643 /* {componentvftbl->arraydesc != NULL} */
645 /* check if o is an array */
650 /* {o is an array} */
652 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
655 /* if not possible, throw an exception */
658 exceptions_throw_arraystoreexception();
666 /* This is an optimized version where a is guaranteed to be one-dimensional */
667 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
669 arraydescriptor *desc;
670 vftbl_t *elementvftbl;
679 /* The following is guaranteed (by verifier checks):
681 * *) a->...vftbl->arraydesc != NULL
682 * *) a->...vftbl->arraydesc->elementvftbl != NULL
683 * *) a->...vftbl->arraydesc->dimension == 1
684 * *) o->vftbl is not an interface vftbl
687 desc = a->header.objheader.vftbl->arraydesc;
688 elementvftbl = desc->elementvftbl;
689 valuevftbl = o->vftbl;
691 /* {a is a one-dimensional array} */
693 if (valuevftbl == elementvftbl)
696 /* XXX TODO Fix me with a lock. */
697 /* ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues); */
699 baseval = elementvftbl->baseval;
702 /* an array of interface references */
703 result = ((valuevftbl->interfacetablelength > -baseval) &&
704 (valuevftbl->interfacetable[baseval] != NULL));
707 diffval = valuevftbl->baseval - elementvftbl->baseval;
708 result = diffval <= (uint32_t) elementvftbl->diffval;
715 /* This is an optimized version where a is guaranteed to be a
716 * one-dimensional array of a class type */
717 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
719 vftbl_t *elementvftbl;
727 /* The following is guaranteed (by verifier checks):
729 * *) a->...vftbl->arraydesc != NULL
730 * *) a->...vftbl->arraydesc->elementvftbl != NULL
731 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
732 * *) a->...vftbl->arraydesc->dimension == 1
733 * *) o->vftbl is not an interface vftbl
736 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
737 valuevftbl = o->vftbl;
739 /* {a is a one-dimensional array} */
741 if (valuevftbl == elementvftbl)
744 /* XXX TODO Fix me with a lock. */
745 /* ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues); */
747 diffval = valuevftbl->baseval - elementvftbl->baseval;
748 result = diffval <= (uint32_t) elementvftbl->diffval;
754 /* builtin_new *****************************************************************
756 Creates a new instance of class c on the heap.
758 Return value: pointer to the object or NULL if no memory is
761 *******************************************************************************/
763 java_objectheader *builtin_new(classinfo *c)
765 java_objectheader *o;
766 #if defined(ENABLE_RT_TIMING)
767 struct timespec time_start, time_end;
769 #if defined(ENABLE_CYCLES_STATS)
770 u8 cycles_start, cycles_end;
773 RT_TIMING_GET_TIME(time_start);
774 CYCLES_STATS_GET(cycles_start);
776 /* is the class loaded */
778 assert(c->state & CLASS_LOADED);
780 /* check if we can instantiate this class */
782 if (c->flags & ACC_ABSTRACT) {
783 exceptions_throw_instantiationerror(c);
787 /* is the class linked */
789 if (!(c->state & CLASS_LINKED))
793 if (!(c->state & CLASS_INITIALIZED)) {
796 log_message_class("Initialize class (from builtin_new): ", c);
799 if (!initialize_class(c))
803 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
811 #if defined(ENABLE_THREADS)
812 lock_init_object_lock(o);
815 CYCLES_STATS_GET(cycles_end);
816 RT_TIMING_GET_TIME(time_end);
818 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
819 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
825 /* builtin_newarray ************************************************************
827 Creates an array with the given vftbl on the heap. This function
828 takes as class argument an array class.
830 Return value: pointer to the array or NULL if no memory is available
832 *******************************************************************************/
834 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
836 arraydescriptor *desc;
841 #if defined(ENABLE_RT_TIMING)
842 struct timespec time_start, time_end;
845 RT_TIMING_GET_TIME(time_start);
847 desc = arrayclass->vftbl->arraydesc;
848 dataoffset = desc->dataoffset;
849 componentsize = desc->componentsize;
852 exceptions_throw_negativearraysizeexception();
856 actualsize = dataoffset + size * componentsize;
858 /* check for overflow */
860 if (((u4) actualsize) < ((u4) size)) {
861 exceptions_throw_outofmemoryerror();
865 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
870 a->objheader.vftbl = arrayclass->vftbl;
872 #if defined(ENABLE_THREADS)
873 lock_init_object_lock(&a->objheader);
878 RT_TIMING_GET_TIME(time_end);
879 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
885 /* builtin_anewarray ***********************************************************
887 Creates an array of references to the given class type on the heap.
889 Return value: pointer to the array or NULL if no memory is
892 *******************************************************************************/
894 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
896 classinfo *arrayclass;
898 /* is class loaded */
900 assert(componentclass->state & CLASS_LOADED);
902 /* is class linked */
904 if (!(componentclass->state & CLASS_LINKED))
905 if (!link_class(componentclass))
908 arrayclass = class_array_of(componentclass, true);
913 return (java_objectarray *) builtin_newarray(size, arrayclass);
917 /* builtin_newarray_boolean ****************************************************
919 Creates an array of bytes on the heap. The array is designated as
920 an array of booleans (important for casts)
922 Return value: pointer to the array or NULL if no memory is
925 *******************************************************************************/
927 java_booleanarray *builtin_newarray_boolean(s4 size)
929 return (java_booleanarray *)
930 builtin_newarray(size,
931 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
935 /* builtin_newarray_byte *******************************************************
937 Creates an array of 8 bit Integers on the heap.
939 Return value: pointer to the array or NULL if no memory is
942 *******************************************************************************/
944 java_bytearray *builtin_newarray_byte(s4 size)
946 return (java_bytearray *)
947 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
951 /* builtin_newarray_char *******************************************************
953 Creates an array of characters on the heap.
955 Return value: pointer to the array or NULL if no memory is
958 *******************************************************************************/
960 java_chararray *builtin_newarray_char(s4 size)
962 return (java_chararray *)
963 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
967 /* builtin_newarray_short ******************************************************
969 Creates an array of 16 bit Integers on the heap.
971 Return value: pointer to the array or NULL if no memory is
974 *******************************************************************************/
976 java_shortarray *builtin_newarray_short(s4 size)
978 return (java_shortarray *)
979 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
983 /* builtin_newarray_int ********************************************************
985 Creates an array of 32 bit Integers on the heap.
987 Return value: pointer to the array or NULL if no memory is
990 *******************************************************************************/
992 java_intarray *builtin_newarray_int(s4 size)
994 return (java_intarray *)
995 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
999 /* builtin_newarray_long *******************************************************
1001 Creates an array of 64 bit Integers on the heap.
1003 Return value: pointer to the array or NULL if no memory is
1006 *******************************************************************************/
1008 java_longarray *builtin_newarray_long(s4 size)
1010 return (java_longarray *)
1011 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1015 /* builtin_newarray_float ******************************************************
1017 Creates an array of 32 bit IEEE floats on the heap.
1019 Return value: pointer to the array or NULL if no memory is
1022 *******************************************************************************/
1024 java_floatarray *builtin_newarray_float(s4 size)
1026 return (java_floatarray *)
1027 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1031 /* builtin_newarray_double *****************************************************
1033 Creates an array of 64 bit IEEE floats on the heap.
1035 Return value: pointer to the array or NULL if no memory is
1038 *******************************************************************************/
1040 java_doublearray *builtin_newarray_double(s4 size)
1042 return (java_doublearray *)
1043 builtin_newarray(size,
1044 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1048 /* builtin_multianewarray_intern ***********************************************
1050 Creates a multi-dimensional array on the heap. The dimensions are
1051 passed in an array of longs.
1054 n.............number of dimensions to create
1055 arrayclass....the array class
1056 dims..........array containing the size of each dimension to create
1058 Return value: pointer to the array or NULL if no memory is
1061 ******************************************************************************/
1063 static java_arrayheader *builtin_multianewarray_intern(int n,
1064 classinfo *arrayclass,
1068 java_arrayheader *a;
1069 classinfo *componentclass;
1072 /* create this dimension */
1074 size = (s4) dims[0];
1075 a = builtin_newarray(size, arrayclass);
1080 /* if this is the last dimension return */
1085 /* get the class of the components to create */
1087 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1089 /* The verifier guarantees that the dimension count is in the range. */
1091 /* create the component arrays */
1093 for (i = 0; i < size; i++) {
1094 java_arrayheader *ea =
1095 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1096 /* we save an s4 to a s8 slot, 8-byte aligned */
1098 builtin_multianewarray_intern(n, componentclass, dims + 2);
1100 builtin_multianewarray_intern(n, componentclass, dims + 1);
1106 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1113 /* builtin_multianewarray ******************************************************
1115 Wrapper for builtin_multianewarray_intern which checks all
1116 dimensions before we start allocating.
1118 ******************************************************************************/
1120 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1126 /* check all dimensions before doing anything */
1128 for (i = 0; i < n; i++) {
1129 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1130 /* we save an s4 to a s8 slot, 8-byte aligned */
1131 size = (s4) dims[i * 2];
1133 size = (s4) dims[i];
1137 exceptions_throw_negativearraysizeexception();
1142 /* now call the real function */
1144 return builtin_multianewarray_intern(n, arrayclass, dims);
1148 /*****************************************************************************
1151 Various functions for printing a message at method entry or exit (for
1154 *****************************************************************************/
1156 #if !defined(NDEBUG)
1157 static s4 methodindent = 0;
1158 static u4 callcount = 0;
1160 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1170 #if defined(ENABLE_DEBUG_FILTER)
1171 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1174 #if defined(ENABLE_VMLOG)
1178 if (opt_verbosecall && indent)
1181 /* calculate message length */
1185 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1188 logtextlen = strlen("Some Throwable");
1191 logtextlen += strlen(" thrown in ");
1195 utf_bytes(m->class->name) +
1197 utf_bytes(m->name) +
1198 utf_bytes(m->descriptor) +
1199 strlen("(NOSYNC,NATIVE");
1201 #if SIZEOF_VOID_P == 8
1203 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1205 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1208 if (m->class->sourcefile == NULL)
1209 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1211 logtextlen += utf_bytes(m->class->sourcefile);
1213 logtextlen += strlen(":65536)");
1217 logtextlen += strlen("call_java_method");
1220 logtextlen += strlen("0");
1222 /* allocate memory */
1224 dumpsize = dump_size();
1226 logtext = DMNEW(char, logtextlen);
1229 strcpy(logtext, "Exception ");
1230 utf_cat_classname(logtext, xptr->vftbl->class->name);
1233 strcpy(logtext, "Some Throwable");
1236 strcat(logtext, " thrown in ");
1239 utf_cat_classname(logtext, m->class->name);
1240 strcat(logtext, ".");
1241 utf_cat(logtext, m->name);
1242 utf_cat(logtext, m->descriptor);
1244 if (m->flags & ACC_SYNCHRONIZED)
1245 strcat(logtext, "(SYNC");
1247 strcat(logtext, "(NOSYNC");
1249 if (m->flags & ACC_NATIVE) {
1250 strcat(logtext, ",NATIVE");
1254 #if SIZEOF_VOID_P == 8
1255 sprintf(logtext + strlen(logtext),
1256 ")(0x%016lx) at position 0x%016lx",
1257 (ptrint) code->entrypoint, (ptrint) pos);
1259 sprintf(logtext + strlen(logtext),
1260 ")(0x%08x) at position 0x%08x",
1261 (ptrint) code->entrypoint, (ptrint) pos);
1266 /* XXX preliminary: This should get the actual codeinfo */
1267 /* in which the exception happened. */
1270 #if SIZEOF_VOID_P == 8
1271 sprintf(logtext + strlen(logtext),
1272 ")(0x%016lx) at position 0x%016lx (",
1273 (ptrint) code->entrypoint, (ptrint) pos);
1275 sprintf(logtext + strlen(logtext),
1276 ")(0x%08x) at position 0x%08x (",
1277 (ptrint) code->entrypoint, (ptrint) pos);
1280 if (m->class->sourcefile == NULL)
1281 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1283 utf_cat(logtext, m->class->sourcefile);
1285 sprintf(logtext + strlen(logtext), ":%d)", 0);
1289 strcat(logtext, "call_java_method");
1293 /* release memory */
1295 dump_release(dumpsize);
1299 #endif /* !defined(NDEBUG) */
1302 /* builtin_print_argument ******************************************************
1304 Prints arguments and return values for the call trace.
1306 *******************************************************************************/
1308 #if !defined(NDEBUG)
1309 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1310 typedesc *paramtype, s8 value)
1313 java_objectheader *o;
1318 switch (paramtype->type) {
1321 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1326 #if SIZEOF_VOID_P == 4
1327 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1329 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1334 #if defined(__S390__)
1336 /* The below won't work on S390 */
1340 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1345 #if SIZEOF_VOID_P == 4
1346 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1348 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1353 #if SIZEOF_VOID_P == 4
1354 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1356 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1359 /* cast to java.lang.Object */
1361 o = (java_objectheader *) (ptrint) value;
1363 /* check return argument for java.lang.Class or java.lang.String */
1366 if (o->vftbl->class == class_java_lang_String) {
1367 /* get java.lang.String object and the length of the
1370 u = javastring_toutf(o, false);
1372 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1374 /* realloc memory for string length */
1376 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1379 /* convert to utf8 string and strcat it to the logtext */
1381 strcat(logtext, " (String = \"");
1382 utf_cat(logtext, u);
1383 strcat(logtext, "\")");
1386 if (o->vftbl->class == class_java_lang_Class) {
1387 /* if the object returned is a java.lang.Class
1388 cast it to classinfo structure and get the name
1391 c = (classinfo *) o;
1396 /* if the object returned is not a java.lang.String or
1397 a java.lang.Class just print the name of the class */
1399 u = o->vftbl->class->name;
1402 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1404 /* realloc memory for string length */
1406 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1409 /* strcat to the logtext */
1411 strcat(logtext, " (Class = \"");
1412 utf_cat_classname(logtext, u);
1413 strcat(logtext, "\")");
1420 #endif /* !defined(NDEBUG) */
1422 /* builtin_verbosecall_enter ***************************************************
1424 Print method call with arguments for -verbose:call.
1426 *******************************************************************************/
1428 #if !defined(NDEBUG)
1430 #ifdef TRACE_ARGS_NUM
1431 void builtin_verbosecall_enter(s8 a0, s8 a1,
1432 # if TRACE_ARGS_NUM >= 4
1435 # if TRACE_ARGS_NUM >= 6
1438 # if TRACE_ARGS_NUM == 8
1450 #if defined(ENABLE_DEBUG_FILTER)
1451 if (! show_filters_test_verbosecall_enter(m)) return;
1454 #if defined(ENABLE_VMLOG)
1455 vmlog_cacao_enter_method(m);
1461 /* calculate message length */
1464 strlen("4294967295 ") +
1465 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1467 strlen("called: ") +
1468 utf_bytes(m->class->name) +
1470 utf_bytes(m->name) +
1471 utf_bytes(m->descriptor);
1473 /* Actually it's not possible to have all flags printed, but:
1478 strlen(" PRIVATE") +
1479 strlen(" PROTECTED") +
1482 strlen(" SYNCHRONIZED") +
1483 strlen(" VOLATILE") +
1484 strlen(" TRANSIENT") +
1486 strlen(" INTERFACE") +
1487 strlen(" ABSTRACT");
1489 /* add maximal argument length */
1493 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1494 strlen("...(255)") +
1497 /* allocate memory */
1499 dumpsize = dump_size();
1501 logtext = DMNEW(char, logtextlen);
1505 sprintf(logtext, "%10d ", callcount);
1506 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1508 pos = strlen(logtext);
1510 for (i = 0; i < methodindent; i++)
1511 logtext[pos++] = '\t';
1513 strcpy(logtext + pos, "called: ");
1515 utf_cat_classname(logtext, m->class->name);
1516 strcat(logtext, ".");
1517 utf_cat(logtext, m->name);
1518 utf_cat(logtext, m->descriptor);
1520 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1521 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1522 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1523 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1524 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1525 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1526 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1527 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1528 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1529 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1530 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1532 strcat(logtext, "(");
1534 if (md->paramcount >= 1) {
1535 logtext = builtin_print_argument(logtext, &logtextlen,
1536 &md->paramtypes[0], a0);
1539 if (md->paramcount >= 2) {
1540 strcat(logtext, ", ");
1542 logtext = builtin_print_argument(logtext, &logtextlen,
1543 &md->paramtypes[1], a1);
1546 #if TRACE_ARGS_NUM >= 4
1547 if (md->paramcount >= 3) {
1548 strcat(logtext, ", ");
1550 logtext = builtin_print_argument(logtext, &logtextlen,
1551 &md->paramtypes[2], a2);
1554 if (md->paramcount >= 4) {
1555 strcat(logtext, ", ");
1557 logtext = builtin_print_argument(logtext, &logtextlen,
1558 &md->paramtypes[3], a3);
1562 #if TRACE_ARGS_NUM >= 6
1563 if (md->paramcount >= 5) {
1564 strcat(logtext, ", ");
1566 logtext = builtin_print_argument(logtext, &logtextlen,
1567 &md->paramtypes[4], a4);
1570 if (md->paramcount >= 6) {
1571 strcat(logtext, ", ");
1573 logtext = builtin_print_argument(logtext, &logtextlen,
1574 &md->paramtypes[5], a5);
1578 #if TRACE_ARGS_NUM == 8
1579 if (md->paramcount >= 7) {
1580 strcat(logtext, ", ");
1582 logtext = builtin_print_argument(logtext, &logtextlen,
1583 &md->paramtypes[6], a6);
1586 if (md->paramcount >= 8) {
1587 strcat(logtext, ", ");
1589 logtext = builtin_print_argument(logtext, &logtextlen,
1590 &md->paramtypes[7], a7);
1594 if (md->paramcount > 8) {
1595 sprintf(logtext + strlen(logtext), ", ...(%d)",
1596 md->paramcount - TRACE_ARGS_NUM);
1599 strcat(logtext, ")");
1603 /* release memory */
1605 dump_release(dumpsize);
1611 #endif /* !defined(NDEBUG) */
1614 /* builtin_verbosecall_exit ****************************************************
1616 Print method exit for -verbose:call.
1618 *******************************************************************************/
1620 #if !defined(NDEBUG)
1621 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1631 #if defined(ENABLE_DEBUG_FILTER)
1632 if (! show_filters_test_verbosecall_exit(m)) return;
1635 #if defined(ENABLE_VMLOG)
1636 vmlog_cacao_leave_method(m);
1642 /* calculate message length */
1645 strlen("4294967295 ") +
1646 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1648 strlen("finished: ") +
1649 utf_bytes(m->class->name) +
1651 utf_bytes(m->name) +
1652 utf_bytes(m->descriptor) +
1653 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1655 /* add maximal argument length */
1657 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1659 /* allocate memory */
1661 dumpsize = dump_size();
1663 logtext = DMNEW(char, logtextlen);
1665 /* outdent the log message */
1670 log_text("WARNING: unmatched methodindent--");
1672 /* generate the message */
1674 sprintf(logtext, " ");
1675 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1677 pos = strlen(logtext);
1679 for (i = 0; i < methodindent; i++)
1680 logtext[pos++] = '\t';
1682 strcpy(logtext + pos, "finished: ");
1683 utf_cat_classname(logtext, m->class->name);
1684 strcat(logtext, ".");
1685 utf_cat(logtext, m->name);
1686 utf_cat(logtext, m->descriptor);
1688 if (!IS_VOID_TYPE(md->returntype.type)) {
1689 strcat(logtext, "->");
1691 switch (md->returntype.type) {
1708 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1713 /* release memory */
1715 dump_release(dumpsize);
1718 #endif /* !defined(NDEBUG) */
1721 #if defined(ENABLE_CYCLES_STATS)
1722 void builtin_print_cycles_stats(FILE *file)
1724 fprintf(file,"builtin cylce count statistics:\n");
1726 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1727 CYCLES_STATS_PRINT(builtin_new ,file);
1731 #endif /* defined(ENABLE_CYCLES_STATS) */
1734 /*****************************************************************************
1735 MISCELLANEOUS HELPER FUNCTIONS
1736 *****************************************************************************/
1740 /*********** Functions for integer divisions *****************************
1742 On some systems (eg. DEC ALPHA), integer division is not supported by the
1743 CPU. These helper functions implement the missing functionality.
1745 ******************************************************************************/
1747 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1748 s4 builtin_idiv(s4 a, s4 b)
1757 s4 builtin_irem(s4 a, s4 b)
1765 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1768 /* functions for long arithmetics **********************************************
1770 On systems where 64 bit Integers are not supported by the CPU,
1771 these functions are needed.
1773 ******************************************************************************/
1775 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1776 s8 builtin_ladd(s8 a, s8 b)
1789 s8 builtin_lsub(s8 a, s8 b)
1802 s8 builtin_lneg(s8 a)
1814 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1817 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1818 s8 builtin_lmul(s8 a, s8 b)
1830 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1833 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1834 s8 builtin_ldiv(s8 a, s8 b)
1847 s8 builtin_lrem(s8 a, s8 b)
1859 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1862 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1863 s8 builtin_lshl(s8 a, s4 b)
1876 s8 builtin_lshr(s8 a, s4 b)
1889 s8 builtin_lushr(s8 a, s4 b)
1894 c = ((u8) a) >> (b & 63);
1901 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1904 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1905 s8 builtin_land(s8 a, s8 b)
1918 s8 builtin_lor(s8 a, s8 b)
1931 s8 builtin_lxor(s8 a, s8 b)
1943 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1946 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1947 s4 builtin_lcmp(s8 a, s8 b)
1961 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1964 /* functions for unsupported floating instructions ****************************/
1966 /* used to convert FLT_xxx defines into float values */
1968 static inline float intBitsToFloat(s4 i)
1977 /* used to convert DBL_xxx defines into double values */
1979 static inline float longBitsToDouble(s8 l)
1989 float builtin_fadd(float a, float b)
1991 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1992 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2003 if (copysignf(1.0, a) == copysignf(1.0, b))
2006 return intBitsToFloat(FLT_NAN);
2012 float builtin_fsub(float a, float b)
2014 return builtin_fadd(a, builtin_fneg(b));
2018 float builtin_fmul(float a, float b)
2020 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2021 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2023 if (finitef(b)) return a * b;
2025 if (a == 0) return intBitsToFloat(FLT_NAN);
2026 else return copysignf(b, copysignf(1.0, b)*a);
2031 if (b == 0) return intBitsToFloat(FLT_NAN);
2032 else return copysignf(a, copysignf(1.0, a)*b);
2035 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2041 /* builtin_ddiv ****************************************************************
2043 Implementation as described in VM Spec.
2045 *******************************************************************************/
2047 float builtin_fdiv(float a, float b)
2051 /* If neither value1' nor value2' is NaN, the sign of the result */
2052 /* is positive if both values have the same sign, negative if the */
2053 /* values have different signs. */
2059 /* If either value1' or value2' is NaN, the result is NaN. */
2061 return intBitsToFloat(FLT_NAN);
2064 /* Division of a finite value by an infinity results in a */
2065 /* signed zero, with the sign-producing rule just given. */
2067 /* is sign equal? */
2069 if (copysignf(1.0, a) == copysignf(1.0, b))
2078 /* If either value1' or value2' is NaN, the result is NaN. */
2080 return intBitsToFloat(FLT_NAN);
2082 } else if (finitef(b)) {
2083 /* Division of an infinity by a finite value results in a signed */
2084 /* infinity, with the sign-producing rule just given. */
2086 /* is sign equal? */
2088 if (copysignf(1.0, a) == copysignf(1.0, b))
2089 return intBitsToFloat(FLT_POSINF);
2091 return intBitsToFloat(FLT_NEGINF);
2094 /* Division of an infinity by an infinity results in NaN. */
2096 return intBitsToFloat(FLT_NAN);
2102 float builtin_fneg(float a)
2104 if (isnanf(a)) return a;
2106 if (finitef(a)) return -a;
2107 else return copysignf(a, -copysignf(1.0, a));
2110 #endif /* !SUPPORT_FLOAT */
2113 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2114 s4 builtin_fcmpl(float a, float b)
2122 if (!finitef(a) || !finitef(b)) {
2123 a = finitef(a) ? 0 : copysignf(1.0, a);
2124 b = finitef(b) ? 0 : copysignf(1.0, b);
2137 s4 builtin_fcmpg(float a, float b)
2139 if (isnanf(a)) return 1;
2140 if (isnanf(b)) return 1;
2141 if (!finitef(a) || !finitef(b)) {
2142 a = finitef(a) ? 0 : copysignf(1.0, a);
2143 b = finitef(b) ? 0 : copysignf(1.0, b);
2145 if (a > b) return 1;
2146 if (a == b) return 0;
2149 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2152 float builtin_frem(float a, float b)
2158 /* functions for unsupported double instructions ******************************/
2161 double builtin_dadd(double a, double b)
2163 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2164 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2166 if (finite(b)) return a + b;
2170 if (finite(b)) return a;
2172 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2173 else return longBitsToDouble(DBL_NAN);
2179 double builtin_dsub(double a, double b)
2181 return builtin_dadd(a, builtin_dneg(b));
2185 double builtin_dmul(double a, double b)
2187 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2188 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2190 if (finite(b)) return a * b;
2192 if (a == 0) return longBitsToDouble(DBL_NAN);
2193 else return copysign(b, copysign(1.0, b) * a);
2198 if (b == 0) return longBitsToDouble(DBL_NAN);
2199 else return copysign(a, copysign(1.0, a) * b);
2202 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2208 /* builtin_ddiv ****************************************************************
2210 Implementation as described in VM Spec.
2212 *******************************************************************************/
2214 double builtin_ddiv(double a, double b)
2218 /* If neither value1' nor value2' is NaN, the sign of the result */
2219 /* is positive if both values have the same sign, negative if the */
2220 /* values have different signs. */
2226 /* If either value1' or value2' is NaN, the result is NaN. */
2228 return longBitsToDouble(DBL_NAN);
2231 /* Division of a finite value by an infinity results in a */
2232 /* signed zero, with the sign-producing rule just given. */
2234 /* is sign equal? */
2236 if (copysign(1.0, a) == copysign(1.0, b))
2245 /* If either value1' or value2' is NaN, the result is NaN. */
2247 return longBitsToDouble(DBL_NAN);
2249 } else if (finite(b)) {
2250 /* Division of an infinity by a finite value results in a signed */
2251 /* infinity, with the sign-producing rule just given. */
2253 /* is sign equal? */
2255 if (copysign(1.0, a) == copysign(1.0, b))
2256 return longBitsToDouble(DBL_POSINF);
2258 return longBitsToDouble(DBL_NEGINF);
2261 /* Division of an infinity by an infinity results in NaN. */
2263 return longBitsToDouble(DBL_NAN);
2269 /* builtin_dneg ****************************************************************
2271 Implemented as described in VM Spec.
2273 *******************************************************************************/
2275 double builtin_dneg(double a)
2278 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2285 /* If the operand is a zero, the result is the zero of opposite */
2291 /* If the operand is an infinity, the result is the infinity of */
2292 /* opposite sign. */
2294 return copysign(a, -copysign(1.0, a));
2298 #endif /* !SUPPORT_DOUBLE */
2301 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2302 s4 builtin_dcmpl(double a, double b)
2310 if (!finite(a) || !finite(b)) {
2311 a = finite(a) ? 0 : copysign(1.0, a);
2312 b = finite(b) ? 0 : copysign(1.0, b);
2325 s4 builtin_dcmpg(double a, double b)
2333 if (!finite(a) || !finite(b)) {
2334 a = finite(a) ? 0 : copysign(1.0, a);
2335 b = finite(b) ? 0 : copysign(1.0, b);
2346 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2349 double builtin_drem(double a, double b)
2355 /* conversion operations ******************************************************/
2358 s8 builtin_i2l(s4 i)
2370 s4 builtin_l2i(s8 l)
2381 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2382 float builtin_i2f(s4 a)
2384 float f = (float) a;
2387 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2390 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2391 double builtin_i2d(s4 a)
2393 double d = (double) a;
2396 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2399 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2400 float builtin_l2f(s8 a)
2403 float f = (float) a;
2409 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2412 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2413 double builtin_l2d(s8 a)
2416 double d = (double) a;
2422 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2425 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2426 s4 builtin_f2i(float a)
2430 i = builtin_d2i((double) a);
2441 if (a < (-2147483648))
2442 return (-2147483648);
2445 f = copysignf((float) 1.0, a);
2448 return (-2147483648); */
2450 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2453 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2454 s8 builtin_f2l(float a)
2458 l = builtin_d2l((double) a);
2465 if (a > 9223372036854775807L)
2466 return 9223372036854775807L;
2467 if (a < (-9223372036854775808L))
2468 return (-9223372036854775808L);
2473 f = copysignf((float) 1.0, a);
2475 return 9223372036854775807L;
2476 return (-9223372036854775808L); */
2478 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2481 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2482 s4 builtin_d2i(double a)
2487 if (a >= 2147483647)
2489 if (a <= (-2147483647-1))
2490 return (-2147483647-1);
2495 d = copysign(1.0, a);
2498 return (-2147483647-1);
2500 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2503 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2504 s8 builtin_d2l(double a)
2509 if (a >= 9223372036854775807LL)
2510 return 9223372036854775807LL;
2511 if (a <= (-9223372036854775807LL-1))
2512 return (-9223372036854775807LL-1);
2517 d = copysign(1.0, a);
2519 return 9223372036854775807LL;
2520 return (-9223372036854775807LL-1);
2522 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2525 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2526 double builtin_f2d(float a)
2528 if (finitef(a)) return (double) a;
2531 return longBitsToDouble(DBL_NAN);
2533 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2537 float builtin_d2f(double a)
2543 return intBitsToFloat(FLT_NAN);
2545 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2548 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2551 /* builtin_arraycopy ***********************************************************
2553 Builtin for java.lang.System.arraycopy.
2555 ATTENTION: This builtin function returns a boolean value to signal
2556 the ICMD_BUILTIN if there was an exception.
2558 *******************************************************************************/
2560 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2561 java_arrayheader *dest, s4 destStart, s4 len)
2563 arraydescriptor *sdesc;
2564 arraydescriptor *ddesc;
2567 if ((src == NULL) || (dest == NULL)) {
2568 exceptions_throw_nullpointerexception();
2572 sdesc = src->objheader.vftbl->arraydesc;
2573 ddesc = dest->objheader.vftbl->arraydesc;
2575 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2576 exceptions_throw_arraystoreexception();
2580 /* we try to throw exception with the same message as SUN does */
2582 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2583 (srcStart + len < 0) || (srcStart + len > src->size) ||
2584 (destStart + len < 0) || (destStart + len > dest->size)) {
2585 exceptions_throw_arrayindexoutofboundsexception();
2589 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2590 /* We copy primitive values or references of exactly the same type */
2592 s4 dataoffset = sdesc->dataoffset;
2593 s4 componentsize = sdesc->componentsize;
2595 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2596 ((u1 *) src) + dataoffset + componentsize * srcStart,
2597 (size_t) len * componentsize);
2600 /* We copy references of different type */
2602 java_objectarray *oas = (java_objectarray *) src;
2603 java_objectarray *oad = (java_objectarray *) dest;
2605 if (destStart <= srcStart) {
2606 for (i = 0; i < len; i++) {
2607 java_objectheader *o = oas->data[srcStart + i];
2609 if (!builtin_canstore(oad, o))
2612 oad->data[destStart + i] = o;
2616 /* XXX this does not completely obey the specification!
2617 If an exception is thrown only the elements above the
2618 current index have been copied. The specification
2619 requires that only the elements *below* the current
2620 index have been copied before the throw. */
2622 for (i = len - 1; i >= 0; i--) {
2623 java_objectheader *o = oas->data[srcStart + i];
2625 if (!builtin_canstore(oad, o))
2628 oad->data[destStart + i] = o;
2637 /* builtin_nanotime ************************************************************
2639 Return the current time in nanoseconds.
2641 *******************************************************************************/
2643 s8 builtin_nanotime(void)
2648 if (gettimeofday(&tv, NULL) == -1)
2649 vm_abort("gettimeofday failed: %s", strerror(errno));
2651 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2653 return usecs * 1000;
2657 /* builtin_currenttimemillis ***************************************************
2659 Return the current time in milliseconds.
2661 *******************************************************************************/
2663 s8 builtin_currenttimemillis(void)
2667 msecs = builtin_nanotime() / 1000 / 1000;
2673 /* builtin_clone ***************************************************************
2675 Function for cloning objects or arrays.
2677 *******************************************************************************/
2679 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2681 arraydescriptor *ad;
2682 java_arrayheader *ah;
2685 java_objectheader *co; /* cloned object header */
2687 /* get the array descriptor */
2689 ad = o->vftbl->arraydesc;
2691 /* we are cloning an array */
2694 ah = (java_arrayheader *) o;
2696 size = ad->dataoffset + ad->componentsize * ah->size;
2698 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2703 MCOPY(co, o, u1, size);
2705 #if defined(ENABLE_GC_CACAO)
2706 heap_init_objectheader(co, size);
2709 #if defined(ENABLE_THREADS)
2710 lock_init_object_lock(co);
2716 /* we are cloning a non-array */
2718 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2719 exceptions_throw_clonenotsupportedexception();
2723 /* get the class of the object */
2725 c = o->vftbl->class;
2727 /* create new object */
2729 co = builtin_new(c);
2734 MCOPY(co, o, u1, c->instancesize);
2736 #if defined(ENABLE_GC_CACAO)
2737 heap_init_objectheader(co, c->instancesize);
2740 #if defined(ENABLE_THREADS)
2741 lock_init_object_lock(co);
2747 #if defined(ENABLE_VMLOG)
2749 #include <vmlog_cacao.c>
2754 * These are local overrides for various environment variables in Emacs.
2755 * Please do not remove this and leave it at the end of the file, where
2756 * Emacs will automagically detect them.
2757 * ---------------------------------------------------------------------
2760 * indent-tabs-mode: t
2764 * vim:noexpandtab:sw=4:ts=4: