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 7563 2007-03-23 21:33:53Z twisti $
50 #include "fdlibm/fdlibm.h"
51 #if defined(__CYGWIN__) && defined(Bias)
55 #include "mm/gc-common.h"
56 #include "mm/memory.h"
58 #include "native/jni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
62 #if defined(ENABLE_THREADS)
63 # include "threads/native/lock.h"
66 #include "toolbox/logging.h"
67 #include "toolbox/util.h"
69 #include "vm/builtin.h"
70 #include "vm/cycles-stats.h"
71 #include "vm/exceptions.h"
72 #include "vm/global.h"
73 #include "vm/initialize.h"
74 #include "vm/stringlocal.h"
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/patcher.h"
79 #include "vmcore/class.h"
80 #include "vmcore/loader.h"
81 #include "vmcore/options.h"
82 #include "vmcore/rt-timing.h"
85 /* include builtin tables *****************************************************/
87 #include "vm/builtintable.inc"
90 CYCLES_STATS_DECLARE(builtin_new ,100,5)
91 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
93 /* builtintable_init ***********************************************************
95 Parse the descriptors of builtin functions and create the parsed
98 *******************************************************************************/
100 static bool builtintable_init(void)
102 descriptor_pool *descpool;
104 builtintable_entry *bte;
106 /* mark start of dump memory area */
108 dumpsize = dump_size();
110 /* create a new descriptor pool */
112 descpool = descriptor_pool_new(class_java_lang_Object);
114 /* add some entries we need */
116 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
119 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
122 /* first add all descriptors to the pool */
124 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
125 /* create a utf8 string from descriptor */
127 bte->descriptor = utf_new_char(bte->cdescriptor);
129 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
130 /* release dump area */
132 dump_release(dumpsize);
138 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
139 bte->descriptor = utf_new_char(bte->cdescriptor);
141 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
142 dump_release(dumpsize);
147 for (bte = builtintable_function; bte->fp != NULL; bte++) {
148 bte->classname = utf_new_char(bte->cclassname);
149 bte->name = utf_new_char(bte->cname);
150 bte->descriptor = utf_new_char(bte->cdescriptor);
152 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
153 dump_release(dumpsize);
158 /* create the class reference table */
160 (void) descriptor_pool_create_classrefs(descpool, NULL);
162 /* allocate space for the parsed descriptors */
164 descriptor_pool_alloc_parsed_descriptors(descpool);
166 /* now parse all descriptors */
168 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
169 /* parse the descriptor, builtin is always static (no `this' pointer) */
171 bte->md = descriptor_pool_parse_method_descriptor(descpool,
176 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
177 bte->md = descriptor_pool_parse_method_descriptor(descpool,
182 for (bte = builtintable_function; bte->fp != NULL; bte++) {
183 bte->md = descriptor_pool_parse_method_descriptor(descpool,
188 /* release dump area */
190 dump_release(dumpsize);
196 /* builtintable_comparator *****************************************************
198 qsort comparator for the automatic builtin table.
200 *******************************************************************************/
202 static int builtintable_comparator(const void *a, const void *b)
204 builtintable_entry *bte1;
205 builtintable_entry *bte2;
207 bte1 = (builtintable_entry *) a;
208 bte2 = (builtintable_entry *) b;
210 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
214 /* builtintable_sort_automatic *************************************************
216 Sorts the automatic builtin table.
218 *******************************************************************************/
220 static void builtintable_sort_automatic(void)
224 /* calculate table size statically (`- 1' comment see builtintable.inc) */
226 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
228 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
229 builtintable_comparator);
233 /* builtin_init ****************************************************************
235 Initialize the global table of builtin functions.
237 *******************************************************************************/
239 bool builtin_init(void)
241 /* initialize the builtin tables */
243 if (!builtintable_init())
246 /* sort builtin tables */
248 builtintable_sort_automatic();
254 /* builtintable_get_internal ***************************************************
256 Finds an entry in the builtintable for internal functions and
257 returns the a pointer to the structure.
259 *******************************************************************************/
261 builtintable_entry *builtintable_get_internal(functionptr fp)
263 builtintable_entry *bte;
265 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
274 /* builtintable_get_automatic **************************************************
276 Finds an entry in the builtintable for functions which are replaced
277 automatically and returns the a pointer to the structure.
279 *******************************************************************************/
281 builtintable_entry *builtintable_get_automatic(s4 opcode)
283 builtintable_entry *first;
284 builtintable_entry *last;
285 builtintable_entry *middle;
289 /* calculate table size statically (`- 1' comment see builtintable.inc) */
291 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
293 first = builtintable_automatic;
294 last = builtintable_automatic + entries;
296 while (entries > 0) {
298 middle = first + half;
300 if (middle->opcode < opcode) {
307 return (first != last ? first : NULL);
311 /* builtintable_replace_function ***********************************************
315 *******************************************************************************/
317 #if defined(ENABLE_JIT)
318 bool builtintable_replace_function(void *iptr_)
321 builtintable_entry *bte;
324 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
326 /* get name and descriptor of the function */
329 case ICMD_INVOKESTATIC:
330 /* The instruction MUST be resolved, otherwise we run into
331 lazy loading troubles. Anyway, we should/can only replace
332 very VM-close functions. */
334 if (INSTRUCTION_IS_UNRESOLVED(iptr))
337 mr = iptr->sx.s23.s3.fmiref;
344 /* search the function table */
346 for (bte = builtintable_function; bte->fp != NULL; bte++) {
347 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
348 (mr->name == bte->name) &&
349 (mr->descriptor == bte->descriptor)) {
351 /* set the values in the instruction */
353 iptr->opc = bte->opcode;
354 iptr->sx.s23.s3.bte = bte;
355 if (bte->checkexception)
356 iptr->flags.bits |= INS_FLAG_CHECK;
358 iptr->flags.bits &= ~INS_FLAG_CHECK;
366 #endif /* defined(ENABLE_JIT) */
369 /*****************************************************************************
371 *****************************************************************************/
373 /* builtin_instanceof **********************************************************
375 Checks if an object is an instance of some given class (or subclass
376 of that class). If class is an interface, checks if the interface
379 Return value: 1 ... o is an instance of class or implements the interface
380 0 ... otherwise or if o == NULL
382 *******************************************************************************/
384 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
389 return class_isanysubclass(o->vftbl->class, class);
394 /* builtin_checkcast ***********************************************************
396 The same as builtin_instanceof except that 1 is returned when o ==
399 *******************************************************************************/
401 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
406 if (class_isanysubclass(o->vftbl->class, class))
413 /* builtin_descriptorscompatible ***********************************************
415 Checks if two array type descriptors are assignment compatible
417 Return value: 1 ... target = desc is possible
420 *******************************************************************************/
422 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
423 arraydescriptor *target)
428 if (desc->arraytype != target->arraytype)
431 if (desc->arraytype != ARRAYTYPE_OBJECT)
434 /* {both arrays are arrays of references} */
436 if (desc->dimension == target->dimension) {
437 /* an array which contains elements of interface types is
438 allowed to be casted to Object (JOWENN)*/
440 if ((desc->elementvftbl->baseval < 0) &&
441 (target->elementvftbl->baseval == 1))
444 return class_isanysubclass(desc->elementvftbl->class,
445 target->elementvftbl->class);
448 if (desc->dimension < target->dimension)
451 /* {desc has higher dimension than target} */
453 return class_isanysubclass(pseudo_class_Arraystub,
454 target->elementvftbl->class);
458 /* builtin_arraycheckcast ******************************************************
460 Checks if an object is really a subtype of the requested array
461 type. The object has to be an array to begin with. For simple
462 arrays (int, short, double, etc.) the types have to match exactly.
463 For arrays of objects, the type of elements in the array has to be
464 a subtype (or the same type) of the requested element type. For
465 arrays of arrays (which in turn can again be arrays of arrays), the
466 types at the lowest level have to satisfy the corresponding sub
469 *******************************************************************************/
471 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
473 arraydescriptor *desc;
478 desc = o->vftbl->arraydesc;
483 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
487 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
492 return builtin_arraycheckcast(o, targetclass);
496 /* builtin_throw_exception *****************************************************
498 Sets the exceptionptr with the thrown exception and prints some
499 debugging information. Called from asm_vm_call_method.
501 *******************************************************************************/
503 void *builtin_throw_exception(java_objectheader *xptr)
506 java_lang_Throwable *t;
512 t = (java_lang_Throwable *) xptr;
514 /* calculate message length */
516 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
520 utf_bytes(xptr->vftbl->class->name);
521 if (t->detailMessage) {
522 logtextlen += strlen(": ") +
523 u2_utflength(t->detailMessage->value->data
524 + t->detailMessage->offset,
525 t->detailMessage->count);
529 logtextlen += strlen("(nil)");
532 /* allocate memory */
534 dumpsize = dump_size();
536 logtext = DMNEW(char, logtextlen);
538 strcpy(logtext, "Builtin exception thrown: ");
541 utf_cat_classname(logtext, xptr->vftbl->class->name);
543 if (t->detailMessage) {
546 buf = javastring_tochar((java_objectheader *) t->detailMessage);
547 strcat(logtext, ": ");
548 strcat(logtext, buf);
549 MFREE(buf, char, strlen(buf) + 1);
553 strcat(logtext, "(nil)");
560 dump_release(dumpsize);
562 #endif /* !defined(NDEBUG) */
564 /* actually set the exception */
566 exceptions_set_exception(xptr);
568 /* Return a NULL pointer. This is required for vm_call_method to
569 check for an exception. This is for convenience. */
575 /* builtin_canstore ************************************************************
577 Checks, if an object can be stored in an array.
579 Return value: 1 ... possible
582 *******************************************************************************/
584 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
586 arraydescriptor *desc;
587 arraydescriptor *valuedesc;
588 vftbl_t *componentvftbl;
591 castinfo classvalues;
596 /* The following is guaranteed (by verifier checks):
598 * *) oa->...vftbl->arraydesc != NULL
599 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
600 * *) o->vftbl is not an interface vftbl
603 desc = oa->header.objheader.vftbl->arraydesc;
604 componentvftbl = desc->componentvftbl;
605 valuevftbl = o->vftbl;
607 if ((desc->dimension - 1) == 0) {
610 /* {oa is a one-dimensional array} */
611 /* {oa is an array of references} */
613 if (valuevftbl == componentvftbl)
616 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
618 if ((base = classvalues.super_baseval) <= 0)
619 /* an array of interface references */
620 return (valuevftbl->interfacetablelength > -base &&
621 valuevftbl->interfacetable[base] != NULL);
623 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
624 <= (unsigned) classvalues.super_diffval);
629 /* {oa has dimension > 1} */
630 /* {componentvftbl->arraydesc != NULL} */
632 /* check if o is an array */
634 if ((valuedesc = valuevftbl->arraydesc) == NULL)
637 /* {o is an array} */
639 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
643 /* This is an optimized version where a is guaranteed to be one-dimensional */
644 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
646 arraydescriptor *desc;
647 vftbl_t *elementvftbl;
651 castinfo classvalues;
655 /* The following is guaranteed (by verifier checks):
657 * *) a->...vftbl->arraydesc != NULL
658 * *) a->...vftbl->arraydesc->elementvftbl != NULL
659 * *) a->...vftbl->arraydesc->dimension == 1
660 * *) o->vftbl is not an interface vftbl
663 desc = a->header.objheader.vftbl->arraydesc;
664 elementvftbl = desc->elementvftbl;
665 valuevftbl = o->vftbl;
667 /* {a is a one-dimensional array} */
669 if (valuevftbl == elementvftbl)
672 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
674 if ((base = classvalues.super_baseval) <= 0)
675 /* an array of interface references */
676 return (valuevftbl->interfacetablelength > -base &&
677 valuevftbl->interfacetable[base] != NULL);
679 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
680 <= (unsigned) classvalues.super_diffval;
686 /* This is an optimized version where a is guaranteed to be a
687 * one-dimensional array of a class type */
688 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
690 vftbl_t *elementvftbl;
693 castinfo classvalues;
697 /* The following is guaranteed (by verifier checks):
699 * *) a->...vftbl->arraydesc != NULL
700 * *) a->...vftbl->arraydesc->elementvftbl != NULL
701 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
702 * *) a->...vftbl->arraydesc->dimension == 1
703 * *) o->vftbl is not an interface vftbl
706 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
707 valuevftbl = o->vftbl;
709 /* {a is a one-dimensional array} */
711 if (valuevftbl == elementvftbl)
714 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
716 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
717 <= (unsigned) classvalues.super_diffval;
723 /* builtin_new *****************************************************************
725 Creates a new instance of class c on the heap.
727 Return value: pointer to the object or NULL if no memory is
730 *******************************************************************************/
732 java_objectheader *builtin_new(classinfo *c)
734 java_objectheader *o;
735 #if defined(ENABLE_RT_TIMING)
736 struct timespec time_start, time_end;
738 #if defined(ENABLE_CYCLES_STATS)
739 u8 cycles_start, cycles_end;
742 RT_TIMING_GET_TIME(time_start);
743 CYCLES_STATS_GET(cycles_start);
745 /* is the class loaded */
747 assert(c->state & CLASS_LOADED);
749 /* check if we can instantiate this class */
751 if (c->flags & ACC_ABSTRACT) {
752 exceptions_throw_instantiationerror(c);
756 /* is the class linked */
758 if (!(c->state & CLASS_LINKED))
762 if (!(c->state & CLASS_INITIALIZED)) {
765 log_message_class("Initialize class (from builtin_new): ", c);
768 if (!initialize_class(c))
772 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
780 #if defined(ENABLE_THREADS)
781 lock_init_object_lock(o);
784 CYCLES_STATS_GET(cycles_end);
785 RT_TIMING_GET_TIME(time_end);
787 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
788 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
794 /* builtin_newarray ************************************************************
796 Creates an array with the given vftbl on the heap. This function
797 takes as class argument an array class.
799 Return value: pointer to the array or NULL if no memory is available
801 *******************************************************************************/
803 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
805 arraydescriptor *desc;
810 #if defined(ENABLE_RT_TIMING)
811 struct timespec time_start, time_end;
814 RT_TIMING_GET_TIME(time_start);
816 desc = arrayclass->vftbl->arraydesc;
817 dataoffset = desc->dataoffset;
818 componentsize = desc->componentsize;
821 exceptions_throw_negativearraysizeexception();
825 actualsize = dataoffset + size * componentsize;
827 /* check for overflow */
829 if (((u4) actualsize) < ((u4) size)) {
830 exceptions_throw_outofmemoryerror();
834 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
839 a->objheader.vftbl = arrayclass->vftbl;
841 #if defined(ENABLE_THREADS)
842 lock_init_object_lock(&a->objheader);
847 RT_TIMING_GET_TIME(time_end);
848 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
854 /* builtin_anewarray ***********************************************************
856 Creates an array of references to the given class type on the heap.
858 Return value: pointer to the array or NULL if no memory is
861 *******************************************************************************/
863 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
865 classinfo *arrayclass;
867 /* is class loaded */
869 assert(componentclass->state & CLASS_LOADED);
871 /* is class linked */
873 if (!(componentclass->state & CLASS_LINKED))
874 if (!link_class(componentclass))
877 arrayclass = class_array_of(componentclass, true);
882 return (java_objectarray *) builtin_newarray(size, arrayclass);
886 /* builtin_newarray_boolean ****************************************************
888 Creates an array of bytes on the heap. The array is designated as
889 an array of booleans (important for casts)
891 Return value: pointer to the array or NULL if no memory is
894 *******************************************************************************/
896 java_booleanarray *builtin_newarray_boolean(s4 size)
898 return (java_booleanarray *)
899 builtin_newarray(size,
900 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
904 /* builtin_newarray_byte *******************************************************
906 Creates an array of 8 bit Integers on the heap.
908 Return value: pointer to the array or NULL if no memory is
911 *******************************************************************************/
913 java_bytearray *builtin_newarray_byte(s4 size)
915 return (java_bytearray *)
916 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
920 /* builtin_newarray_char *******************************************************
922 Creates an array of characters on the heap.
924 Return value: pointer to the array or NULL if no memory is
927 *******************************************************************************/
929 java_chararray *builtin_newarray_char(s4 size)
931 return (java_chararray *)
932 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
936 /* builtin_newarray_short ******************************************************
938 Creates an array of 16 bit Integers on the heap.
940 Return value: pointer to the array or NULL if no memory is
943 *******************************************************************************/
945 java_shortarray *builtin_newarray_short(s4 size)
947 return (java_shortarray *)
948 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
952 /* builtin_newarray_int ********************************************************
954 Creates an array of 32 bit Integers on the heap.
956 Return value: pointer to the array or NULL if no memory is
959 *******************************************************************************/
961 java_intarray *builtin_newarray_int(s4 size)
963 return (java_intarray *)
964 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
968 /* builtin_newarray_long *******************************************************
970 Creates an array of 64 bit Integers on the heap.
972 Return value: pointer to the array or NULL if no memory is
975 *******************************************************************************/
977 java_longarray *builtin_newarray_long(s4 size)
979 return (java_longarray *)
980 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
984 /* builtin_newarray_float ******************************************************
986 Creates an array of 32 bit IEEE floats on the heap.
988 Return value: pointer to the array or NULL if no memory is
991 *******************************************************************************/
993 java_floatarray *builtin_newarray_float(s4 size)
995 return (java_floatarray *)
996 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1000 /* builtin_newarray_double *****************************************************
1002 Creates an array of 64 bit IEEE floats on the heap.
1004 Return value: pointer to the array or NULL if no memory is
1007 *******************************************************************************/
1009 java_doublearray *builtin_newarray_double(s4 size)
1011 return (java_doublearray *)
1012 builtin_newarray(size,
1013 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1017 /* builtin_multianewarray_intern ***********************************************
1019 Creates a multi-dimensional array on the heap. The dimensions are
1020 passed in an array of longs.
1023 n............number of dimensions to create
1024 arrayvftbl...vftbl of the array class
1025 dims.........array containing the size of each dimension to create
1027 Return value: pointer to the array or NULL if no memory is
1030 ******************************************************************************/
1032 static java_arrayheader *builtin_multianewarray_intern(int n,
1033 classinfo *arrayclass,
1037 java_arrayheader *a;
1038 classinfo *componentclass;
1041 /* create this dimension */
1043 size = (s4) dims[0];
1044 a = builtin_newarray(size, arrayclass);
1049 /* if this is the last dimension return */
1054 /* get the class of the components to create */
1056 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1058 /* The verifier guarantees that the dimension count is in the range. */
1060 /* create the component arrays */
1062 for (i = 0; i < size; i++) {
1063 java_arrayheader *ea =
1064 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1065 /* we save an s4 to a s8 slot, 8-byte aligned */
1067 builtin_multianewarray_intern(n, componentclass, dims + 2);
1069 builtin_multianewarray_intern(n, componentclass, dims + 1);
1075 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1082 /* builtin_multianewarray ******************************************************
1084 Wrapper for builtin_multianewarray_intern which checks all
1085 dimensions before we start allocating.
1087 ******************************************************************************/
1089 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1095 /* check all dimensions before doing anything */
1097 for (i = 0; i < n; i++) {
1098 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1099 /* we save an s4 to a s8 slot, 8-byte aligned */
1100 size = (s4) dims[i * 2];
1102 size = (s4) dims[i];
1106 exceptions_throw_negativearraysizeexception();
1111 /* now call the real function */
1113 return builtin_multianewarray_intern(n, arrayclass, dims);
1117 /*****************************************************************************
1120 Various functions for printing a message at method entry or exit (for
1123 *****************************************************************************/
1125 #if !defined(NDEBUG)
1126 static s4 methodindent = 0;
1127 static u4 callcount = 0;
1129 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1139 if (opt_verbosecall && indent)
1142 /* calculate message length */
1146 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1149 logtextlen = strlen("Some Throwable");
1152 logtextlen += strlen(" thrown in ");
1156 utf_bytes(m->class->name) +
1158 utf_bytes(m->name) +
1159 utf_bytes(m->descriptor) +
1160 strlen("(NOSYNC,NATIVE");
1162 #if SIZEOF_VOID_P == 8
1164 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1166 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1169 if (m->class->sourcefile == NULL)
1170 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1172 logtextlen += utf_bytes(m->class->sourcefile);
1174 logtextlen += strlen(":65536)");
1178 logtextlen += strlen("call_java_method");
1181 logtextlen += strlen("0");
1183 /* allocate memory */
1185 dumpsize = dump_size();
1187 logtext = DMNEW(char, logtextlen);
1190 strcpy(logtext, "Exception ");
1191 utf_cat_classname(logtext, xptr->vftbl->class->name);
1194 strcpy(logtext, "Some Throwable");
1197 strcat(logtext, " thrown in ");
1200 utf_cat_classname(logtext, m->class->name);
1201 strcat(logtext, ".");
1202 utf_cat(logtext, m->name);
1203 utf_cat(logtext, m->descriptor);
1205 if (m->flags & ACC_SYNCHRONIZED)
1206 strcat(logtext, "(SYNC");
1208 strcat(logtext, "(NOSYNC");
1210 if (m->flags & ACC_NATIVE) {
1211 strcat(logtext, ",NATIVE");
1215 #if SIZEOF_VOID_P == 8
1216 sprintf(logtext + strlen(logtext),
1217 ")(0x%016lx) at position 0x%016lx",
1218 (ptrint) code->entrypoint, (ptrint) pos);
1220 sprintf(logtext + strlen(logtext),
1221 ")(0x%08x) at position 0x%08x",
1222 (ptrint) code->entrypoint, (ptrint) pos);
1227 /* XXX preliminary: This should get the actual codeinfo */
1228 /* in which the exception happened. */
1231 #if SIZEOF_VOID_P == 8
1232 sprintf(logtext + strlen(logtext),
1233 ")(0x%016lx) at position 0x%016lx (",
1234 (ptrint) code->entrypoint, (ptrint) pos);
1236 sprintf(logtext + strlen(logtext),
1237 ")(0x%08x) at position 0x%08x (",
1238 (ptrint) code->entrypoint, (ptrint) pos);
1241 if (m->class->sourcefile == NULL)
1242 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1244 utf_cat(logtext, m->class->sourcefile);
1246 sprintf(logtext + strlen(logtext), ":%d)", 0);
1250 strcat(logtext, "call_java_method");
1254 /* release memory */
1256 dump_release(dumpsize);
1260 #endif /* !defined(NDEBUG) */
1263 /* builtin_print_argument ******************************************************
1265 Prints arguments and return values for the call trace.
1267 *******************************************************************************/
1269 #if !defined(NDEBUG)
1270 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1271 typedesc *paramtype, s8 value)
1274 java_objectheader *o;
1275 java_lang_String *s;
1280 switch (paramtype->type) {
1283 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1288 #if SIZEOF_VOID_P == 4
1289 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1291 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1297 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1302 #if SIZEOF_VOID_P == 4
1303 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1305 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1310 #if SIZEOF_VOID_P == 4
1311 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1313 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1316 /* cast to java.lang.Object */
1318 o = (java_objectheader *) (ptrint) value;
1320 /* check return argument for java.lang.Class or java.lang.String */
1323 if (o->vftbl->class == class_java_lang_String) {
1324 /* get java.lang.String object and the length of the
1327 s = (java_lang_String *) o;
1329 u = javastring_toutf(s, false);
1331 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1333 /* realloc memory for string length */
1335 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1338 /* convert to utf8 string and strcat it to the logtext */
1340 strcat(logtext, " (String = \"");
1341 utf_cat(logtext, u);
1342 strcat(logtext, "\")");
1345 if (o->vftbl->class == class_java_lang_Class) {
1346 /* if the object returned is a java.lang.Class
1347 cast it to classinfo structure and get the name
1350 c = (classinfo *) o;
1355 /* if the object returned is not a java.lang.String or
1356 a java.lang.Class just print the name of the class */
1358 u = o->vftbl->class->name;
1361 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1363 /* realloc memory for string length */
1365 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1368 /* strcat to the logtext */
1370 strcat(logtext, " (Class = \"");
1371 utf_cat_classname(logtext, u);
1372 strcat(logtext, "\")");
1379 #endif /* !defined(NDEBUG) */
1382 /* builtin_verbosecall_enter ***************************************************
1384 Print method call with arguments for -verbose:call.
1386 *******************************************************************************/
1388 #if !defined(NDEBUG)
1390 #ifdef TRACE_ARGS_NUM
1391 void builtin_verbosecall_enter(s8 a0, s8 a1,
1392 # if TRACE_ARGS_NUM >= 4
1395 # if TRACE_ARGS_NUM >= 6
1398 # if TRACE_ARGS_NUM == 8
1412 /* calculate message length */
1415 strlen("4294967295 ") +
1416 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1418 strlen("called: ") +
1419 utf_bytes(m->class->name) +
1421 utf_bytes(m->name) +
1422 utf_bytes(m->descriptor);
1424 /* Actually it's not possible to have all flags printed, but:
1429 strlen(" PRIVATE") +
1430 strlen(" PROTECTED") +
1433 strlen(" SYNCHRONIZED") +
1434 strlen(" VOLATILE") +
1435 strlen(" TRANSIENT") +
1437 strlen(" INTERFACE") +
1438 strlen(" ABSTRACT");
1440 /* add maximal argument length */
1444 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1445 strlen("...(255)") +
1448 /* allocate memory */
1450 dumpsize = dump_size();
1452 logtext = DMNEW(char, logtextlen);
1456 sprintf(logtext, "%10d ", callcount);
1457 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1459 pos = strlen(logtext);
1461 for (i = 0; i < methodindent; i++)
1462 logtext[pos++] = '\t';
1464 strcpy(logtext + pos, "called: ");
1466 utf_cat_classname(logtext, m->class->name);
1467 strcat(logtext, ".");
1468 utf_cat(logtext, m->name);
1469 utf_cat(logtext, m->descriptor);
1471 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1472 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1473 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1474 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1475 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1476 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1477 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1478 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1479 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1480 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1481 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1483 strcat(logtext, "(");
1485 if (md->paramcount >= 1) {
1486 logtext = builtin_print_argument(logtext, &logtextlen,
1487 &md->paramtypes[0], a0);
1490 if (md->paramcount >= 2) {
1491 strcat(logtext, ", ");
1493 logtext = builtin_print_argument(logtext, &logtextlen,
1494 &md->paramtypes[1], a1);
1497 #if TRACE_ARGS_NUM >= 4
1498 if (md->paramcount >= 3) {
1499 strcat(logtext, ", ");
1501 logtext = builtin_print_argument(logtext, &logtextlen,
1502 &md->paramtypes[2], a2);
1505 if (md->paramcount >= 4) {
1506 strcat(logtext, ", ");
1508 logtext = builtin_print_argument(logtext, &logtextlen,
1509 &md->paramtypes[3], a3);
1513 #if TRACE_ARGS_NUM >= 6
1514 if (md->paramcount >= 5) {
1515 strcat(logtext, ", ");
1517 logtext = builtin_print_argument(logtext, &logtextlen,
1518 &md->paramtypes[4], a4);
1521 if (md->paramcount >= 6) {
1522 strcat(logtext, ", ");
1524 logtext = builtin_print_argument(logtext, &logtextlen,
1525 &md->paramtypes[5], a5);
1529 #if TRACE_ARGS_NUM == 8
1530 if (md->paramcount >= 7) {
1531 strcat(logtext, ", ");
1533 logtext = builtin_print_argument(logtext, &logtextlen,
1534 &md->paramtypes[6], a6);
1537 if (md->paramcount >= 8) {
1538 strcat(logtext, ", ");
1540 logtext = builtin_print_argument(logtext, &logtextlen,
1541 &md->paramtypes[7], a7);
1545 if (md->paramcount > 8) {
1546 sprintf(logtext + strlen(logtext), ", ...(%d)",
1547 md->paramcount - TRACE_ARGS_NUM);
1550 strcat(logtext, ")");
1554 /* release memory */
1556 dump_release(dumpsize);
1561 #endif /* !defined(NDEBUG) */
1564 /* builtin_verbosecall_exit ****************************************************
1566 Print method exit for -verbose:call.
1568 *******************************************************************************/
1570 #if !defined(NDEBUG)
1571 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1583 /* calculate message length */
1586 strlen("4294967295 ") +
1587 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1589 strlen("finished: ") +
1590 utf_bytes(m->class->name) +
1592 utf_bytes(m->name) +
1593 utf_bytes(m->descriptor) +
1594 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1596 /* add maximal argument length */
1598 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1600 /* allocate memory */
1602 dumpsize = dump_size();
1604 logtext = DMNEW(char, logtextlen);
1606 /* outdent the log message */
1611 log_text("WARNING: unmatched methodindent--");
1613 /* generate the message */
1615 sprintf(logtext, " ");
1616 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1618 pos = strlen(logtext);
1620 for (i = 0; i < methodindent; i++)
1621 logtext[pos++] = '\t';
1623 strcpy(logtext + pos, "finished: ");
1624 utf_cat_classname(logtext, m->class->name);
1625 strcat(logtext, ".");
1626 utf_cat(logtext, m->name);
1627 utf_cat(logtext, m->descriptor);
1629 if (!IS_VOID_TYPE(md->returntype.type)) {
1630 strcat(logtext, "->");
1632 switch (md->returntype.type) {
1649 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1654 /* release memory */
1656 dump_release(dumpsize);
1658 #endif /* !defined(NDEBUG) */
1661 #if defined(ENABLE_CYCLES_STATS)
1662 void builtin_print_cycles_stats(FILE *file)
1664 fprintf(file,"builtin cylce count statistics:\n");
1666 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1667 CYCLES_STATS_PRINT(builtin_new ,file);
1671 #endif /* defined(ENABLE_CYCLES_STATS) */
1674 /*****************************************************************************
1675 MISCELLANEOUS HELPER FUNCTIONS
1676 *****************************************************************************/
1680 /*********** Functions for integer divisions *****************************
1682 On some systems (eg. DEC ALPHA), integer division is not supported by the
1683 CPU. These helper functions implement the missing functionality.
1685 ******************************************************************************/
1687 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1688 s4 builtin_idiv(s4 a, s4 b)
1697 s4 builtin_irem(s4 a, s4 b)
1705 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1708 /* functions for long arithmetics **********************************************
1710 On systems where 64 bit Integers are not supported by the CPU,
1711 these functions are needed.
1713 ******************************************************************************/
1715 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1716 s8 builtin_ladd(s8 a, s8 b)
1729 s8 builtin_lsub(s8 a, s8 b)
1742 s8 builtin_lneg(s8 a)
1754 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1757 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1758 s8 builtin_lmul(s8 a, s8 b)
1770 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1773 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1774 s8 builtin_ldiv(s8 a, s8 b)
1787 s8 builtin_lrem(s8 a, s8 b)
1799 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1802 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1803 s8 builtin_lshl(s8 a, s4 b)
1816 s8 builtin_lshr(s8 a, s4 b)
1829 s8 builtin_lushr(s8 a, s4 b)
1834 c = ((u8) a) >> (b & 63);
1841 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1844 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1845 s8 builtin_land(s8 a, s8 b)
1858 s8 builtin_lor(s8 a, s8 b)
1871 s8 builtin_lxor(s8 a, s8 b)
1883 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1886 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1887 s4 builtin_lcmp(s8 a, s8 b)
1901 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1904 /* functions for unsupported floating instructions ****************************/
1906 /* used to convert FLT_xxx defines into float values */
1908 static inline float intBitsToFloat(s4 i)
1917 /* used to convert DBL_xxx defines into double values */
1919 static inline float longBitsToDouble(s8 l)
1929 float builtin_fadd(float a, float b)
1931 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1932 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1943 if (copysignf(1.0, a) == copysignf(1.0, b))
1946 return intBitsToFloat(FLT_NAN);
1952 float builtin_fsub(float a, float b)
1954 return builtin_fadd(a, builtin_fneg(b));
1958 float builtin_fmul(float a, float b)
1960 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1961 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1963 if (finitef(b)) return a * b;
1965 if (a == 0) return intBitsToFloat(FLT_NAN);
1966 else return copysignf(b, copysignf(1.0, b)*a);
1971 if (b == 0) return intBitsToFloat(FLT_NAN);
1972 else return copysignf(a, copysignf(1.0, a)*b);
1975 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1981 /* builtin_ddiv ****************************************************************
1983 Implementation as described in VM Spec.
1985 *******************************************************************************/
1987 float builtin_fdiv(float a, float b)
1991 /* If neither value1' nor value2' is NaN, the sign of the result */
1992 /* is positive if both values have the same sign, negative if the */
1993 /* values have different signs. */
1999 /* If either value1' or value2' is NaN, the result is NaN. */
2001 return intBitsToFloat(FLT_NAN);
2004 /* Division of a finite value by an infinity results in a */
2005 /* signed zero, with the sign-producing rule just given. */
2007 /* is sign equal? */
2009 if (copysignf(1.0, a) == copysignf(1.0, b))
2018 /* If either value1' or value2' is NaN, the result is NaN. */
2020 return intBitsToFloat(FLT_NAN);
2022 } else if (finitef(b)) {
2023 /* Division of an infinity by a finite value results in a signed */
2024 /* infinity, with the sign-producing rule just given. */
2026 /* is sign equal? */
2028 if (copysignf(1.0, a) == copysignf(1.0, b))
2029 return intBitsToFloat(FLT_POSINF);
2031 return intBitsToFloat(FLT_NEGINF);
2034 /* Division of an infinity by an infinity results in NaN. */
2036 return intBitsToFloat(FLT_NAN);
2042 float builtin_fneg(float a)
2044 if (isnanf(a)) return a;
2046 if (finitef(a)) return -a;
2047 else return copysignf(a, -copysignf(1.0, a));
2050 #endif /* !SUPPORT_FLOAT */
2053 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2054 s4 builtin_fcmpl(float a, float b)
2062 if (!finitef(a) || !finitef(b)) {
2063 a = finitef(a) ? 0 : copysignf(1.0, a);
2064 b = finitef(b) ? 0 : copysignf(1.0, b);
2077 s4 builtin_fcmpg(float a, float b)
2079 if (isnanf(a)) return 1;
2080 if (isnanf(b)) return 1;
2081 if (!finitef(a) || !finitef(b)) {
2082 a = finitef(a) ? 0 : copysignf(1.0, a);
2083 b = finitef(b) ? 0 : copysignf(1.0, b);
2085 if (a > b) return 1;
2086 if (a == b) return 0;
2089 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2092 float builtin_frem(float a, float b)
2098 /* functions for unsupported double instructions ******************************/
2101 double builtin_dadd(double a, double b)
2103 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2104 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2106 if (finite(b)) return a + b;
2110 if (finite(b)) return a;
2112 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2113 else return longBitsToDouble(DBL_NAN);
2119 double builtin_dsub(double a, double b)
2121 return builtin_dadd(a, builtin_dneg(b));
2125 double builtin_dmul(double a, double b)
2127 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2128 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2130 if (finite(b)) return a * b;
2132 if (a == 0) return longBitsToDouble(DBL_NAN);
2133 else return copysign(b, copysign(1.0, b) * a);
2138 if (b == 0) return longBitsToDouble(DBL_NAN);
2139 else return copysign(a, copysign(1.0, a) * b);
2142 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2148 /* builtin_ddiv ****************************************************************
2150 Implementation as described in VM Spec.
2152 *******************************************************************************/
2154 double builtin_ddiv(double a, double b)
2158 /* If neither value1' nor value2' is NaN, the sign of the result */
2159 /* is positive if both values have the same sign, negative if the */
2160 /* values have different signs. */
2166 /* If either value1' or value2' is NaN, the result is NaN. */
2168 return longBitsToDouble(DBL_NAN);
2171 /* Division of a finite value by an infinity results in a */
2172 /* signed zero, with the sign-producing rule just given. */
2174 /* is sign equal? */
2176 if (copysign(1.0, a) == copysign(1.0, b))
2185 /* If either value1' or value2' is NaN, the result is NaN. */
2187 return longBitsToDouble(DBL_NAN);
2189 } else if (finite(b)) {
2190 /* Division of an infinity by a finite value results in a signed */
2191 /* infinity, with the sign-producing rule just given. */
2193 /* is sign equal? */
2195 if (copysign(1.0, a) == copysign(1.0, b))
2196 return longBitsToDouble(DBL_POSINF);
2198 return longBitsToDouble(DBL_NEGINF);
2201 /* Division of an infinity by an infinity results in NaN. */
2203 return longBitsToDouble(DBL_NAN);
2209 /* builtin_dneg ****************************************************************
2211 Implemented as described in VM Spec.
2213 *******************************************************************************/
2215 double builtin_dneg(double a)
2218 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2225 /* If the operand is a zero, the result is the zero of opposite */
2231 /* If the operand is an infinity, the result is the infinity of */
2232 /* opposite sign. */
2234 return copysign(a, -copysign(1.0, a));
2238 #endif /* !SUPPORT_DOUBLE */
2241 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2242 s4 builtin_dcmpl(double a, double b)
2250 if (!finite(a) || !finite(b)) {
2251 a = finite(a) ? 0 : copysign(1.0, a);
2252 b = finite(b) ? 0 : copysign(1.0, b);
2265 s4 builtin_dcmpg(double a, double b)
2273 if (!finite(a) || !finite(b)) {
2274 a = finite(a) ? 0 : copysign(1.0, a);
2275 b = finite(b) ? 0 : copysign(1.0, b);
2286 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2289 double builtin_drem(double a, double b)
2295 /* conversion operations ******************************************************/
2298 s8 builtin_i2l(s4 i)
2310 s4 builtin_l2i(s8 l)
2321 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2322 float builtin_i2f(s4 a)
2324 float f = (float) a;
2327 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2330 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2331 double builtin_i2d(s4 a)
2333 double d = (double) a;
2336 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2339 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2340 float builtin_l2f(s8 a)
2343 float f = (float) a;
2349 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2352 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2353 double builtin_l2d(s8 a)
2356 double d = (double) a;
2362 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2365 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2366 s4 builtin_f2i(float a)
2370 i = builtin_d2i((double) a);
2381 if (a < (-2147483648))
2382 return (-2147483648);
2385 f = copysignf((float) 1.0, a);
2388 return (-2147483648); */
2390 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2393 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2394 s8 builtin_f2l(float a)
2398 l = builtin_d2l((double) a);
2405 if (a > 9223372036854775807L)
2406 return 9223372036854775807L;
2407 if (a < (-9223372036854775808L))
2408 return (-9223372036854775808L);
2413 f = copysignf((float) 1.0, a);
2415 return 9223372036854775807L;
2416 return (-9223372036854775808L); */
2418 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2421 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2422 s4 builtin_d2i(double a)
2427 if (a >= 2147483647)
2429 if (a <= (-2147483647-1))
2430 return (-2147483647-1);
2435 d = copysign(1.0, a);
2438 return (-2147483647-1);
2440 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2443 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2444 s8 builtin_d2l(double a)
2449 if (a >= 9223372036854775807LL)
2450 return 9223372036854775807LL;
2451 if (a <= (-9223372036854775807LL-1))
2452 return (-9223372036854775807LL-1);
2457 d = copysign(1.0, a);
2459 return 9223372036854775807LL;
2460 return (-9223372036854775807LL-1);
2462 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2465 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2466 double builtin_f2d(float a)
2468 if (finitef(a)) return (double) a;
2471 return longBitsToDouble(DBL_NAN);
2473 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2477 float builtin_d2f(double a)
2483 return intBitsToFloat(FLT_NAN);
2485 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2488 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2491 /* builtin_arraycopy ***********************************************************
2493 Builtin for java.lang.System.arraycopy.
2495 ATTENTION: This builtin function returns a boolean value to signal
2496 the ICMD_BUILTIN if there was an exception.
2498 *******************************************************************************/
2500 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2501 java_arrayheader *dest, s4 destStart, s4 len)
2503 arraydescriptor *sdesc;
2504 arraydescriptor *ddesc;
2507 if ((src == NULL) || (dest == NULL)) {
2508 exceptions_throw_nullpointerexception();
2512 sdesc = src->objheader.vftbl->arraydesc;
2513 ddesc = dest->objheader.vftbl->arraydesc;
2515 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2516 exceptions_throw_arraystoreexception();
2520 /* we try to throw exception with the same message as SUN does */
2522 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2523 (srcStart + len < 0) || (srcStart + len > src->size) ||
2524 (destStart + len < 0) || (destStart + len > dest->size)) {
2525 exceptions_throw_arrayindexoutofboundsexception();
2529 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2530 /* We copy primitive values or references of exactly the same type */
2532 s4 dataoffset = sdesc->dataoffset;
2533 s4 componentsize = sdesc->componentsize;
2535 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2536 ((u1 *) src) + dataoffset + componentsize * srcStart,
2537 (size_t) len * componentsize);
2540 /* We copy references of different type */
2542 java_objectarray *oas = (java_objectarray *) src;
2543 java_objectarray *oad = (java_objectarray *) dest;
2545 if (destStart <= srcStart) {
2546 for (i = 0; i < len; i++) {
2547 java_objectheader *o = oas->data[srcStart + i];
2549 if (!builtin_canstore(oad, o)) {
2550 exceptions_throw_arraystoreexception();
2554 oad->data[destStart + i] = o;
2558 /* XXX this does not completely obey the specification!
2559 If an exception is thrown only the elements above the
2560 current index have been copied. The specification
2561 requires that only the elements *below* the current
2562 index have been copied before the throw. */
2564 for (i = len - 1; i >= 0; i--) {
2565 java_objectheader *o = oas->data[srcStart + i];
2567 if (!builtin_canstore(oad, o)) {
2568 exceptions_throw_arraystoreexception();
2572 oad->data[destStart + i] = o;
2581 /* builtin_currenttimemillis ***************************************************
2583 Return the current time in milliseconds.
2585 *******************************************************************************/
2587 s8 builtin_currenttimemillis(void)
2592 if (gettimeofday(&tv, NULL) == -1)
2593 vm_abort("gettimeofday failed: %s", strerror(errno));
2595 result = (s8) tv.tv_sec;
2597 result += (tv.tv_usec / 1000);
2603 /* builtin_clone ***************************************************************
2605 Function for cloning objects or arrays.
2607 *******************************************************************************/
2609 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2611 arraydescriptor *ad;
2612 java_arrayheader *ah;
2615 java_objectheader *co; /* cloned object header */
2617 /* get the array descriptor */
2619 ad = o->vftbl->arraydesc;
2621 /* we are cloning an array */
2624 ah = (java_arrayheader *) o;
2626 size = ad->dataoffset + ad->componentsize * ah->size;
2628 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2633 MCOPY(co, o, u1, size);
2635 #if defined(ENABLE_GC_CACAO)
2636 heap_init_objectheader(co, size);
2639 #if defined(ENABLE_THREADS)
2640 lock_init_object_lock(co);
2646 /* we are cloning a non-array */
2648 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2649 exceptions_throw_clonenotsupportedexception();
2653 /* get the class of the object */
2655 c = o->vftbl->class;
2657 /* create new object */
2659 co = builtin_new(c);
2664 MCOPY(co, o, u1, c->instancesize);
2666 #if defined(ENABLE_GC_CACAO)
2667 heap_init_objectheader(co, c->instancesize);
2670 #if defined(ENABLE_THREADS)
2671 lock_init_object_lock(co);
2679 * These are local overrides for various environment variables in Emacs.
2680 * Please do not remove this and leave it at the end of the file, where
2681 * Emacs will automagically detect them.
2682 * ---------------------------------------------------------------------
2685 * indent-tabs-mode: t
2689 * vim:noexpandtab:sw=4:ts=4: