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 4921 2006-05-15 14:24:36Z twisti $
57 #include "fdlibm/fdlibm.h"
60 #include "mm/memory.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Cloneable.h"
63 #include "native/include/java_lang_Object.h" /* required by VMObject */
64 #include "native/include/java_lang_VMObject.h"
66 #if defined(ENABLE_THREADS)
67 # include "threads/native/threads.h"
70 #include "toolbox/logging.h"
71 #include "toolbox/util.h"
72 #include "vm/builtin.h"
74 #include "vm/exceptions.h"
75 #include "vm/global.h"
76 #include "vm/initialize.h"
77 #include "vm/loader.h"
78 #include "vm/options.h"
79 #include "vm/stringlocal.h"
80 #include "vm/jit/asmpart.h"
81 #include "vm/jit/patcher.h"
82 #include "vm/rt-timing.h"
83 #include "vm/cycles-stats.h"
86 /* include builtin tables *****************************************************/
88 #include "vm/builtintable.inc"
91 CYCLES_STATS_DECLARE(builtin_monitorenter,100,2)
92 CYCLES_STATS_DECLARE(builtin_monitorexit ,100,2)
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;
109 s4 entries_automatic;
112 /* mark start of dump memory area */
114 dumpsize = dump_size();
116 /* create a new descriptor pool */
118 descpool = descriptor_pool_new(class_java_lang_Object);
120 /* add some entries we need */
122 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
125 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
128 /* calculate table entries statically */
131 sizeof(builtintable_internal) / sizeof(builtintable_entry);
134 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
135 - 1; /* last filler entry (comment see builtintable.inc) */
137 /* first add all descriptors to the pool */
139 for (i = 0; i < entries_internal; i++) {
140 /* create a utf8 string from descriptor */
142 descriptor = utf_new_char(builtintable_internal[i].descriptor);
144 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
145 /* release dump area */
147 dump_release(dumpsize);
153 for (i = 0; i < entries_automatic; i++) {
154 /* create a utf8 string from descriptor */
156 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
158 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
159 /* release dump area */
161 dump_release(dumpsize);
167 /* create the class reference table */
169 (void) descriptor_pool_create_classrefs(descpool, NULL);
171 /* allocate space for the parsed descriptors */
173 descriptor_pool_alloc_parsed_descriptors(descpool);
175 /* now parse all descriptors */
177 for (i = 0; i < entries_internal; i++) {
178 /* create a utf8 string from descriptor */
180 descriptor = utf_new_char(builtintable_internal[i].descriptor);
182 /* parse the descriptor, builtin is always static (no `this' pointer) */
184 builtintable_internal[i].md =
185 descriptor_pool_parse_method_descriptor(descpool, descriptor,
189 for (i = 0; i < entries_automatic; i++) {
190 /* create a utf8 string from descriptor */
192 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
194 /* parse the descriptor, builtin is always static (no `this' pointer) */
196 builtintable_automatic[i].md =
197 descriptor_pool_parse_method_descriptor(descpool, descriptor,
201 /* release dump area */
203 dump_release(dumpsize);
209 /* builtintable_comparator *****************************************************
211 qsort comparator for the automatic builtin table.
213 *******************************************************************************/
215 static int builtintable_comparator(const void *a, const void *b)
217 builtintable_entry *bte1;
218 builtintable_entry *bte2;
220 bte1 = (builtintable_entry *) a;
221 bte2 = (builtintable_entry *) b;
223 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
227 /* builtintable_sort_automatic *************************************************
229 Sorts the automatic builtin table.
231 *******************************************************************************/
233 static void builtintable_sort_automatic(void)
237 /* calculate table size statically (`- 1' comment see builtintable.inc) */
239 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
241 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
242 builtintable_comparator);
246 /* builtin_init ****************************************************************
250 *******************************************************************************/
252 bool builtin_init(void)
254 /* initialize the builtin tables */
256 if (!builtintable_init())
259 /* sort builtin tables */
261 builtintable_sort_automatic();
267 /* builtintable_get_internal ***************************************************
269 Finds an entry in the builtintable for internal functions and
270 returns the a pointer to the structure.
272 *******************************************************************************/
274 builtintable_entry *builtintable_get_internal(functionptr fp)
278 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
279 if (builtintable_internal[i].fp == fp)
280 return &builtintable_internal[i];
287 /* builtintable_get_automatic **************************************************
289 Finds an entry in the builtintable for functions which are replaced
290 automatically and returns the a pointer to the structure.
292 *******************************************************************************/
294 builtintable_entry *builtintable_get_automatic(s4 opcode)
296 builtintable_entry *first;
297 builtintable_entry *last;
298 builtintable_entry *middle;
302 /* calculate table size statically (`- 1' comment see builtintable.inc) */
304 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
306 first = builtintable_automatic;
307 last = builtintable_automatic + entries;
309 while (entries > 0) {
311 middle = first + half;
313 if (middle->opcode < opcode) {
320 return (first != last ? first : NULL);
324 /*****************************************************************************
326 *****************************************************************************/
330 /*************** internal function: builtin_isanysubclass *********************
332 Checks a subclass relation between two classes. Implemented interfaces
333 are interpreted as super classes.
334 Return value: 1 ... sub is subclass of super
337 *****************************************************************************/
338 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
341 castinfo classvalues;
346 if (super->flags & ACC_INTERFACE) {
347 res = (sub->vftbl->interfacetablelength > super->index) &&
348 (sub->vftbl->interfacetable[-super->index] != NULL);
351 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
353 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
354 (u4) classvalues.super_diffval;
361 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
365 castinfo classvalues;
370 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
372 if ((base = classvalues.super_baseval) <= 0) {
373 /* super is an interface */
374 res = (sub->interfacetablelength > -base) &&
375 (sub->interfacetable[base] != NULL);
377 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
378 <= (u4) classvalues.super_diffval;
385 /****************** function: builtin_instanceof *****************************
387 Checks if an object is an instance of some given class (or subclass of
388 that class). If class is an interface, checks if the interface is
390 Return value: 1 ... obj is an instance of class or implements the interface
391 0 ... otherwise or if obj == NULL
393 *****************************************************************************/
395 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
400 return builtin_isanysubclass(obj->vftbl->class, class);
405 /**************** function: builtin_checkcast *******************************
407 The same as builtin_instanceof except that 1 is returned when
410 ****************************************************************************/
412 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
417 if (builtin_isanysubclass(obj->vftbl->class, class))
424 /* builtin_descriptorscompatible ***********************************************
426 Checks if two array type descriptors are assignment compatible
428 Return value: 1 ... target = desc is possible
431 *******************************************************************************/
433 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
434 arraydescriptor *target)
439 if (desc->arraytype != target->arraytype)
442 if (desc->arraytype != ARRAYTYPE_OBJECT)
445 /* {both arrays are arrays of references} */
447 if (desc->dimension == target->dimension) {
448 /* an array which contains elements of interface types is
449 allowed to be casted to Object (JOWENN)*/
451 if ((desc->elementvftbl->baseval < 0) &&
452 (target->elementvftbl->baseval == 1))
455 return builtin_isanysubclass_vftbl(desc->elementvftbl,
456 target->elementvftbl);
459 if (desc->dimension < target->dimension)
462 /* {desc has higher dimension than target} */
464 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
465 target->elementvftbl);
469 /* builtin_arraycheckcast ******************************************************
471 Checks if an object is really a subtype of the requested array
472 type. The object has to be an array to begin with. For simple
473 arrays (int, short, double, etc.) the types have to match exactly.
474 For arrays of objects, the type of elements in the array has to be
475 a subtype (or the same type) of the requested element type. For
476 arrays of arrays (which in turn can again be arrays of arrays), the
477 types at the lowest level have to satisfy the corresponding sub
480 *******************************************************************************/
482 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
484 arraydescriptor *desc;
489 if ((desc = o->vftbl->arraydesc) == NULL)
492 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
496 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
501 return builtin_arraycheckcast(o, targetclass);
505 /* builtin_throw_exception *****************************************************
507 Sets the exceptionptr with the thrown exception and prints some
508 debugging information. Called from asm_vm_call_method.
510 *******************************************************************************/
512 void *builtin_throw_exception(java_objectheader *xptr)
515 java_lang_Throwable *t;
521 t = (java_lang_Throwable *) xptr;
523 /* calculate message length */
525 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
529 utf_bytes(xptr->vftbl->class->name);
530 if (t->detailMessage) {
531 logtextlen += strlen(": ") +
532 u2_utflength(t->detailMessage->value->data
533 + t->detailMessage->offset,
534 t->detailMessage->count);
538 logtextlen += strlen("(nil)");
541 /* allocate memory */
543 dumpsize = dump_size();
545 logtext = DMNEW(char, logtextlen);
547 strcpy(logtext, "Builtin exception thrown: ");
550 utf_cat_classname(logtext, xptr->vftbl->class->name);
552 if (t->detailMessage) {
555 buf = javastring_tochar((java_objectheader *) t->detailMessage);
556 strcat(logtext, ": ");
557 strcat(logtext, buf);
558 MFREE(buf, char, strlen(buf) + 1);
562 strcat(logtext, "(nil)");
569 dump_release(dumpsize);
571 #endif /* !defined(NDEBUG) */
573 /* actually set the exception */
575 *exceptionptr = xptr;
577 /* Return a NULL pointer. This is required for vm_call_method to
578 check for an exception. This is for convenience. */
584 /* builtin_canstore ************************************************************
586 Checks, if an object can be stored in an array.
588 Return value: 1 ... possible
591 *******************************************************************************/
593 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
595 arraydescriptor *desc;
596 arraydescriptor *valuedesc;
597 vftbl_t *componentvftbl;
600 castinfo classvalues;
605 /* The following is guaranteed (by verifier checks):
607 * *) oa->...vftbl->arraydesc != NULL
608 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
609 * *) o->vftbl is not an interface vftbl
612 desc = oa->header.objheader.vftbl->arraydesc;
613 componentvftbl = desc->componentvftbl;
614 valuevftbl = o->vftbl;
616 if ((desc->dimension - 1) == 0) {
619 /* {oa is a one-dimensional array} */
620 /* {oa is an array of references} */
622 if (valuevftbl == componentvftbl)
625 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
627 if ((base = classvalues.super_baseval) <= 0)
628 /* an array of interface references */
629 return (valuevftbl->interfacetablelength > -base &&
630 valuevftbl->interfacetable[base] != NULL);
632 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
633 <= (unsigned) classvalues.super_diffval);
638 /* {oa has dimension > 1} */
639 /* {componentvftbl->arraydesc != NULL} */
641 /* check if o is an array */
643 if ((valuedesc = valuevftbl->arraydesc) == NULL)
646 /* {o is an array} */
648 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
652 /* This is an optimized version where a is guaranteed to be one-dimensional */
653 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
655 arraydescriptor *desc;
656 vftbl_t *elementvftbl;
660 castinfo classvalues;
664 /* The following is guaranteed (by verifier checks):
666 * *) a->...vftbl->arraydesc != NULL
667 * *) a->...vftbl->arraydesc->elementvftbl != NULL
668 * *) a->...vftbl->arraydesc->dimension == 1
669 * *) o->vftbl is not an interface vftbl
672 desc = a->header.objheader.vftbl->arraydesc;
673 elementvftbl = desc->elementvftbl;
674 valuevftbl = o->vftbl;
676 /* {a is a one-dimensional array} */
678 if (valuevftbl == elementvftbl)
681 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
683 if ((base = classvalues.super_baseval) <= 0)
684 /* an array of interface references */
685 return (valuevftbl->interfacetablelength > -base &&
686 valuevftbl->interfacetable[base] != NULL);
688 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
689 <= (unsigned) classvalues.super_diffval;
695 /* This is an optimized version where a is guaranteed to be a
696 * one-dimensional array of a class type */
697 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
699 vftbl_t *elementvftbl;
702 castinfo classvalues;
706 /* The following is guaranteed (by verifier checks):
708 * *) a->...vftbl->arraydesc != NULL
709 * *) a->...vftbl->arraydesc->elementvftbl != NULL
710 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
711 * *) a->...vftbl->arraydesc->dimension == 1
712 * *) o->vftbl is not an interface vftbl
715 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
716 valuevftbl = o->vftbl;
718 /* {a is a one-dimensional array} */
720 if (valuevftbl == elementvftbl)
723 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
725 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
726 <= (unsigned) classvalues.super_diffval;
732 /* builtin_new *****************************************************************
734 Creates a new instance of class c on the heap.
736 Return value: pointer to the object or NULL if no memory is
739 *******************************************************************************/
741 java_objectheader *builtin_new(classinfo *c)
743 java_objectheader *o;
744 #if defined(ENABLE_RT_TIMING)
745 struct timespec time_start, time_end;
747 #if defined(ENABLE_CYCLES_STATS)
748 u8 cycles_start, cycles_end;
751 RT_TIMING_GET_TIME(time_start);
752 CYCLES_STATS_GET(cycles_start);
754 /* is the class loaded */
756 assert(c->state & CLASS_LOADED);
758 /* check if we can instantiate this class */
760 if (c->flags & ACC_ABSTRACT) {
762 new_exception_utfmessage(string_java_lang_InstantiationError,
767 /* is the class linked */
769 if (!(c->state & CLASS_LINKED))
773 if (!(c->state & CLASS_INITIALIZED)) {
776 log_message_class("Initialize class (from builtin_new): ", c);
779 if (!initialize_class(c))
783 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
791 #if defined(ENABLE_THREADS)
792 lock_init_object_lock(o);
795 CYCLES_STATS_GET(cycles_end);
796 RT_TIMING_GET_TIME(time_end);
798 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
799 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
805 /* builtin_newarray ************************************************************
807 Creates an array with the given vftbl on the heap. This function
808 takes as class argument an array class.
810 Return value: pointer to the array or NULL if no memory is available
812 *******************************************************************************/
814 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
816 arraydescriptor *desc;
821 #if defined(ENABLE_RT_TIMING)
822 struct timespec time_start, time_end;
825 RT_TIMING_GET_TIME(time_start);
827 desc = arrayclass->vftbl->arraydesc;
828 dataoffset = desc->dataoffset;
829 componentsize = desc->componentsize;
832 exceptions_throw_negativearraysizeexception();
836 actualsize = dataoffset + size * componentsize;
838 if (((u4) actualsize) < ((u4) size)) { /* overflow */
839 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
843 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
848 a->objheader.vftbl = arrayclass->vftbl;
850 #if defined(ENABLE_THREADS)
851 lock_init_object_lock(&a->objheader);
856 RT_TIMING_GET_TIME(time_end);
857 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
863 /* builtin_anewarray ***********************************************************
865 Creates an array of references to the given class type on the heap.
867 Return value: pointer to the array or NULL if no memory is
870 *******************************************************************************/
872 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
874 classinfo *arrayclass;
876 /* is class loaded */
878 assert(componentclass->state & CLASS_LOADED);
880 /* is class linked */
882 if (!(componentclass->state & CLASS_LINKED))
883 if (!link_class(componentclass))
886 arrayclass = class_array_of(componentclass, true);
891 return (java_objectarray *) builtin_newarray(size, arrayclass);
895 /* builtin_newarray_boolean ****************************************************
897 Creates an array of bytes on the heap. The array is designated as
898 an array of booleans (important for casts)
900 Return value: pointer to the array or NULL if no memory is
903 *******************************************************************************/
905 java_booleanarray *builtin_newarray_boolean(s4 size)
907 return (java_booleanarray *)
908 builtin_newarray(size,
909 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
913 /* builtin_newarray_byte *******************************************************
915 Creates an array of 8 bit Integers on the heap.
917 Return value: pointer to the array or NULL if no memory is
920 *******************************************************************************/
922 java_bytearray *builtin_newarray_byte(s4 size)
924 return (java_bytearray *)
925 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
929 /* builtin_newarray_char *******************************************************
931 Creates an array of characters on the heap.
933 Return value: pointer to the array or NULL if no memory is
936 *******************************************************************************/
938 java_chararray *builtin_newarray_char(s4 size)
940 return (java_chararray *)
941 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
945 /* builtin_newarray_short ******************************************************
947 Creates an array of 16 bit Integers on the heap.
949 Return value: pointer to the array or NULL if no memory is
952 *******************************************************************************/
954 java_shortarray *builtin_newarray_short(s4 size)
956 return (java_shortarray *)
957 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
961 /* builtin_newarray_int ********************************************************
963 Creates an array of 32 bit Integers on the heap.
965 Return value: pointer to the array or NULL if no memory is
968 *******************************************************************************/
970 java_intarray *builtin_newarray_int(s4 size)
972 return (java_intarray *)
973 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
977 /* builtin_newarray_long *******************************************************
979 Creates an array of 64 bit Integers on the heap.
981 Return value: pointer to the array or NULL if no memory is
984 *******************************************************************************/
986 java_longarray *builtin_newarray_long(s4 size)
988 return (java_longarray *)
989 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
993 /* builtin_newarray_float ******************************************************
995 Creates an array of 32 bit IEEE floats on the heap.
997 Return value: pointer to the array or NULL if no memory is
1000 *******************************************************************************/
1002 java_floatarray *builtin_newarray_float(s4 size)
1004 return (java_floatarray *)
1005 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1009 /* builtin_newarray_double *****************************************************
1011 Creates an array of 64 bit IEEE floats on the heap.
1013 Return value: pointer to the array or NULL if no memory is
1016 *******************************************************************************/
1018 java_doublearray *builtin_newarray_double(s4 size)
1020 return (java_doublearray *)
1021 builtin_newarray(size,
1022 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1026 /* builtin_multianewarray_intern ***********************************************
1028 Creates a multi-dimensional array on the heap. The dimensions are
1029 passed in an array of longs.
1032 n............number of dimensions to create
1033 arrayvftbl...vftbl of the array class
1034 dims.........array containing the size of each dimension to create
1036 Return value: pointer to the array or NULL if no memory is
1039 ******************************************************************************/
1041 static java_arrayheader *builtin_multianewarray_intern(int n,
1042 classinfo *arrayclass,
1046 java_arrayheader *a;
1047 classinfo *componentclass;
1050 /* create this dimension */
1052 size = (s4) dims[0];
1053 a = builtin_newarray(size, arrayclass);
1058 /* if this is the last dimension return */
1063 /* get the class of the components to create */
1065 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1067 /* The verifier guarantees that the dimension count is in the range. */
1069 /* create the component arrays */
1071 for (i = 0; i < size; i++) {
1072 java_arrayheader *ea =
1073 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1074 /* we save an s4 to a s8 slot, 8-byte aligned */
1076 builtin_multianewarray_intern(n, componentclass, dims + 2);
1078 builtin_multianewarray_intern(n, componentclass, dims + 1);
1084 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1091 /* builtin_multianewarray ******************************************************
1093 Wrapper for builtin_multianewarray_intern which checks all
1094 dimensions before we start allocating.
1096 ******************************************************************************/
1098 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1104 /* check all dimensions before doing anything */
1106 for (i = 0; i < n; i++) {
1107 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1108 /* we save an s4 to a s8 slot, 8-byte aligned */
1109 size = (s4) dims[i * 2];
1111 size = (s4) dims[i];
1115 exceptions_throw_negativearraysizeexception();
1120 /* now call the real function */
1122 return builtin_multianewarray_intern(n, arrayclass, dims);
1126 /*****************************************************************************
1129 Various functions for printing a message at method entry or exit (for
1132 *****************************************************************************/
1134 #if !defined(NDEBUG)
1135 static s4 methodindent = 0;
1136 static u4 callcount = 0;
1138 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1148 if (opt_verbosecall && indent)
1151 /* calculate message length */
1155 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1158 logtextlen = strlen("Some Throwable");
1161 logtextlen += strlen(" thrown in ");
1165 utf_bytes(m->class->name) +
1167 utf_bytes(m->name) +
1168 utf_bytes(m->descriptor) +
1169 strlen("(NOSYNC,NATIVE");
1171 #if SIZEOF_VOID_P == 8
1173 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1175 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1178 if (m->class->sourcefile == NULL)
1179 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1181 logtextlen += utf_bytes(m->class->sourcefile);
1183 logtextlen += strlen(":65536)");
1187 logtextlen += strlen("call_java_method");
1190 logtextlen += strlen("0");
1192 /* allocate memory */
1194 dumpsize = dump_size();
1196 logtext = DMNEW(char, logtextlen);
1199 strcpy(logtext, "Exception ");
1200 utf_cat_classname(logtext, xptr->vftbl->class->name);
1203 strcpy(logtext, "Some Throwable");
1206 strcat(logtext, " thrown in ");
1209 utf_cat_classname(logtext, m->class->name);
1210 strcat(logtext, ".");
1211 utf_cat(logtext, m->name);
1212 utf_cat(logtext, m->descriptor);
1214 if (m->flags & ACC_SYNCHRONIZED)
1215 strcat(logtext, "(SYNC");
1217 strcat(logtext, "(NOSYNC");
1219 if (m->flags & ACC_NATIVE) {
1220 strcat(logtext, ",NATIVE");
1224 #if SIZEOF_VOID_P == 8
1225 sprintf(logtext + strlen(logtext),
1226 ")(0x%016lx) at position 0x%016lx",
1227 (ptrint) code->entrypoint, (ptrint) pos);
1229 sprintf(logtext + strlen(logtext),
1230 ")(0x%08x) at position 0x%08x",
1231 (ptrint) code->entrypoint, (ptrint) pos);
1236 /* XXX preliminary: This should get the actual codeinfo */
1237 /* in which the exception happened. */
1240 #if SIZEOF_VOID_P == 8
1241 sprintf(logtext + strlen(logtext),
1242 ")(0x%016lx) at position 0x%016lx (",
1243 (ptrint) code->entrypoint, (ptrint) pos);
1245 sprintf(logtext + strlen(logtext),
1246 ")(0x%08x) at position 0x%08x (",
1247 (ptrint) code->entrypoint, (ptrint) pos);
1250 if (m->class->sourcefile == NULL)
1251 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1253 utf_cat(logtext, m->class->sourcefile);
1255 sprintf(logtext + strlen(logtext), ":%d)", 0);
1259 strcat(logtext, "call_java_method");
1263 /* release memory */
1265 dump_release(dumpsize);
1269 #endif /* !defined(NDEBUG) */
1272 /* builtin_trace_args **********************************************************
1276 *******************************************************************************/
1278 #if !defined(NDEBUG)
1280 #ifdef TRACE_ARGS_NUM
1281 void builtin_trace_args(s8 a0, s8 a1,
1282 #if TRACE_ARGS_NUM >= 4
1284 #endif /* TRACE_ARGS_NUM >= 4 */
1285 #if TRACE_ARGS_NUM >= 6
1287 #endif /* TRACE_ARGS_NUM >= 6 */
1288 #if TRACE_ARGS_NUM == 8
1290 #endif /* TRACE_ARGS_NUM == 8 */
1302 /* calculate message length */
1305 strlen("4294967295 ") +
1306 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1308 strlen("called: ") +
1309 utf_bytes(m->class->name) +
1311 utf_bytes(m->name) +
1312 utf_bytes(m->descriptor) +
1313 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1315 /* add maximal argument length */
1317 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1319 /* allocate memory */
1321 dumpsize = dump_size();
1323 logtext = DMNEW(char, logtextlen);
1327 sprintf(logtext, "%10d ", callcount);
1328 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1330 pos = strlen(logtext);
1332 for (i = 0; i < methodindent; i++)
1333 logtext[pos++] = '\t';
1335 strcpy(logtext + pos, "called: ");
1337 utf_cat_classname(logtext, m->class->name);
1338 strcat(logtext, ".");
1339 utf_cat(logtext, m->name);
1340 utf_cat(logtext, m->descriptor);
1342 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1343 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1344 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1345 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1346 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1347 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1348 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1349 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1350 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1351 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1352 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1354 strcat(logtext, "(");
1356 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1357 /* Only Arguments in integer Registers are passed correctly here */
1358 /* long longs spilled on Stack have an wrong offset of +4 */
1359 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1360 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1361 switch (md->paramcount) {
1365 #if SIZEOF_VOID_P == 4
1367 sprintf(logtext + strlen(logtext),
1373 sprintf(logtext + strlen(logtext),
1378 #if TRACE_ARGS_NUM >= 4
1380 sprintf(logtext + strlen(logtext),
1381 "0x%llx, 0x%llx, 0x%llx",
1386 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1388 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1391 #endif /* TRACE_ARGS_NUM >= 4 */
1393 #if TRACE_ARGS_NUM >= 6
1395 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1397 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1402 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1404 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1407 #endif /* TRACE_ARGS_NUM >= 6 */
1409 #if TRACE_ARGS_NUM == 8
1411 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1413 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1415 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1419 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1421 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1423 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1425 #endif /* TRACE_ARGS_NUM == 8 */
1428 #if TRACE_ARGS_NUM == 2
1429 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1431 #elif TRACE_ARGS_NUM == 4
1432 sprintf(logtext + strlen(logtext),
1433 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1434 a0, a1, a2, a3, md->paramcount - 4);
1436 #elif TRACE_ARGS_NUM == 6
1437 sprintf(logtext + strlen(logtext),
1438 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1439 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1441 #elif TRACE_ARGS_NUM == 8
1442 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1444 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1446 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1447 , a6, a7, md->paramcount - 8);
1451 #else /* SIZEOF_VOID_P == 4 */
1454 sprintf(logtext + strlen(logtext),
1460 sprintf(logtext + strlen(logtext),
1466 sprintf(logtext + strlen(logtext),
1467 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1471 sprintf(logtext + strlen(logtext),
1472 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1476 #if TRACE_ARGS_NUM >= 6
1478 sprintf(logtext + strlen(logtext),
1479 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1480 a0, a1, a2, a3, a4);
1484 sprintf(logtext + strlen(logtext),
1485 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1486 a0, a1, a2, a3, a4, a5);
1488 #endif /* TRACE_ARGS_NUM >= 6 */
1490 #if TRACE_ARGS_NUM == 8
1492 sprintf(logtext + strlen(logtext),
1493 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1494 a0, a1, a2, a3, a4, a5, a6);
1498 sprintf(logtext + strlen(logtext),
1499 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1500 a0, a1, a2, a3, a4, a5, a6, a7);
1502 #endif /* TRACE_ARGS_NUM == 8 */
1505 #if TRACE_ARGS_NUM == 4
1506 sprintf(logtext + strlen(logtext),
1507 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1508 a0, a1, a2, a3, md->paramcount - 4);
1510 #elif TRACE_ARGS_NUM == 6
1511 sprintf(logtext + strlen(logtext),
1512 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1513 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1515 #elif TRACE_ARGS_NUM == 8
1516 sprintf(logtext + strlen(logtext),
1517 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1518 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1521 #endif /* SIZEOF_VOID_P == 4 */
1524 strcat(logtext, ")");
1528 /* release memory */
1530 dump_release(dumpsize);
1535 #endif /* !defined(NDEBUG) */
1538 /* builtin_displaymethodstop ***************************************************
1542 *******************************************************************************/
1544 #if !defined(NDEBUG)
1545 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1553 java_objectheader *o;
1554 java_lang_String *s;
1562 /* calculate message length */
1565 strlen("4294967295 ") +
1566 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1568 strlen("finished: ") +
1569 utf_bytes(m->class->name) +
1571 utf_bytes(m->name) +
1572 utf_bytes(m->descriptor) +
1573 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1575 /* add maximal argument length */
1577 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1579 /* allocate memory */
1581 dumpsize = dump_size();
1583 logtext = DMNEW(char, logtextlen);
1585 /* outdent the log message */
1590 log_text("WARNING: unmatched methodindent--");
1592 /* generate the message */
1594 sprintf(logtext, " ");
1595 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1597 pos = strlen(logtext);
1599 for (i = 0; i < methodindent; i++)
1600 logtext[pos++] = '\t';
1602 strcpy(logtext + pos, "finished: ");
1603 utf_cat_classname(logtext, m->class->name);
1604 strcat(logtext, ".");
1605 utf_cat(logtext, m->name);
1606 utf_cat(logtext, m->descriptor);
1608 switch (md->returntype.type) {
1610 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1614 #if SIZEOF_VOID_P == 4
1615 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1617 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1622 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1624 /* check return argument for java.lang.Class or java.lang.String */
1626 o = (java_objectheader *) (ptrint) l;
1629 if (o->vftbl->class == class_java_lang_String) {
1630 /* get java.lang.String object and the length of the
1633 s = (java_lang_String *) (ptrint) l;
1635 u = javastring_toutf(s, false);
1637 len = strlen(", String = \"") + utf_bytes(u) + strlen("\"");
1639 /* realloc memory for string length */
1641 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1643 /* convert to utf8 string and strcat it to the logtext */
1645 strcat(logtext, ", String = \"");
1646 utf_cat(logtext, u);
1647 strcat(logtext, "\"");
1650 if (o->vftbl->class == class_java_lang_Class) {
1651 /* if the object returned is a java.lang.Class
1652 cast it to classinfo structure and get the name
1655 c = (classinfo *) (ptrint) l;
1660 /* if the object returned is not a java.lang.String or
1661 a java.lang.Class just print the name of the class */
1663 u = o->vftbl->class->name;
1666 len = strlen(", Class = \"") + utf_bytes(u) + strlen("\"");
1668 /* realloc memory for string length */
1670 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1672 /* strcat to the logtext */
1674 strcat(logtext, ", Class = \"");
1675 utf_cat_classname(logtext, u);
1676 strcat(logtext, "\"");
1683 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1688 #if SIZEOF_VOID_P == 4
1689 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1691 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1698 /* release memory */
1700 dump_release(dumpsize);
1702 #endif /* !defined(NDEBUG) */
1705 #if defined(ENABLE_CYCLES_STATS)
1706 void builtin_print_cycles_stats(FILE *file)
1708 fprintf(file,"builtin cylce count statistics:\n");
1710 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1711 CYCLES_STATS_PRINT(builtin_monitorenter,file);
1712 CYCLES_STATS_PRINT(builtin_monitorexit ,file);
1713 CYCLES_STATS_PRINT(builtin_new ,file);
1717 #endif /* defined(ENABLE_CYCLES_STATS) */
1719 #if defined(ENABLE_THREADS)
1720 void builtin_monitorenter(java_objectheader *o)
1722 #if defined(ENABLE_CYCLES_STATS)
1723 u8 cycles_start, cycles_overhead, cycles_end;
1726 CYCLES_STATS_GET(cycles_start);
1727 CYCLES_STATS_GET(cycles_overhead);
1729 lock_monitor_enter((threadobject *) THREADOBJECT, o);
1731 CYCLES_STATS_GET(cycles_end);
1732 CYCLES_STATS_COUNT(builtin_monitorenter, cycles_end - cycles_overhead);
1733 CYCLES_STATS_COUNT(builtin_overhead , cycles_overhead - cycles_start);
1738 #if defined(ENABLE_THREADS)
1740 * Locks the class object - needed for static synchronized methods.
1742 void builtin_staticmonitorenter(classinfo *c)
1744 builtin_monitorenter(&c->object.header);
1749 #if defined(ENABLE_THREADS)
1750 void builtin_monitorexit(java_objectheader *o)
1752 #if defined(ENABLE_CYCLES_STATS)
1753 u8 cycles_start, cycles_end;
1756 CYCLES_STATS_GET(cycles_start);
1758 lock_monitor_exit((threadobject *) THREADOBJECT, o);
1760 CYCLES_STATS_GET(cycles_end);
1761 CYCLES_STATS_COUNT(builtin_monitorexit, cycles_end - cycles_start);
1766 /*****************************************************************************
1767 MISCELLANEOUS HELPER FUNCTIONS
1768 *****************************************************************************/
1772 /*********** Functions for integer divisions *****************************
1774 On some systems (eg. DEC ALPHA), integer division is not supported by the
1775 CPU. These helper functions implement the missing functionality.
1777 ******************************************************************************/
1779 #if !SUPPORT_DIVISION
1780 s4 builtin_idiv(s4 a, s4 b)
1789 s4 builtin_irem(s4 a, s4 b)
1797 #endif /* !SUPPORT_DIVISION */
1800 /* functions for long arithmetics **********************************************
1802 On systems where 64 bit Integers are not supported by the CPU,
1803 these functions are needed.
1805 ******************************************************************************/
1807 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1808 s8 builtin_ladd(s8 a, s8 b)
1821 s8 builtin_lsub(s8 a, s8 b)
1834 s8 builtin_lneg(s8 a)
1846 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1849 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1850 s8 builtin_lmul(s8 a, s8 b)
1862 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1865 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1866 s8 builtin_ldiv(s8 a, s8 b)
1879 s8 builtin_lrem(s8 a, s8 b)
1891 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1894 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1895 s8 builtin_lshl(s8 a, s4 b)
1908 s8 builtin_lshr(s8 a, s4 b)
1921 s8 builtin_lushr(s8 a, s4 b)
1926 c = ((u8) a) >> (b & 63);
1933 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1936 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1937 s8 builtin_land(s8 a, s8 b)
1950 s8 builtin_lor(s8 a, s8 b)
1963 s8 builtin_lxor(s8 a, s8 b)
1975 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1978 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1979 s4 builtin_lcmp(s8 a, s8 b)
1993 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1996 /* functions for unsupported floating instructions ****************************/
1998 /* used to convert FLT_xxx defines into float values */
2000 static inline float intBitsToFloat(s4 i)
2009 /* used to convert DBL_xxx defines into double values */
2011 static inline float longBitsToDouble(s8 l)
2021 float builtin_fadd(float a, float b)
2023 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2024 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2035 if (copysignf(1.0, a) == copysignf(1.0, b))
2038 return intBitsToFloat(FLT_NAN);
2044 float builtin_fsub(float a, float b)
2046 return builtin_fadd(a, builtin_fneg(b));
2050 float builtin_fmul(float a, float b)
2052 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2053 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2055 if (finitef(b)) return a * b;
2057 if (a == 0) return intBitsToFloat(FLT_NAN);
2058 else return copysignf(b, copysignf(1.0, b)*a);
2063 if (b == 0) return intBitsToFloat(FLT_NAN);
2064 else return copysignf(a, copysignf(1.0, a)*b);
2067 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2073 /* builtin_ddiv ****************************************************************
2075 Implementation as described in VM Spec.
2077 *******************************************************************************/
2079 float builtin_fdiv(float a, float b)
2083 /* If neither value1' nor value2' is NaN, the sign of the result */
2084 /* is positive if both values have the same sign, negative if the */
2085 /* values have different signs. */
2091 /* If either value1' or value2' is NaN, the result is NaN. */
2093 return intBitsToFloat(FLT_NAN);
2096 /* Division of a finite value by an infinity results in a */
2097 /* signed zero, with the sign-producing rule just given. */
2099 /* is sign equal? */
2101 if (copysignf(1.0, a) == copysignf(1.0, b))
2110 /* If either value1' or value2' is NaN, the result is NaN. */
2112 return intBitsToFloat(FLT_NAN);
2114 } else if (finitef(b)) {
2115 /* Division of an infinity by a finite value results in a signed */
2116 /* infinity, with the sign-producing rule just given. */
2118 /* is sign equal? */
2120 if (copysignf(1.0, a) == copysignf(1.0, b))
2121 return intBitsToFloat(FLT_POSINF);
2123 return intBitsToFloat(FLT_NEGINF);
2126 /* Division of an infinity by an infinity results in NaN. */
2128 return intBitsToFloat(FLT_NAN);
2134 float builtin_fneg(float a)
2136 if (isnanf(a)) return a;
2138 if (finitef(a)) return -a;
2139 else return copysignf(a, -copysignf(1.0, a));
2142 #endif /* !SUPPORT_FLOAT */
2145 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2146 s4 builtin_fcmpl(float a, float b)
2148 if (isnanf(a)) return -1;
2149 if (isnanf(b)) return -1;
2150 if (!finitef(a) || !finitef(b)) {
2151 a = finitef(a) ? 0 : copysignf(1.0, a);
2152 b = finitef(b) ? 0 : copysignf(1.0, b);
2154 if (a > b) return 1;
2155 if (a == b) return 0;
2160 s4 builtin_fcmpg(float a, float b)
2162 if (isnanf(a)) return 1;
2163 if (isnanf(b)) return 1;
2164 if (!finitef(a) || !finitef(b)) {
2165 a = finitef(a) ? 0 : copysignf(1.0, a);
2166 b = finitef(b) ? 0 : copysignf(1.0, b);
2168 if (a > b) return 1;
2169 if (a == b) return 0;
2172 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2175 float builtin_frem(float a, float b)
2181 /* functions for unsupported double instructions ******************************/
2184 double builtin_dadd(double a, double b)
2186 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2187 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2189 if (finite(b)) return a + b;
2193 if (finite(b)) return a;
2195 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2196 else return longBitsToDouble(DBL_NAN);
2202 double builtin_dsub(double a, double b)
2204 return builtin_dadd(a, builtin_dneg(b));
2208 double builtin_dmul(double a, double b)
2210 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2211 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2213 if (finite(b)) return a * b;
2215 if (a == 0) return longBitsToDouble(DBL_NAN);
2216 else return copysign(b, copysign(1.0, b) * a);
2221 if (b == 0) return longBitsToDouble(DBL_NAN);
2222 else return copysign(a, copysign(1.0, a) * b);
2225 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2231 /* builtin_ddiv ****************************************************************
2233 Implementation as described in VM Spec.
2235 *******************************************************************************/
2237 double builtin_ddiv(double a, double b)
2241 /* If neither value1' nor value2' is NaN, the sign of the result */
2242 /* is positive if both values have the same sign, negative if the */
2243 /* values have different signs. */
2249 /* If either value1' or value2' is NaN, the result is NaN. */
2251 return longBitsToDouble(DBL_NAN);
2254 /* Division of a finite value by an infinity results in a */
2255 /* signed zero, with the sign-producing rule just given. */
2257 /* is sign equal? */
2259 if (copysign(1.0, a) == copysign(1.0, b))
2268 /* If either value1' or value2' is NaN, the result is NaN. */
2270 return longBitsToDouble(DBL_NAN);
2272 } else if (finite(b)) {
2273 /* Division of an infinity by a finite value results in a signed */
2274 /* infinity, with the sign-producing rule just given. */
2276 /* is sign equal? */
2278 if (copysign(1.0, a) == copysign(1.0, b))
2279 return longBitsToDouble(DBL_POSINF);
2281 return longBitsToDouble(DBL_NEGINF);
2284 /* Division of an infinity by an infinity results in NaN. */
2286 return longBitsToDouble(DBL_NAN);
2292 /* builtin_dneg ****************************************************************
2294 Implemented as described in VM Spec.
2296 *******************************************************************************/
2298 double builtin_dneg(double a)
2301 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2308 /* If the operand is a zero, the result is the zero of opposite */
2314 /* If the operand is an infinity, the result is the infinity of */
2315 /* opposite sign. */
2317 return copysign(a, -copysign(1.0, a));
2321 #endif /* !SUPPORT_DOUBLE */
2324 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2325 s4 builtin_dcmpl(double a, double b)
2327 if (isnan(a)) return -1;
2328 if (isnan(b)) return -1;
2329 if (!finite(a) || !finite(b)) {
2330 a = finite(a) ? 0 : copysign(1.0, a);
2331 b = finite(b) ? 0 : copysign(1.0, b);
2333 if (a > b) return 1;
2334 if (a == b) return 0;
2339 s4 builtin_dcmpg(double a, double b)
2341 if (isnan(a)) return 1;
2342 if (isnan(b)) return 1;
2343 if (!finite(a) || !finite(b)) {
2344 a = finite(a) ? 0 : copysign(1.0, a);
2345 b = finite(b) ? 0 : copysign(1.0, b);
2347 if (a > b) return 1;
2348 if (a == b) return 0;
2351 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2354 double builtin_drem(double a, double b)
2360 /* conversion operations ******************************************************/
2363 s8 builtin_i2l(s4 i)
2375 s4 builtin_l2i(s8 l)
2386 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2387 float builtin_i2f(s4 a)
2389 float f = (float) a;
2392 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2395 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2396 double builtin_i2d(s4 a)
2398 double d = (double) a;
2401 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2404 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2405 float builtin_l2f(s8 a)
2408 float f = (float) a;
2414 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2417 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2418 double builtin_l2d(s8 a)
2421 double d = (double) a;
2427 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2430 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
2431 s4 builtin_f2i(float a)
2435 i = builtin_d2i((double) a);
2446 if (a < (-2147483648))
2447 return (-2147483648);
2450 f = copysignf((float) 1.0, a);
2453 return (-2147483648); */
2455 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
2458 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2459 s8 builtin_f2l(float a)
2463 l = builtin_d2l((double) a);
2470 if (a > 9223372036854775807L)
2471 return 9223372036854775807L;
2472 if (a < (-9223372036854775808L))
2473 return (-9223372036854775808L);
2478 f = copysignf((float) 1.0, a);
2480 return 9223372036854775807L;
2481 return (-9223372036854775808L); */
2483 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2486 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
2487 s4 builtin_d2i(double a)
2492 if (a >= 2147483647)
2494 if (a <= (-2147483647-1))
2495 return (-2147483647-1);
2500 d = copysign(1.0, a);
2503 return (-2147483647-1);
2505 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
2508 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2509 s8 builtin_d2l(double a)
2514 if (a >= 9223372036854775807LL)
2515 return 9223372036854775807LL;
2516 if (a <= (-9223372036854775807LL-1))
2517 return (-9223372036854775807LL-1);
2522 d = copysign(1.0, a);
2524 return 9223372036854775807LL;
2525 return (-9223372036854775807LL-1);
2527 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2530 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2531 double builtin_f2d(float a)
2533 if (finitef(a)) return (double) a;
2536 return longBitsToDouble(DBL_NAN);
2538 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2542 float builtin_d2f(double a)
2548 return intBitsToFloat(FLT_NAN);
2550 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2553 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2556 /* builtin_clone_array *********************************************************
2558 Wrapper function for cloning arrays.
2560 *******************************************************************************/
2562 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2564 java_arrayheader *ah;
2565 java_lang_Cloneable *c;
2567 c = (java_lang_Cloneable *) o;
2569 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2575 /* builtin_asm_get_exceptionptrptr *********************************************
2577 this is a wrapper for calls from asmpart
2579 *******************************************************************************/
2581 #if defined(ENABLE_THREADS)
2582 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2584 return builtin_get_exceptionptrptr();
2590 * These are local overrides for various environment variables in Emacs.
2591 * Please do not remove this and leave it at the end of the file, where
2592 * Emacs will automagically detect them.
2593 * ---------------------------------------------------------------------
2596 * indent-tabs-mode: t
2600 * vim:noexpandtab:sw=4:ts=4: