1 /* src/vm/builtin.c - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
34 Contains C functions for JavaVM Instructions that cannot be
35 translated to machine language directly. Consequently, the
36 generated machine code for these instructions contains function
37 calls instead of machine instructions, using the C calling
40 $Id: builtin.c 5332 2006-09-05 19:38:28Z twisti $
59 #include "fdlibm/fdlibm.h"
62 #include "mm/memory.h"
63 #include "native/native.h"
64 #include "native/include/java_lang_Cloneable.h"
65 #include "native/include/java_lang_Object.h" /* required by VMObject */
66 #include "native/include/java_lang_VMObject.h"
68 #if defined(ENABLE_THREADS)
69 # include "threads/native/threads.h"
72 #include "toolbox/logging.h"
73 #include "toolbox/util.h"
74 #include "vm/builtin.h"
76 #include "vm/exceptions.h"
77 #include "vm/global.h"
78 #include "vm/initialize.h"
79 #include "vm/loader.h"
80 #include "vm/options.h"
81 #include "vm/stringlocal.h"
82 #include "vm/jit/asmpart.h"
83 #include "vm/jit/patcher.h"
84 #include "vm/rt-timing.h"
85 #include "vm/cycles-stats.h"
88 /* include builtin tables *****************************************************/
90 #include "vm/builtintable.inc"
93 CYCLES_STATS_DECLARE(builtin_new ,100,5)
94 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
96 /* builtintable_init ***********************************************************
98 Parse the descriptors of builtin functions and create the parsed
101 *******************************************************************************/
103 static bool builtintable_init(void)
105 descriptor_pool *descpool;
107 builtintable_entry *bte;
109 /* mark start of dump memory area */
111 dumpsize = dump_size();
113 /* create a new descriptor pool */
115 descpool = descriptor_pool_new(class_java_lang_Object);
117 /* add some entries we need */
119 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
122 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
125 /* first add all descriptors to the pool */
127 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
128 /* create a utf8 string from descriptor */
130 bte->descriptor = utf_new_char(bte->cdescriptor);
132 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
133 /* release dump area */
135 dump_release(dumpsize);
141 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
142 bte->descriptor = utf_new_char(bte->cdescriptor);
144 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
145 dump_release(dumpsize);
150 for (bte = builtintable_function; bte->fp != NULL; bte++) {
151 bte->classname = utf_new_char(bte->cclassname);
152 bte->name = utf_new_char(bte->cname);
153 bte->descriptor = utf_new_char(bte->cdescriptor);
155 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
156 dump_release(dumpsize);
161 /* create the class reference table */
163 (void) descriptor_pool_create_classrefs(descpool, NULL);
165 /* allocate space for the parsed descriptors */
167 descriptor_pool_alloc_parsed_descriptors(descpool);
169 /* now parse all descriptors */
171 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
172 /* parse the descriptor, builtin is always static (no `this' pointer) */
174 bte->md = descriptor_pool_parse_method_descriptor(descpool,
179 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
180 bte->md = descriptor_pool_parse_method_descriptor(descpool,
185 for (bte = builtintable_function; bte->fp != NULL; bte++) {
186 bte->md = descriptor_pool_parse_method_descriptor(descpool,
191 /* release dump area */
193 dump_release(dumpsize);
199 /* builtintable_comparator *****************************************************
201 qsort comparator for the automatic builtin table.
203 *******************************************************************************/
205 static int builtintable_comparator(const void *a, const void *b)
207 builtintable_entry *bte1;
208 builtintable_entry *bte2;
210 bte1 = (builtintable_entry *) a;
211 bte2 = (builtintable_entry *) b;
213 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
217 /* builtintable_sort_automatic *************************************************
219 Sorts the automatic builtin table.
221 *******************************************************************************/
223 static void builtintable_sort_automatic(void)
227 /* calculate table size statically (`- 1' comment see builtintable.inc) */
229 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
231 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
232 builtintable_comparator);
236 /* builtin_init ****************************************************************
238 Initialize the global table of builtin functions.
240 *******************************************************************************/
242 bool builtin_init(void)
244 /* initialize the builtin tables */
246 if (!builtintable_init())
249 /* sort builtin tables */
251 builtintable_sort_automatic();
257 /* builtintable_get_internal ***************************************************
259 Finds an entry in the builtintable for internal functions and
260 returns the a pointer to the structure.
262 *******************************************************************************/
264 builtintable_entry *builtintable_get_internal(functionptr fp)
266 builtintable_entry *bte;
268 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
277 /* builtintable_get_automatic **************************************************
279 Finds an entry in the builtintable for functions which are replaced
280 automatically and returns the a pointer to the structure.
282 *******************************************************************************/
284 builtintable_entry *builtintable_get_automatic(s4 opcode)
286 builtintable_entry *first;
287 builtintable_entry *last;
288 builtintable_entry *middle;
292 /* calculate table size statically (`- 1' comment see builtintable.inc) */
294 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
296 first = builtintable_automatic;
297 last = builtintable_automatic + entries;
299 while (entries > 0) {
301 middle = first + half;
303 if (middle->opcode < opcode) {
310 return (first != last ? first : NULL);
314 /* builtintable_replace_function ***********************************************
318 *******************************************************************************/
320 bool builtintable_replace_function(instruction *iptr)
323 builtintable_entry *bte;
325 /* get name and descriptor of the function */
328 case ICMD_INVOKESTATIC:
329 /* The instruction MUST be resolved, otherwise we run into
330 lazy loading troubles. Anyway, we should/can only replace
331 very VM-close functions. */
333 if (INSTRUCTION_IS_UNRESOLVED(iptr))
336 mr = iptr->sx.s23.s3.fmiref;
343 /* search the function table */
345 for (bte = builtintable_function; bte->fp != NULL; bte++) {
346 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
347 (mr->name == bte->name) &&
348 (mr->descriptor == bte->descriptor)) {
350 /* set the values in the instruction */
352 iptr->opc = bte->opcode;
353 iptr->sx.s23.s3.bte = bte;
354 if (bte->checkexception)
355 iptr->flags.bits &= ~INS_FLAG_NOCHECK;
357 iptr->flags.bits |= INS_FLAG_NOCHECK;
367 /*****************************************************************************
369 *****************************************************************************/
373 /*************** internal function: builtin_isanysubclass *********************
375 Checks a subclass relation between two classes. Implemented interfaces
376 are interpreted as super classes.
377 Return value: 1 ... sub is subclass of super
380 *****************************************************************************/
381 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
384 castinfo classvalues;
389 if (super->flags & ACC_INTERFACE) {
390 res = (sub->vftbl->interfacetablelength > super->index) &&
391 (sub->vftbl->interfacetable[-super->index] != NULL);
394 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
396 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
397 (u4) classvalues.super_diffval;
404 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
408 castinfo classvalues;
413 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
415 if ((base = classvalues.super_baseval) <= 0) {
416 /* super is an interface */
417 res = (sub->interfacetablelength > -base) &&
418 (sub->interfacetable[base] != NULL);
420 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
421 <= (u4) classvalues.super_diffval;
428 /****************** function: builtin_instanceof *****************************
430 Checks if an object is an instance of some given class (or subclass of
431 that class). If class is an interface, checks if the interface is
433 Return value: 1 ... obj is an instance of class or implements the interface
434 0 ... otherwise or if obj == NULL
436 *****************************************************************************/
438 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
443 return builtin_isanysubclass(obj->vftbl->class, class);
448 /**************** function: builtin_checkcast *******************************
450 The same as builtin_instanceof except that 1 is returned when
453 ****************************************************************************/
455 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
460 if (builtin_isanysubclass(obj->vftbl->class, class))
467 /* builtin_descriptorscompatible ***********************************************
469 Checks if two array type descriptors are assignment compatible
471 Return value: 1 ... target = desc is possible
474 *******************************************************************************/
476 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
477 arraydescriptor *target)
482 if (desc->arraytype != target->arraytype)
485 if (desc->arraytype != ARRAYTYPE_OBJECT)
488 /* {both arrays are arrays of references} */
490 if (desc->dimension == target->dimension) {
491 /* an array which contains elements of interface types is
492 allowed to be casted to Object (JOWENN)*/
494 if ((desc->elementvftbl->baseval < 0) &&
495 (target->elementvftbl->baseval == 1))
498 return builtin_isanysubclass_vftbl(desc->elementvftbl,
499 target->elementvftbl);
502 if (desc->dimension < target->dimension)
505 /* {desc has higher dimension than target} */
507 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
508 target->elementvftbl);
512 /* builtin_arraycheckcast ******************************************************
514 Checks if an object is really a subtype of the requested array
515 type. The object has to be an array to begin with. For simple
516 arrays (int, short, double, etc.) the types have to match exactly.
517 For arrays of objects, the type of elements in the array has to be
518 a subtype (or the same type) of the requested element type. For
519 arrays of arrays (which in turn can again be arrays of arrays), the
520 types at the lowest level have to satisfy the corresponding sub
523 *******************************************************************************/
525 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
527 arraydescriptor *desc;
532 if ((desc = o->vftbl->arraydesc) == NULL)
535 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
539 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
544 return builtin_arraycheckcast(o, targetclass);
548 /* builtin_throw_exception *****************************************************
550 Sets the exceptionptr with the thrown exception and prints some
551 debugging information. Called from asm_vm_call_method.
553 *******************************************************************************/
555 void *builtin_throw_exception(java_objectheader *xptr)
558 java_lang_Throwable *t;
564 t = (java_lang_Throwable *) xptr;
566 /* calculate message length */
568 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
572 utf_bytes(xptr->vftbl->class->name);
573 if (t->detailMessage) {
574 logtextlen += strlen(": ") +
575 u2_utflength(t->detailMessage->value->data
576 + t->detailMessage->offset,
577 t->detailMessage->count);
581 logtextlen += strlen("(nil)");
584 /* allocate memory */
586 dumpsize = dump_size();
588 logtext = DMNEW(char, logtextlen);
590 strcpy(logtext, "Builtin exception thrown: ");
593 utf_cat_classname(logtext, xptr->vftbl->class->name);
595 if (t->detailMessage) {
598 buf = javastring_tochar((java_objectheader *) t->detailMessage);
599 strcat(logtext, ": ");
600 strcat(logtext, buf);
601 MFREE(buf, char, strlen(buf) + 1);
605 strcat(logtext, "(nil)");
612 dump_release(dumpsize);
614 #endif /* !defined(NDEBUG) */
616 /* actually set the exception */
618 *exceptionptr = xptr;
620 /* Return a NULL pointer. This is required for vm_call_method to
621 check for an exception. This is for convenience. */
627 /* builtin_canstore ************************************************************
629 Checks, if an object can be stored in an array.
631 Return value: 1 ... possible
634 *******************************************************************************/
636 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
638 arraydescriptor *desc;
639 arraydescriptor *valuedesc;
640 vftbl_t *componentvftbl;
643 castinfo classvalues;
648 /* The following is guaranteed (by verifier checks):
650 * *) oa->...vftbl->arraydesc != NULL
651 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
652 * *) o->vftbl is not an interface vftbl
655 desc = oa->header.objheader.vftbl->arraydesc;
656 componentvftbl = desc->componentvftbl;
657 valuevftbl = o->vftbl;
659 if ((desc->dimension - 1) == 0) {
662 /* {oa is a one-dimensional array} */
663 /* {oa is an array of references} */
665 if (valuevftbl == componentvftbl)
668 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
670 if ((base = classvalues.super_baseval) <= 0)
671 /* an array of interface references */
672 return (valuevftbl->interfacetablelength > -base &&
673 valuevftbl->interfacetable[base] != NULL);
675 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
676 <= (unsigned) classvalues.super_diffval);
681 /* {oa has dimension > 1} */
682 /* {componentvftbl->arraydesc != NULL} */
684 /* check if o is an array */
686 if ((valuedesc = valuevftbl->arraydesc) == NULL)
689 /* {o is an array} */
691 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
695 /* This is an optimized version where a is guaranteed to be one-dimensional */
696 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
698 arraydescriptor *desc;
699 vftbl_t *elementvftbl;
703 castinfo classvalues;
707 /* The following is guaranteed (by verifier checks):
709 * *) a->...vftbl->arraydesc != NULL
710 * *) a->...vftbl->arraydesc->elementvftbl != NULL
711 * *) a->...vftbl->arraydesc->dimension == 1
712 * *) o->vftbl is not an interface vftbl
715 desc = a->header.objheader.vftbl->arraydesc;
716 elementvftbl = desc->elementvftbl;
717 valuevftbl = o->vftbl;
719 /* {a is a one-dimensional array} */
721 if (valuevftbl == elementvftbl)
724 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
726 if ((base = classvalues.super_baseval) <= 0)
727 /* an array of interface references */
728 return (valuevftbl->interfacetablelength > -base &&
729 valuevftbl->interfacetable[base] != NULL);
731 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
732 <= (unsigned) classvalues.super_diffval;
738 /* This is an optimized version where a is guaranteed to be a
739 * one-dimensional array of a class type */
740 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
742 vftbl_t *elementvftbl;
745 castinfo classvalues;
749 /* The following is guaranteed (by verifier checks):
751 * *) a->...vftbl->arraydesc != NULL
752 * *) a->...vftbl->arraydesc->elementvftbl != NULL
753 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
754 * *) a->...vftbl->arraydesc->dimension == 1
755 * *) o->vftbl is not an interface vftbl
758 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
759 valuevftbl = o->vftbl;
761 /* {a is a one-dimensional array} */
763 if (valuevftbl == elementvftbl)
766 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
768 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
769 <= (unsigned) classvalues.super_diffval;
775 /* builtin_new *****************************************************************
777 Creates a new instance of class c on the heap.
779 Return value: pointer to the object or NULL if no memory is
782 *******************************************************************************/
784 java_objectheader *builtin_new(classinfo *c)
786 java_objectheader *o;
787 #if defined(ENABLE_RT_TIMING)
788 struct timespec time_start, time_end;
790 #if defined(ENABLE_CYCLES_STATS)
791 u8 cycles_start, cycles_end;
794 RT_TIMING_GET_TIME(time_start);
795 CYCLES_STATS_GET(cycles_start);
797 /* is the class loaded */
799 assert(c->state & CLASS_LOADED);
801 /* check if we can instantiate this class */
803 if (c->flags & ACC_ABSTRACT) {
805 new_exception_utfmessage(string_java_lang_InstantiationError,
810 /* is the class linked */
812 if (!(c->state & CLASS_LINKED))
816 if (!(c->state & CLASS_INITIALIZED)) {
819 log_message_class("Initialize class (from builtin_new): ", c);
822 if (!initialize_class(c))
826 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
834 #if defined(ENABLE_THREADS)
835 lock_init_object_lock(o);
838 CYCLES_STATS_GET(cycles_end);
839 RT_TIMING_GET_TIME(time_end);
841 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
842 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
848 /* builtin_newarray ************************************************************
850 Creates an array with the given vftbl on the heap. This function
851 takes as class argument an array class.
853 Return value: pointer to the array or NULL if no memory is available
855 *******************************************************************************/
857 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
859 arraydescriptor *desc;
864 #if defined(ENABLE_RT_TIMING)
865 struct timespec time_start, time_end;
868 RT_TIMING_GET_TIME(time_start);
870 desc = arrayclass->vftbl->arraydesc;
871 dataoffset = desc->dataoffset;
872 componentsize = desc->componentsize;
875 exceptions_throw_negativearraysizeexception();
879 actualsize = dataoffset + size * componentsize;
881 if (((u4) actualsize) < ((u4) size)) { /* overflow */
882 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
886 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
891 a->objheader.vftbl = arrayclass->vftbl;
893 #if defined(ENABLE_THREADS)
894 lock_init_object_lock(&a->objheader);
899 RT_TIMING_GET_TIME(time_end);
900 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
906 /* builtin_anewarray ***********************************************************
908 Creates an array of references to the given class type on the heap.
910 Return value: pointer to the array or NULL if no memory is
913 *******************************************************************************/
915 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
917 classinfo *arrayclass;
919 /* is class loaded */
921 assert(componentclass->state & CLASS_LOADED);
923 /* is class linked */
925 if (!(componentclass->state & CLASS_LINKED))
926 if (!link_class(componentclass))
929 arrayclass = class_array_of(componentclass, true);
934 return (java_objectarray *) builtin_newarray(size, arrayclass);
938 /* builtin_newarray_boolean ****************************************************
940 Creates an array of bytes on the heap. The array is designated as
941 an array of booleans (important for casts)
943 Return value: pointer to the array or NULL if no memory is
946 *******************************************************************************/
948 java_booleanarray *builtin_newarray_boolean(s4 size)
950 return (java_booleanarray *)
951 builtin_newarray(size,
952 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
956 /* builtin_newarray_byte *******************************************************
958 Creates an array of 8 bit Integers on the heap.
960 Return value: pointer to the array or NULL if no memory is
963 *******************************************************************************/
965 java_bytearray *builtin_newarray_byte(s4 size)
967 return (java_bytearray *)
968 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
972 /* builtin_newarray_char *******************************************************
974 Creates an array of characters on the heap.
976 Return value: pointer to the array or NULL if no memory is
979 *******************************************************************************/
981 java_chararray *builtin_newarray_char(s4 size)
983 return (java_chararray *)
984 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
988 /* builtin_newarray_short ******************************************************
990 Creates an array of 16 bit Integers on the heap.
992 Return value: pointer to the array or NULL if no memory is
995 *******************************************************************************/
997 java_shortarray *builtin_newarray_short(s4 size)
999 return (java_shortarray *)
1000 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1004 /* builtin_newarray_int ********************************************************
1006 Creates an array of 32 bit Integers on the heap.
1008 Return value: pointer to the array or NULL if no memory is
1011 *******************************************************************************/
1013 java_intarray *builtin_newarray_int(s4 size)
1015 return (java_intarray *)
1016 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1020 /* builtin_newarray_long *******************************************************
1022 Creates an array of 64 bit Integers on the heap.
1024 Return value: pointer to the array or NULL if no memory is
1027 *******************************************************************************/
1029 java_longarray *builtin_newarray_long(s4 size)
1031 return (java_longarray *)
1032 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1036 /* builtin_newarray_float ******************************************************
1038 Creates an array of 32 bit IEEE floats on the heap.
1040 Return value: pointer to the array or NULL if no memory is
1043 *******************************************************************************/
1045 java_floatarray *builtin_newarray_float(s4 size)
1047 return (java_floatarray *)
1048 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1052 /* builtin_newarray_double *****************************************************
1054 Creates an array of 64 bit IEEE floats on the heap.
1056 Return value: pointer to the array or NULL if no memory is
1059 *******************************************************************************/
1061 java_doublearray *builtin_newarray_double(s4 size)
1063 return (java_doublearray *)
1064 builtin_newarray(size,
1065 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1069 /* builtin_multianewarray_intern ***********************************************
1071 Creates a multi-dimensional array on the heap. The dimensions are
1072 passed in an array of longs.
1075 n............number of dimensions to create
1076 arrayvftbl...vftbl of the array class
1077 dims.........array containing the size of each dimension to create
1079 Return value: pointer to the array or NULL if no memory is
1082 ******************************************************************************/
1084 static java_arrayheader *builtin_multianewarray_intern(int n,
1085 classinfo *arrayclass,
1089 java_arrayheader *a;
1090 classinfo *componentclass;
1093 /* create this dimension */
1095 size = (s4) dims[0];
1096 a = builtin_newarray(size, arrayclass);
1101 /* if this is the last dimension return */
1106 /* get the class of the components to create */
1108 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1110 /* The verifier guarantees that the dimension count is in the range. */
1112 /* create the component arrays */
1114 for (i = 0; i < size; i++) {
1115 java_arrayheader *ea =
1116 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1117 /* we save an s4 to a s8 slot, 8-byte aligned */
1119 builtin_multianewarray_intern(n, componentclass, dims + 2);
1121 builtin_multianewarray_intern(n, componentclass, dims + 1);
1127 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1134 /* builtin_multianewarray ******************************************************
1136 Wrapper for builtin_multianewarray_intern which checks all
1137 dimensions before we start allocating.
1139 ******************************************************************************/
1141 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1147 /* check all dimensions before doing anything */
1149 for (i = 0; i < n; i++) {
1150 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1151 /* we save an s4 to a s8 slot, 8-byte aligned */
1152 size = (s4) dims[i * 2];
1154 size = (s4) dims[i];
1158 exceptions_throw_negativearraysizeexception();
1163 /* now call the real function */
1165 return builtin_multianewarray_intern(n, arrayclass, dims);
1169 /*****************************************************************************
1172 Various functions for printing a message at method entry or exit (for
1175 *****************************************************************************/
1177 #if !defined(NDEBUG)
1178 static s4 methodindent = 0;
1179 static u4 callcount = 0;
1181 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1191 if (opt_verbosecall && indent)
1194 /* calculate message length */
1198 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1201 logtextlen = strlen("Some Throwable");
1204 logtextlen += strlen(" thrown in ");
1208 utf_bytes(m->class->name) +
1210 utf_bytes(m->name) +
1211 utf_bytes(m->descriptor) +
1212 strlen("(NOSYNC,NATIVE");
1214 #if SIZEOF_VOID_P == 8
1216 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1218 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1221 if (m->class->sourcefile == NULL)
1222 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1224 logtextlen += utf_bytes(m->class->sourcefile);
1226 logtextlen += strlen(":65536)");
1230 logtextlen += strlen("call_java_method");
1233 logtextlen += strlen("0");
1235 /* allocate memory */
1237 dumpsize = dump_size();
1239 logtext = DMNEW(char, logtextlen);
1242 strcpy(logtext, "Exception ");
1243 utf_cat_classname(logtext, xptr->vftbl->class->name);
1246 strcpy(logtext, "Some Throwable");
1249 strcat(logtext, " thrown in ");
1252 utf_cat_classname(logtext, m->class->name);
1253 strcat(logtext, ".");
1254 utf_cat(logtext, m->name);
1255 utf_cat(logtext, m->descriptor);
1257 if (m->flags & ACC_SYNCHRONIZED)
1258 strcat(logtext, "(SYNC");
1260 strcat(logtext, "(NOSYNC");
1262 if (m->flags & ACC_NATIVE) {
1263 strcat(logtext, ",NATIVE");
1267 #if SIZEOF_VOID_P == 8
1268 sprintf(logtext + strlen(logtext),
1269 ")(0x%016lx) at position 0x%016lx",
1270 (ptrint) code->entrypoint, (ptrint) pos);
1272 sprintf(logtext + strlen(logtext),
1273 ")(0x%08x) at position 0x%08x",
1274 (ptrint) code->entrypoint, (ptrint) pos);
1279 /* XXX preliminary: This should get the actual codeinfo */
1280 /* in which the exception happened. */
1283 #if SIZEOF_VOID_P == 8
1284 sprintf(logtext + strlen(logtext),
1285 ")(0x%016lx) at position 0x%016lx (",
1286 (ptrint) code->entrypoint, (ptrint) pos);
1288 sprintf(logtext + strlen(logtext),
1289 ")(0x%08x) at position 0x%08x (",
1290 (ptrint) code->entrypoint, (ptrint) pos);
1293 if (m->class->sourcefile == NULL)
1294 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1296 utf_cat(logtext, m->class->sourcefile);
1298 sprintf(logtext + strlen(logtext), ":%d)", 0);
1302 strcat(logtext, "call_java_method");
1306 /* release memory */
1308 dump_release(dumpsize);
1312 #endif /* !defined(NDEBUG) */
1315 /* builtin_print_argument ******************************************************
1317 Prints arguments and return values for the call trace.
1319 *******************************************************************************/
1321 #if !defined(NDEBUG)
1322 static char *builtin_print_argument(char *logtext, s4 logtextlen,
1323 typedesc *paramtype, s8 value)
1326 java_objectheader *o;
1327 java_lang_String *s;
1332 switch (paramtype->type) {
1334 sprintf(logtext + strlen(logtext), "0x%x", (s4) value);
1338 #if SIZEOF_VOID_P == 4
1339 sprintf(logtext + strlen(logtext), "0x%llx", value);
1341 sprintf(logtext + strlen(logtext), "0x%lx", value);
1347 sprintf(logtext + strlen(logtext), "%.8f (0x%08x)", imu.f, imu.i);
1352 #if SIZEOF_VOID_P == 4
1353 sprintf(logtext + strlen(logtext), "%.16g (0x%016llx)", imu.d, imu.l);
1355 sprintf(logtext + strlen(logtext), "%.16g (0x%016lx)", imu.d, imu.l);
1360 sprintf(logtext + strlen(logtext), "%p", (void *) (ptrint) value);
1362 /* cast to java.lang.Object */
1364 o = (java_objectheader *) (ptrint) value;
1366 /* check return argument for java.lang.Class or java.lang.String */
1369 if (o->vftbl->class == class_java_lang_String) {
1370 /* get java.lang.String object and the length of the
1373 s = (java_lang_String *) o;
1375 u = javastring_toutf(s, false);
1377 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1379 /* realloc memory for string length */
1381 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1383 /* convert to utf8 string and strcat it to the logtext */
1385 strcat(logtext, " (String = \"");
1386 utf_cat(logtext, u);
1387 strcat(logtext, "\")");
1390 if (o->vftbl->class == class_java_lang_Class) {
1391 /* if the object returned is a java.lang.Class
1392 cast it to classinfo structure and get the name
1395 c = (classinfo *) o;
1400 /* if the object returned is not a java.lang.String or
1401 a java.lang.Class just print the name of the class */
1403 u = o->vftbl->class->name;
1406 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1408 /* realloc memory for string length */
1410 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1412 /* strcat to the logtext */
1414 strcat(logtext, " (Class = \"");
1415 utf_cat_classname(logtext, u);
1416 strcat(logtext, "\")");
1423 #endif /* !defined(NDEBUG) */
1426 /* builtin_trace_args **********************************************************
1428 Print method call with arguments for -verbose:call.
1430 *******************************************************************************/
1432 #if !defined(NDEBUG)
1434 #ifdef TRACE_ARGS_NUM
1435 void builtin_trace_args(s8 a0, s8 a1,
1436 #if TRACE_ARGS_NUM >= 4
1438 #endif /* TRACE_ARGS_NUM >= 4 */
1439 #if TRACE_ARGS_NUM >= 6
1441 #endif /* TRACE_ARGS_NUM >= 6 */
1442 #if TRACE_ARGS_NUM == 8
1444 #endif /* TRACE_ARGS_NUM == 8 */
1456 /* calculate message length */
1459 strlen("4294967295 ") +
1460 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1462 strlen("called: ") +
1463 utf_bytes(m->class->name) +
1465 utf_bytes(m->name) +
1466 utf_bytes(m->descriptor) +
1467 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1469 /* add maximal argument length */
1471 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1473 /* allocate memory */
1475 dumpsize = dump_size();
1477 logtext = DMNEW(char, logtextlen);
1481 sprintf(logtext, "%10d ", callcount);
1482 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1484 pos = strlen(logtext);
1486 for (i = 0; i < methodindent; i++)
1487 logtext[pos++] = '\t';
1489 strcpy(logtext + pos, "called: ");
1491 utf_cat_classname(logtext, m->class->name);
1492 strcat(logtext, ".");
1493 utf_cat(logtext, m->name);
1494 utf_cat(logtext, m->descriptor);
1496 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1497 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1498 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1499 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1500 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1501 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1502 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1503 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1504 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1505 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1506 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1508 strcat(logtext, "(");
1510 if (md->paramcount >= 1) {
1511 logtext = builtin_print_argument(logtext, logtextlen,
1512 &md->paramtypes[0], a0);
1515 if (md->paramcount >= 2) {
1516 strcat(logtext, ", ");
1518 logtext = builtin_print_argument(logtext, logtextlen,
1519 &md->paramtypes[1], a1);
1522 #if TRACE_ARGS_NUM >= 4
1523 if (md->paramcount >= 3) {
1524 strcat(logtext, ", ");
1526 logtext = builtin_print_argument(logtext, logtextlen,
1527 &md->paramtypes[2], a2);
1530 if (md->paramcount >= 4) {
1531 strcat(logtext, ", ");
1533 logtext = builtin_print_argument(logtext, logtextlen,
1534 &md->paramtypes[3], a3);
1538 #if TRACE_ARGS_NUM >= 6
1539 if (md->paramcount >= 5) {
1540 strcat(logtext, ", ");
1542 logtext = builtin_print_argument(logtext, logtextlen,
1543 &md->paramtypes[4], a4);
1546 if (md->paramcount >= 6) {
1547 strcat(logtext, ", ");
1549 logtext = builtin_print_argument(logtext, logtextlen,
1550 &md->paramtypes[5], a5);
1554 #if TRACE_ARGS_NUM == 8
1555 if (md->paramcount >= 7) {
1556 strcat(logtext, ", ");
1558 logtext = builtin_print_argument(logtext, logtextlen,
1559 &md->paramtypes[6], a6);
1562 if (md->paramcount >= 8) {
1563 strcat(logtext, ", ");
1565 logtext = builtin_print_argument(logtext, logtextlen,
1566 &md->paramtypes[7], a7);
1570 if (md->paramcount > 8) {
1571 sprintf(logtext + strlen(logtext), ", ...(%d)",
1572 md->paramcount - TRACE_ARGS_NUM);
1575 strcat(logtext, ")");
1579 /* release memory */
1581 dump_release(dumpsize);
1586 #endif /* !defined(NDEBUG) */
1589 /* builtin_displaymethodstop ***************************************************
1591 Print method exit for -verbose:call.
1593 *******************************************************************************/
1595 #if !defined(NDEBUG)
1596 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1607 /* calculate message length */
1610 strlen("4294967295 ") +
1611 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1613 strlen("finished: ") +
1614 utf_bytes(m->class->name) +
1616 utf_bytes(m->name) +
1617 utf_bytes(m->descriptor) +
1618 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1620 /* add maximal argument length */
1622 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1624 /* allocate memory */
1626 dumpsize = dump_size();
1628 logtext = DMNEW(char, logtextlen);
1630 /* outdent the log message */
1635 log_text("WARNING: unmatched methodindent--");
1637 /* generate the message */
1639 sprintf(logtext, " ");
1640 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1642 pos = strlen(logtext);
1644 for (i = 0; i < methodindent; i++)
1645 logtext[pos++] = '\t';
1647 strcpy(logtext + pos, "finished: ");
1648 utf_cat_classname(logtext, m->class->name);
1649 strcat(logtext, ".");
1650 utf_cat(logtext, m->name);
1651 utf_cat(logtext, m->descriptor);
1653 if (!IS_VOID_TYPE(md->returntype.type))
1654 strcat(logtext, "->");
1656 logtext = builtin_print_argument(logtext, logtextlen, &md->returntype, l);
1660 /* release memory */
1662 dump_release(dumpsize);
1664 #endif /* !defined(NDEBUG) */
1667 #if defined(ENABLE_CYCLES_STATS)
1668 void builtin_print_cycles_stats(FILE *file)
1670 fprintf(file,"builtin cylce count statistics:\n");
1672 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1673 CYCLES_STATS_PRINT(builtin_new ,file);
1677 #endif /* defined(ENABLE_CYCLES_STATS) */
1680 /*****************************************************************************
1681 MISCELLANEOUS HELPER FUNCTIONS
1682 *****************************************************************************/
1686 /*********** Functions for integer divisions *****************************
1688 On some systems (eg. DEC ALPHA), integer division is not supported by the
1689 CPU. These helper functions implement the missing functionality.
1691 ******************************************************************************/
1693 #if !SUPPORT_DIVISION
1694 s4 builtin_idiv(s4 a, s4 b)
1703 s4 builtin_irem(s4 a, s4 b)
1711 #endif /* !SUPPORT_DIVISION */
1714 /* functions for long arithmetics **********************************************
1716 On systems where 64 bit Integers are not supported by the CPU,
1717 these functions are needed.
1719 ******************************************************************************/
1721 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1722 s8 builtin_ladd(s8 a, s8 b)
1735 s8 builtin_lsub(s8 a, s8 b)
1748 s8 builtin_lneg(s8 a)
1760 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1763 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1764 s8 builtin_lmul(s8 a, s8 b)
1776 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1779 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1780 s8 builtin_ldiv(s8 a, s8 b)
1793 s8 builtin_lrem(s8 a, s8 b)
1805 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1808 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1809 s8 builtin_lshl(s8 a, s4 b)
1822 s8 builtin_lshr(s8 a, s4 b)
1835 s8 builtin_lushr(s8 a, s4 b)
1840 c = ((u8) a) >> (b & 63);
1847 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1850 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1851 s8 builtin_land(s8 a, s8 b)
1864 s8 builtin_lor(s8 a, s8 b)
1877 s8 builtin_lxor(s8 a, s8 b)
1889 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1892 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1893 s4 builtin_lcmp(s8 a, s8 b)
1907 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1910 /* functions for unsupported floating instructions ****************************/
1912 /* used to convert FLT_xxx defines into float values */
1914 static inline float intBitsToFloat(s4 i)
1923 /* used to convert DBL_xxx defines into double values */
1925 static inline float longBitsToDouble(s8 l)
1935 float builtin_fadd(float a, float b)
1937 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1938 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1949 if (copysignf(1.0, a) == copysignf(1.0, b))
1952 return intBitsToFloat(FLT_NAN);
1958 float builtin_fsub(float a, float b)
1960 return builtin_fadd(a, builtin_fneg(b));
1964 float builtin_fmul(float a, float b)
1966 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1967 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1969 if (finitef(b)) return a * b;
1971 if (a == 0) return intBitsToFloat(FLT_NAN);
1972 else return copysignf(b, copysignf(1.0, b)*a);
1977 if (b == 0) return intBitsToFloat(FLT_NAN);
1978 else return copysignf(a, copysignf(1.0, a)*b);
1981 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1987 /* builtin_ddiv ****************************************************************
1989 Implementation as described in VM Spec.
1991 *******************************************************************************/
1993 float builtin_fdiv(float a, float b)
1997 /* If neither value1' nor value2' is NaN, the sign of the result */
1998 /* is positive if both values have the same sign, negative if the */
1999 /* values have different signs. */
2005 /* If either value1' or value2' is NaN, the result is NaN. */
2007 return intBitsToFloat(FLT_NAN);
2010 /* Division of a finite value by an infinity results in a */
2011 /* signed zero, with the sign-producing rule just given. */
2013 /* is sign equal? */
2015 if (copysignf(1.0, a) == copysignf(1.0, b))
2024 /* If either value1' or value2' is NaN, the result is NaN. */
2026 return intBitsToFloat(FLT_NAN);
2028 } else if (finitef(b)) {
2029 /* Division of an infinity by a finite value results in a signed */
2030 /* infinity, with the sign-producing rule just given. */
2032 /* is sign equal? */
2034 if (copysignf(1.0, a) == copysignf(1.0, b))
2035 return intBitsToFloat(FLT_POSINF);
2037 return intBitsToFloat(FLT_NEGINF);
2040 /* Division of an infinity by an infinity results in NaN. */
2042 return intBitsToFloat(FLT_NAN);
2048 float builtin_fneg(float a)
2050 if (isnanf(a)) return a;
2052 if (finitef(a)) return -a;
2053 else return copysignf(a, -copysignf(1.0, a));
2056 #endif /* !SUPPORT_FLOAT */
2059 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2060 s4 builtin_fcmpl(float a, float b)
2062 if (isnanf(a)) return -1;
2063 if (isnanf(b)) return -1;
2064 if (!finitef(a) || !finitef(b)) {
2065 a = finitef(a) ? 0 : copysignf(1.0, a);
2066 b = finitef(b) ? 0 : copysignf(1.0, b);
2068 if (a > b) return 1;
2069 if (a == b) return 0;
2074 s4 builtin_fcmpg(float a, float b)
2076 if (isnanf(a)) return 1;
2077 if (isnanf(b)) return 1;
2078 if (!finitef(a) || !finitef(b)) {
2079 a = finitef(a) ? 0 : copysignf(1.0, a);
2080 b = finitef(b) ? 0 : copysignf(1.0, b);
2082 if (a > b) return 1;
2083 if (a == b) return 0;
2086 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2089 float builtin_frem(float a, float b)
2095 /* functions for unsupported double instructions ******************************/
2098 double builtin_dadd(double a, double b)
2100 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2101 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2103 if (finite(b)) return a + b;
2107 if (finite(b)) return a;
2109 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2110 else return longBitsToDouble(DBL_NAN);
2116 double builtin_dsub(double a, double b)
2118 return builtin_dadd(a, builtin_dneg(b));
2122 double builtin_dmul(double a, double b)
2124 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2125 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2127 if (finite(b)) return a * b;
2129 if (a == 0) return longBitsToDouble(DBL_NAN);
2130 else return copysign(b, copysign(1.0, b) * a);
2135 if (b == 0) return longBitsToDouble(DBL_NAN);
2136 else return copysign(a, copysign(1.0, a) * b);
2139 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2145 /* builtin_ddiv ****************************************************************
2147 Implementation as described in VM Spec.
2149 *******************************************************************************/
2151 double builtin_ddiv(double a, double b)
2155 /* If neither value1' nor value2' is NaN, the sign of the result */
2156 /* is positive if both values have the same sign, negative if the */
2157 /* values have different signs. */
2163 /* If either value1' or value2' is NaN, the result is NaN. */
2165 return longBitsToDouble(DBL_NAN);
2168 /* Division of a finite value by an infinity results in a */
2169 /* signed zero, with the sign-producing rule just given. */
2171 /* is sign equal? */
2173 if (copysign(1.0, a) == copysign(1.0, b))
2182 /* If either value1' or value2' is NaN, the result is NaN. */
2184 return longBitsToDouble(DBL_NAN);
2186 } else if (finite(b)) {
2187 /* Division of an infinity by a finite value results in a signed */
2188 /* infinity, with the sign-producing rule just given. */
2190 /* is sign equal? */
2192 if (copysign(1.0, a) == copysign(1.0, b))
2193 return longBitsToDouble(DBL_POSINF);
2195 return longBitsToDouble(DBL_NEGINF);
2198 /* Division of an infinity by an infinity results in NaN. */
2200 return longBitsToDouble(DBL_NAN);
2206 /* builtin_dneg ****************************************************************
2208 Implemented as described in VM Spec.
2210 *******************************************************************************/
2212 double builtin_dneg(double a)
2215 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2222 /* If the operand is a zero, the result is the zero of opposite */
2228 /* If the operand is an infinity, the result is the infinity of */
2229 /* opposite sign. */
2231 return copysign(a, -copysign(1.0, a));
2235 #endif /* !SUPPORT_DOUBLE */
2238 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2239 s4 builtin_dcmpl(double a, double b)
2241 if (isnan(a)) return -1;
2242 if (isnan(b)) return -1;
2243 if (!finite(a) || !finite(b)) {
2244 a = finite(a) ? 0 : copysign(1.0, a);
2245 b = finite(b) ? 0 : copysign(1.0, b);
2247 if (a > b) return 1;
2248 if (a == b) return 0;
2253 s4 builtin_dcmpg(double a, double b)
2255 if (isnan(a)) return 1;
2256 if (isnan(b)) return 1;
2257 if (!finite(a) || !finite(b)) {
2258 a = finite(a) ? 0 : copysign(1.0, a);
2259 b = finite(b) ? 0 : copysign(1.0, b);
2261 if (a > b) return 1;
2262 if (a == b) return 0;
2265 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2268 double builtin_drem(double a, double b)
2274 /* conversion operations ******************************************************/
2277 s8 builtin_i2l(s4 i)
2289 s4 builtin_l2i(s8 l)
2300 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2301 float builtin_i2f(s4 a)
2303 float f = (float) a;
2306 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2309 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2310 double builtin_i2d(s4 a)
2312 double d = (double) a;
2315 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2318 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2319 float builtin_l2f(s8 a)
2322 float f = (float) a;
2328 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2331 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2332 double builtin_l2d(s8 a)
2335 double d = (double) a;
2341 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2344 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
2345 s4 builtin_f2i(float a)
2349 i = builtin_d2i((double) a);
2360 if (a < (-2147483648))
2361 return (-2147483648);
2364 f = copysignf((float) 1.0, a);
2367 return (-2147483648); */
2369 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
2372 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2373 s8 builtin_f2l(float a)
2377 l = builtin_d2l((double) a);
2384 if (a > 9223372036854775807L)
2385 return 9223372036854775807L;
2386 if (a < (-9223372036854775808L))
2387 return (-9223372036854775808L);
2392 f = copysignf((float) 1.0, a);
2394 return 9223372036854775807L;
2395 return (-9223372036854775808L); */
2397 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2400 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
2401 s4 builtin_d2i(double a)
2406 if (a >= 2147483647)
2408 if (a <= (-2147483647-1))
2409 return (-2147483647-1);
2414 d = copysign(1.0, a);
2417 return (-2147483647-1);
2419 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
2422 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2423 s8 builtin_d2l(double a)
2428 if (a >= 9223372036854775807LL)
2429 return 9223372036854775807LL;
2430 if (a <= (-9223372036854775807LL-1))
2431 return (-9223372036854775807LL-1);
2436 d = copysign(1.0, a);
2438 return 9223372036854775807LL;
2439 return (-9223372036854775807LL-1);
2441 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2444 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2445 double builtin_f2d(float a)
2447 if (finitef(a)) return (double) a;
2450 return longBitsToDouble(DBL_NAN);
2452 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2456 float builtin_d2f(double a)
2462 return intBitsToFloat(FLT_NAN);
2464 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2467 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2470 /* builtin_arraycopy ***********************************************************
2472 Builtin for java.lang.System.arraycopy.
2474 ATTENTION: This builtin function returns a boolean value to signal
2475 the ICMD_BUILTIN if there was an exception.
2477 *******************************************************************************/
2479 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2480 java_arrayheader *dest, s4 destStart, s4 len)
2482 arraydescriptor *sdesc;
2483 arraydescriptor *ddesc;
2486 if ((src == NULL) || (dest == NULL)) {
2487 exceptions_throw_nullpointerexception();
2491 sdesc = src->objheader.vftbl->arraydesc;
2492 ddesc = dest->objheader.vftbl->arraydesc;
2494 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2495 exceptions_throw_arraystoreexception();
2499 /* we try to throw exception with the same message as SUN does */
2501 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2502 (srcStart + len < 0) || (srcStart + len > src->size) ||
2503 (destStart + len < 0) || (destStart + len > dest->size)) {
2504 exceptions_throw_arrayindexoutofboundsexception();
2508 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2509 /* We copy primitive values or references of exactly the same type */
2511 s4 dataoffset = sdesc->dataoffset;
2512 s4 componentsize = sdesc->componentsize;
2514 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2515 ((u1 *) src) + dataoffset + componentsize * srcStart,
2516 (size_t) len * componentsize);
2519 /* We copy references of different type */
2521 java_objectarray *oas = (java_objectarray *) src;
2522 java_objectarray *oad = (java_objectarray *) dest;
2524 if (destStart <= srcStart) {
2525 for (i = 0; i < len; i++) {
2526 java_objectheader *o = oas->data[srcStart + i];
2528 if (!builtin_canstore(oad, o)) {
2529 exceptions_throw_arraystoreexception();
2533 oad->data[destStart + i] = o;
2537 /* XXX this does not completely obey the specification!
2538 If an exception is thrown only the elements above the
2539 current index have been copied. The specification
2540 requires that only the elements *below* the current
2541 index have been copied before the throw. */
2543 for (i = len - 1; i >= 0; i--) {
2544 java_objectheader *o = oas->data[srcStart + i];
2546 if (!builtin_canstore(oad, o)) {
2547 exceptions_throw_arraystoreexception();
2551 oad->data[destStart + i] = o;
2560 /* builtin_currenttimemillis ***************************************************
2562 Return the current time in milliseconds.
2564 *******************************************************************************/
2566 s8 builtin_currenttimemillis(void)
2571 if (gettimeofday(&tv, NULL) == -1)
2572 vm_abort("gettimeofday failed: %s", strerror(errno));
2574 result = (s8) tv.tv_sec;
2576 result += (tv.tv_usec / 1000);
2582 /* builtin_clone_array *********************************************************
2584 Wrapper function for cloning arrays.
2586 *******************************************************************************/
2588 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2590 java_arrayheader *ah;
2591 java_lang_Cloneable *c;
2593 c = (java_lang_Cloneable *) o;
2595 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2602 * These are local overrides for various environment variables in Emacs.
2603 * Please do not remove this and leave it at the end of the file, where
2604 * Emacs will automagically detect them.
2605 * ---------------------------------------------------------------------
2608 * indent-tabs-mode: t
2612 * vim:noexpandtab:sw=4:ts=4: