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 4815 2006-04-23 19:16:54Z edwin $
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(USE_THREADS)
67 # if defined(NATIVE_THREADS)
68 # include "threads/native/threads.h"
70 # include "threads/green/threads.h"
71 # include "threads/green/locks.h"
75 #include "toolbox/logging.h"
76 #include "toolbox/util.h"
77 #include "vm/builtin.h"
79 #include "vm/exceptions.h"
80 #include "vm/global.h"
81 #include "vm/initialize.h"
82 #include "vm/loader.h"
83 #include "vm/options.h"
84 #include "vm/stringlocal.h"
85 #include "vm/jit/asmpart.h"
86 #include "vm/jit/patcher.h"
87 #include "vm/rt-timing.h"
88 #include "vm/cycles-stats.h"
91 /* include builtin tables *****************************************************/
93 #include "vm/builtintable.inc"
96 CYCLES_STATS_DECLARE(builtin_monitorenter,100,2)
97 CYCLES_STATS_DECLARE(builtin_monitorexit ,100,2)
98 CYCLES_STATS_DECLARE(builtin_new ,100,5)
99 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
101 /* builtintable_init ***********************************************************
103 Parse the descriptors of builtin functions and create the parsed
106 *******************************************************************************/
108 static bool builtintable_init(void)
110 descriptor_pool *descpool;
114 s4 entries_automatic;
117 /* mark start of dump memory area */
119 dumpsize = dump_size();
121 /* create a new descriptor pool */
123 descpool = descriptor_pool_new(class_java_lang_Object);
125 /* add some entries we need */
127 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
130 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
133 /* calculate table entries statically */
136 sizeof(builtintable_internal) / sizeof(builtintable_entry);
139 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
140 - 1; /* last filler entry (comment see builtintable.inc) */
142 /* first add all descriptors to the pool */
144 for (i = 0; i < entries_internal; i++) {
145 /* create a utf8 string from descriptor */
147 descriptor = utf_new_char(builtintable_internal[i].descriptor);
149 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
150 /* release dump area */
152 dump_release(dumpsize);
158 for (i = 0; i < entries_automatic; i++) {
159 /* create a utf8 string from descriptor */
161 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
163 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
164 /* release dump area */
166 dump_release(dumpsize);
172 /* create the class reference table */
174 (void) descriptor_pool_create_classrefs(descpool, NULL);
176 /* allocate space for the parsed descriptors */
178 descriptor_pool_alloc_parsed_descriptors(descpool);
180 /* now parse all descriptors */
182 for (i = 0; i < entries_internal; i++) {
183 /* create a utf8 string from descriptor */
185 descriptor = utf_new_char(builtintable_internal[i].descriptor);
187 /* parse the descriptor, builtin is always static (no `this' pointer) */
189 builtintable_internal[i].md =
190 descriptor_pool_parse_method_descriptor(descpool, descriptor,
194 for (i = 0; i < entries_automatic; i++) {
195 /* create a utf8 string from descriptor */
197 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
199 /* parse the descriptor, builtin is always static (no `this' pointer) */
201 builtintable_automatic[i].md =
202 descriptor_pool_parse_method_descriptor(descpool, descriptor,
206 /* release dump area */
208 dump_release(dumpsize);
214 /* builtintable_comparator *****************************************************
216 qsort comparator for the automatic builtin table.
218 *******************************************************************************/
220 static int builtintable_comparator(const void *a, const void *b)
222 builtintable_entry *bte1;
223 builtintable_entry *bte2;
225 bte1 = (builtintable_entry *) a;
226 bte2 = (builtintable_entry *) b;
228 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
232 /* builtintable_sort_automatic *************************************************
234 Sorts the automatic builtin table.
236 *******************************************************************************/
238 static void builtintable_sort_automatic(void)
242 /* calculate table size statically (`- 1' comment see builtintable.inc) */
244 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
246 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
247 builtintable_comparator);
251 /* builtin_init ****************************************************************
255 *******************************************************************************/
257 bool builtin_init(void)
259 /* initialize the builtin tables */
261 if (!builtintable_init())
264 /* sort builtin tables */
266 builtintable_sort_automatic();
272 /* builtintable_get_internal ***************************************************
274 Finds an entry in the builtintable for internal functions and
275 returns the a pointer to the structure.
277 *******************************************************************************/
279 builtintable_entry *builtintable_get_internal(functionptr fp)
283 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
284 if (builtintable_internal[i].fp == fp)
285 return &builtintable_internal[i];
292 /* builtintable_get_automatic **************************************************
294 Finds an entry in the builtintable for functions which are replaced
295 automatically and returns the a pointer to the structure.
297 *******************************************************************************/
299 builtintable_entry *builtintable_get_automatic(s4 opcode)
301 builtintable_entry *first;
302 builtintable_entry *last;
303 builtintable_entry *middle;
307 /* calculate table size statically (`- 1' comment see builtintable.inc) */
309 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
311 first = builtintable_automatic;
312 last = builtintable_automatic + entries;
314 while (entries > 0) {
316 middle = first + half;
318 if (middle->opcode < opcode) {
325 return (first != last ? first : NULL);
329 /*****************************************************************************
331 *****************************************************************************/
335 /*************** internal function: builtin_isanysubclass *********************
337 Checks a subclass relation between two classes. Implemented interfaces
338 are interpreted as super classes.
339 Return value: 1 ... sub is subclass of super
342 *****************************************************************************/
343 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
346 castinfo classvalues;
351 if (super->flags & ACC_INTERFACE) {
352 res = (sub->vftbl->interfacetablelength > super->index) &&
353 (sub->vftbl->interfacetable[-super->index] != NULL);
356 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
358 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
359 (u4) classvalues.super_diffval;
366 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
370 castinfo classvalues;
375 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
377 if ((base = classvalues.super_baseval) <= 0) {
378 /* super is an interface */
379 res = (sub->interfacetablelength > -base) &&
380 (sub->interfacetable[base] != NULL);
382 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
383 <= (u4) classvalues.super_diffval;
390 /****************** function: builtin_instanceof *****************************
392 Checks if an object is an instance of some given class (or subclass of
393 that class). If class is an interface, checks if the interface is
395 Return value: 1 ... obj is an instance of class or implements the interface
396 0 ... otherwise or if obj == NULL
398 *****************************************************************************/
400 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
405 return builtin_isanysubclass(obj->vftbl->class, class);
410 /**************** function: builtin_checkcast *******************************
412 The same as builtin_instanceof except that 1 is returned when
415 ****************************************************************************/
417 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
422 if (builtin_isanysubclass(obj->vftbl->class, class))
429 /* builtin_descriptorscompatible ***********************************************
431 Checks if two array type descriptors are assignment compatible
433 Return value: 1 ... target = desc is possible
436 *******************************************************************************/
438 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
439 arraydescriptor *target)
444 if (desc->arraytype != target->arraytype)
447 if (desc->arraytype != ARRAYTYPE_OBJECT)
450 /* {both arrays are arrays of references} */
452 if (desc->dimension == target->dimension) {
453 /* an array which contains elements of interface types is
454 allowed to be casted to Object (JOWENN)*/
456 if ((desc->elementvftbl->baseval < 0) &&
457 (target->elementvftbl->baseval == 1))
460 return builtin_isanysubclass_vftbl(desc->elementvftbl,
461 target->elementvftbl);
464 if (desc->dimension < target->dimension)
467 /* {desc has higher dimension than target} */
469 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
470 target->elementvftbl);
474 /* builtin_arraycheckcast ******************************************************
476 Checks if an object is really a subtype of the requested array
477 type. The object has to be an array to begin with. For simple
478 arrays (int, short, double, etc.) the types have to match exactly.
479 For arrays of objects, the type of elements in the array has to be
480 a subtype (or the same type) of the requested element type. For
481 arrays of arrays (which in turn can again be arrays of arrays), the
482 types at the lowest level have to satisfy the corresponding sub
485 *******************************************************************************/
487 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
489 arraydescriptor *desc;
494 if ((desc = o->vftbl->arraydesc) == NULL)
497 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
501 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
506 return builtin_arraycheckcast(o, targetclass);
510 /* builtin_throw_exception *****************************************************
512 Sets the exceptionptr with the thrown exception and prints some
513 debugging information. Called from asm_vm_call_method.
515 *******************************************************************************/
517 void *builtin_throw_exception(java_objectheader *xptr)
520 java_lang_Throwable *t;
526 t = (java_lang_Throwable *) xptr;
528 /* calculate message length */
530 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
534 utf_strlen(xptr->vftbl->class->name) +
536 javastring_strlen(t->detailMessage);
539 logtextlen += strlen("(nil)");
541 /* allocate memory */
543 dumpsize = dump_size();
545 logtext = DMNEW(char, logtextlen);
547 strcpy(logtext, "Builtin exception thrown: ");
550 utf_sprint_classname(logtext + strlen(logtext),
551 xptr->vftbl->class->name);
553 if (t->detailMessage) {
556 buf = javastring_tochar((java_objectheader *) t->detailMessage);
557 strcat(logtext, ": ");
558 strcat(logtext, buf);
559 MFREE(buf, char, strlen(buf));
563 strcat(logtext, "(nil)");
570 dump_release(dumpsize);
572 #endif /* !defined(NDEBUG) */
574 /* actually set the exception */
576 *exceptionptr = xptr;
578 /* Return a NULL pointer. This is required for vm_call_method to
579 check for an exception. This is for convenience. */
585 /* builtin_canstore ************************************************************
587 Checks, if an object can be stored in an array.
589 Return value: 1 ... possible
592 *******************************************************************************/
594 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
596 arraydescriptor *desc;
597 arraydescriptor *valuedesc;
598 vftbl_t *componentvftbl;
601 castinfo classvalues;
606 /* The following is guaranteed (by verifier checks):
608 * *) oa->...vftbl->arraydesc != NULL
609 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
610 * *) o->vftbl is not an interface vftbl
613 desc = oa->header.objheader.vftbl->arraydesc;
614 componentvftbl = desc->componentvftbl;
615 valuevftbl = o->vftbl;
617 if ((desc->dimension - 1) == 0) {
620 /* {oa is a one-dimensional array} */
621 /* {oa is an array of references} */
623 if (valuevftbl == componentvftbl)
626 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
628 if ((base = classvalues.super_baseval) <= 0)
629 /* an array of interface references */
630 return (valuevftbl->interfacetablelength > -base &&
631 valuevftbl->interfacetable[base] != NULL);
633 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
634 <= (unsigned) classvalues.super_diffval);
639 /* {oa has dimension > 1} */
640 /* {componentvftbl->arraydesc != NULL} */
642 /* check if o is an array */
644 if ((valuedesc = valuevftbl->arraydesc) == NULL)
647 /* {o is an array} */
649 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
653 /* This is an optimized version where a is guaranteed to be one-dimensional */
654 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
656 arraydescriptor *desc;
657 vftbl_t *elementvftbl;
661 castinfo classvalues;
665 /* The following is guaranteed (by verifier checks):
667 * *) a->...vftbl->arraydesc != NULL
668 * *) a->...vftbl->arraydesc->elementvftbl != NULL
669 * *) a->...vftbl->arraydesc->dimension == 1
670 * *) o->vftbl is not an interface vftbl
673 desc = a->header.objheader.vftbl->arraydesc;
674 elementvftbl = desc->elementvftbl;
675 valuevftbl = o->vftbl;
677 /* {a is a one-dimensional array} */
679 if (valuevftbl == elementvftbl)
682 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
684 if ((base = classvalues.super_baseval) <= 0)
685 /* an array of interface references */
686 return (valuevftbl->interfacetablelength > -base &&
687 valuevftbl->interfacetable[base] != NULL);
689 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
690 <= (unsigned) classvalues.super_diffval;
696 /* This is an optimized version where a is guaranteed to be a
697 * one-dimensional array of a class type */
698 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
700 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->elementvftbl is not an interface vftbl
712 * *) a->...vftbl->arraydesc->dimension == 1
713 * *) o->vftbl is not an interface vftbl
716 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
717 valuevftbl = o->vftbl;
719 /* {a is a one-dimensional array} */
721 if (valuevftbl == elementvftbl)
724 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
726 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
727 <= (unsigned) classvalues.super_diffval;
733 /* builtin_new *****************************************************************
735 Creates a new instance of class c on the heap.
737 Return value: pointer to the object or NULL if no memory is
740 *******************************************************************************/
742 java_objectheader *builtin_new(classinfo *c)
744 java_objectheader *o;
745 #if defined(ENABLE_RT_TIMING)
746 struct timespec time_start, time_end;
748 #if defined(ENABLE_CYCLES_STATS)
749 u8 cycles_start, cycles_end;
752 RT_TIMING_GET_TIME(time_start);
753 CYCLES_STATS_GET(cycles_start);
755 /* is the class loaded */
757 assert(c->state & CLASS_LOADED);
759 /* check if we can instantiate this class */
761 if (c->flags & ACC_ABSTRACT) {
763 new_exception_utfmessage(string_java_lang_InstantiationError,
768 /* is the class linked */
770 if (!(c->state & CLASS_LINKED))
774 if (!(c->state & CLASS_INITIALIZED)) {
777 log_message_class("Initialize class (from builtin_new): ", c);
780 if (!initialize_class(c))
784 o = heap_allocate(c->instancesize, true, c->finalizer);
791 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
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(USE_THREADS) && defined(NATIVE_THREADS)
851 initObjectLock(&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 ") +
1156 utf_strlen(xptr->vftbl->class->name);
1159 logtextlen = strlen("Some Throwable");
1162 logtextlen += strlen(" thrown in ");
1166 utf_strlen(m->class->name) +
1168 utf_strlen(m->name) +
1169 utf_strlen(m->descriptor) +
1170 strlen("(NOSYNC,NATIVE");
1172 #if SIZEOF_VOID_P == 8
1174 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1176 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1179 if (m->class->sourcefile == NULL)
1180 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1182 logtextlen += utf_strlen(m->class->sourcefile);
1184 logtextlen += strlen(":65536)");
1187 logtextlen += strlen("call_java_method");
1189 logtextlen += strlen("0");
1191 /* allocate memory */
1193 dumpsize = dump_size();
1195 logtext = DMNEW(char, logtextlen);
1198 strcpy(logtext, "Exception ");
1199 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1202 strcpy(logtext, "Some Throwable");
1205 strcat(logtext, " thrown in ");
1208 utf_strcat_classname(logtext, m->class->name);
1209 strcat(logtext, ".");
1210 utf_strcat(logtext, m->name);
1211 utf_strcat(logtext, m->descriptor);
1213 if (m->flags & ACC_SYNCHRONIZED)
1214 strcat(logtext, "(SYNC");
1216 strcat(logtext, "(NOSYNC");
1218 if (m->flags & ACC_NATIVE) {
1219 strcat(logtext, ",NATIVE");
1223 #if SIZEOF_VOID_P == 8
1224 sprintf(logtext + strlen(logtext),
1225 ")(0x%016lx) at position 0x%016lx",
1226 (ptrint) code->entrypoint, (ptrint) pos);
1228 sprintf(logtext + strlen(logtext),
1229 ")(0x%08x) at position 0x%08x",
1230 (ptrint) code->entrypoint, (ptrint) pos);
1235 /* XXX preliminary: This should get the actual codeinfo */
1236 /* in which the exception happened. */
1239 #if SIZEOF_VOID_P == 8
1240 sprintf(logtext + strlen(logtext),
1241 ")(0x%016lx) at position 0x%016lx (",
1242 (ptrint) code->entrypoint, (ptrint) pos);
1244 sprintf(logtext + strlen(logtext),
1245 ")(0x%08x) at position 0x%08x (",
1246 (ptrint) code->entrypoint, (ptrint) pos);
1249 if (m->class->sourcefile == NULL)
1250 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1252 utf_strcat(logtext, m->class->sourcefile);
1254 sprintf(logtext + strlen(logtext), ":%d)", 0);
1258 strcat(logtext, "call_java_method");
1262 /* release memory */
1264 dump_release(dumpsize);
1268 #endif /* !defined(NDEBUG) */
1271 /* builtin_trace_args **********************************************************
1275 *******************************************************************************/
1277 #if !defined(NDEBUG)
1279 #ifdef TRACE_ARGS_NUM
1280 void builtin_trace_args(s8 a0, s8 a1,
1281 #if TRACE_ARGS_NUM >= 4
1283 #endif /* TRACE_ARGS_NUM >= 4 */
1284 #if TRACE_ARGS_NUM >= 6
1286 #endif /* TRACE_ARGS_NUM >= 6 */
1287 #if TRACE_ARGS_NUM == 8
1289 #endif /* TRACE_ARGS_NUM == 8 */
1301 /* calculate message length */
1304 strlen("4294967295 ") +
1305 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1307 strlen("called: ") +
1308 utf_strlen(m->class->name) +
1310 utf_strlen(m->name) +
1311 utf_strlen(m->descriptor) +
1312 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1314 /* add maximal argument length */
1316 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1318 /* allocate memory */
1320 dumpsize = dump_size();
1322 logtext = DMNEW(char, logtextlen);
1326 sprintf(logtext, "%10d ", callcount);
1327 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1329 pos = strlen(logtext);
1331 for (i = 0; i < methodindent; i++)
1332 logtext[pos++] = '\t';
1334 strcpy(logtext + pos, "called: ");
1336 utf_strcat_classname(logtext, m->class->name);
1337 strcat(logtext, ".");
1338 utf_strcat(logtext, m->name);
1339 utf_strcat(logtext, m->descriptor);
1341 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1342 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1343 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1344 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1345 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1346 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1347 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1348 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1349 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1350 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1351 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1353 strcat(logtext, "(");
1355 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1356 /* Only Arguments in integer Registers are passed correctly here */
1357 /* long longs spilled on Stack have an wrong offset of +4 */
1358 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1359 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1360 switch (md->paramcount) {
1364 #if SIZEOF_VOID_P == 4
1366 sprintf(logtext + strlen(logtext),
1372 sprintf(logtext + strlen(logtext),
1377 #if TRACE_ARGS_NUM >= 4
1379 sprintf(logtext + strlen(logtext),
1380 "0x%llx, 0x%llx, 0x%llx",
1385 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1387 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1390 #endif /* TRACE_ARGS_NUM >= 4 */
1392 #if TRACE_ARGS_NUM >= 6
1394 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1396 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1401 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1403 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1406 #endif /* TRACE_ARGS_NUM >= 6 */
1408 #if TRACE_ARGS_NUM == 8
1410 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1412 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1414 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1418 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1420 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1422 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1424 #endif /* TRACE_ARGS_NUM == 8 */
1427 #if TRACE_ARGS_NUM == 2
1428 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1430 #elif TRACE_ARGS_NUM == 4
1431 sprintf(logtext + strlen(logtext),
1432 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1433 a0, a1, a2, a3, md->paramcount - 4);
1435 #elif TRACE_ARGS_NUM == 6
1436 sprintf(logtext + strlen(logtext),
1437 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1438 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1440 #elif TRACE_ARGS_NUM == 8
1441 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1443 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1445 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1446 , a6, a7, md->paramcount - 8);
1450 #else /* SIZEOF_VOID_P == 4 */
1453 sprintf(logtext + strlen(logtext),
1459 sprintf(logtext + strlen(logtext),
1465 sprintf(logtext + strlen(logtext),
1466 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1470 sprintf(logtext + strlen(logtext),
1471 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1475 #if TRACE_ARGS_NUM >= 6
1477 sprintf(logtext + strlen(logtext),
1478 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1479 a0, a1, a2, a3, a4);
1483 sprintf(logtext + strlen(logtext),
1484 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1485 a0, a1, a2, a3, a4, a5);
1487 #endif /* TRACE_ARGS_NUM >= 6 */
1489 #if TRACE_ARGS_NUM == 8
1491 sprintf(logtext + strlen(logtext),
1492 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1493 a0, a1, a2, a3, a4, a5, a6);
1497 sprintf(logtext + strlen(logtext),
1498 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1499 a0, a1, a2, a3, a4, a5, a6, a7);
1501 #endif /* TRACE_ARGS_NUM == 8 */
1504 #if TRACE_ARGS_NUM == 4
1505 sprintf(logtext + strlen(logtext),
1506 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1507 a0, a1, a2, a3, md->paramcount - 4);
1509 #elif TRACE_ARGS_NUM == 6
1510 sprintf(logtext + strlen(logtext),
1511 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1512 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1514 #elif TRACE_ARGS_NUM == 8
1515 sprintf(logtext + strlen(logtext),
1516 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1517 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1520 #endif /* SIZEOF_VOID_P == 4 */
1523 strcat(logtext, ")");
1527 /* release memory */
1529 dump_release(dumpsize);
1534 #endif /* !defined(NDEBUG) */
1537 /* builtin_displaymethodstop ***************************************************
1541 *******************************************************************************/
1543 #if !defined(NDEBUG)
1544 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1552 java_objectheader *o;
1553 java_lang_String *s;
1561 /* calculate message length */
1564 strlen("4294967295 ") +
1565 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1567 strlen("finished: ") +
1568 utf_strlen(m->class->name) +
1570 utf_strlen(m->name) +
1571 utf_strlen(m->descriptor) +
1572 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1574 /* add maximal argument length */
1576 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1578 /* allocate memory */
1580 dumpsize = dump_size();
1582 logtext = DMNEW(char, logtextlen);
1584 /* outdent the log message */
1589 log_text("WARNING: unmatched methodindent--");
1591 /* generate the message */
1593 sprintf(logtext, " ");
1594 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1596 pos = strlen(logtext);
1598 for (i = 0; i < methodindent; i++)
1599 logtext[pos++] = '\t';
1601 strcpy(logtext + pos, "finished: ");
1602 utf_strcat_classname(logtext, m->class->name);
1603 strcat(logtext, ".");
1604 utf_strcat(logtext, m->name);
1605 utf_strcat(logtext, m->descriptor);
1607 switch (md->returntype.type) {
1609 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1613 #if SIZEOF_VOID_P == 4
1614 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1616 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1621 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1623 /* check return argument for java.lang.Class or java.lang.String */
1625 o = (java_objectheader *) (ptrint) l;
1628 if (o->vftbl->class == class_java_lang_String) {
1629 /* get java.lang.String object and the length of the
1632 s= (java_lang_String *) (ptrint) l;
1634 len = strlen(", String = \"") + javastring_strlen(s) +
1637 /* realloc memory for string length */
1639 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1641 /* convert to utf8 string and strcat it to the logtext */
1643 u = javastring_toutf(s, false);
1645 strcat(logtext, ", String = \"");
1646 utf_strcat(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_strlen(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_strcat(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 /****************************************************************************
1706 SYNCHRONIZATION FUNCTIONS
1707 *****************************************************************************/
1709 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1711 * Lock the mutex of an object.
1713 void internal_lock_mutex_for_object(java_objectheader *object)
1715 mutexHashEntry *entry;
1718 assert(object != 0);
1720 hashValue = MUTEX_HASH_VALUE(object);
1721 entry = &mutexHashTable[hashValue];
1723 if (entry->object != 0) {
1724 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1726 entry->mutex.holder = 0;
1727 entry->mutex.count = 0;
1728 entry->mutex.muxWaiters = 0;
1731 while (entry->next != 0 && entry->object != object)
1732 entry = entry->next;
1734 if (entry->object != object) {
1735 entry->next = firstFreeOverflowEntry;
1736 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1738 entry = entry->next;
1741 assert(entry->conditionCount == 0);
1746 entry->mutex.holder = 0;
1747 entry->mutex.count = 0;
1748 entry->mutex.muxWaiters = 0;
1751 if (entry->object == 0)
1752 entry->object = object;
1754 internal_lock_mutex(&entry->mutex);
1759 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1761 * Unlocks the mutex of an object.
1763 void internal_unlock_mutex_for_object (java_objectheader *object)
1766 mutexHashEntry *entry;
1768 hashValue = MUTEX_HASH_VALUE(object);
1769 entry = &mutexHashTable[hashValue];
1771 if (entry->object == object) {
1772 internal_unlock_mutex(&entry->mutex);
1775 while (entry->next != 0 && entry->next->object != object)
1776 entry = entry->next;
1778 assert(entry->next != 0);
1780 internal_unlock_mutex(&entry->next->mutex);
1782 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1783 mutexHashEntry *unlinked = entry->next;
1785 entry->next = unlinked->next;
1786 unlinked->next = firstFreeOverflowEntry;
1787 firstFreeOverflowEntry = unlinked;
1793 #if defined(ENABLE_CYCLES_STATS)
1794 void builtin_print_cycles_stats(FILE *file)
1796 fprintf(file,"builtin cylce count statistics:\n");
1798 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1799 CYCLES_STATS_PRINT(builtin_monitorenter,file);
1800 CYCLES_STATS_PRINT(builtin_monitorexit ,file);
1801 CYCLES_STATS_PRINT(builtin_new ,file);
1805 #endif /* defined(ENABLE_CYCLES_STATS) */
1807 #if defined(USE_THREADS)
1808 void builtin_monitorenter(java_objectheader *o)
1810 #if defined(ENABLE_CYCLES_STATS)
1811 u8 cycles_start, cycles_overhead, cycles_end;
1814 #if !defined(NATIVE_THREADS)
1819 hashValue = MUTEX_HASH_VALUE(o);
1820 if (mutexHashTable[hashValue].object == o
1821 && mutexHashTable[hashValue].mutex.holder == currentThread)
1822 ++mutexHashTable[hashValue].mutex.count;
1824 internal_lock_mutex_for_object(o);
1827 #else /* defined(NATIVE_THREADS) */
1828 CYCLES_STATS_GET(cycles_start);
1829 CYCLES_STATS_GET(cycles_overhead);
1831 monitorEnter((threadobject *) THREADOBJECT, o);
1833 CYCLES_STATS_GET(cycles_end);
1834 CYCLES_STATS_COUNT(builtin_monitorenter, cycles_end - cycles_overhead);
1835 CYCLES_STATS_COUNT(builtin_overhead , cycles_overhead - cycles_start);
1836 #endif /* defined(NATIVE_THREADS) */
1841 #if defined(USE_THREADS)
1843 * Locks the class object - needed for static synchronized methods.
1845 void builtin_staticmonitorenter(classinfo *c)
1847 builtin_monitorenter(&c->object.header);
1852 #if defined(USE_THREADS)
1853 void builtin_monitorexit(java_objectheader *o)
1855 #if defined(ENABLE_CYCLES_STATS)
1856 u8 cycles_start, cycles_end;
1859 #if !defined(NATIVE_THREADS)
1864 hashValue = MUTEX_HASH_VALUE(o);
1865 if (mutexHashTable[hashValue].object == o) {
1866 if (mutexHashTable[hashValue].mutex.count == 1
1867 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1868 internal_unlock_mutex_for_object(o);
1870 --mutexHashTable[hashValue].mutex.count;
1873 internal_unlock_mutex_for_object(o);
1876 #else /* defined(NATIVE_THREADS) */
1877 CYCLES_STATS_GET(cycles_start);
1879 monitorExit((threadobject *) THREADOBJECT, o);
1881 CYCLES_STATS_GET(cycles_end);
1882 CYCLES_STATS_COUNT(builtin_monitorexit, cycles_end - cycles_start);
1883 #endif /* defined(NATIVE_THREADS) */
1888 /*****************************************************************************
1889 MISCELLANEOUS HELPER FUNCTIONS
1890 *****************************************************************************/
1894 /*********** Functions for integer divisions *****************************
1896 On some systems (eg. DEC ALPHA), integer division is not supported by the
1897 CPU. These helper functions implement the missing functionality.
1899 ******************************************************************************/
1901 #if !SUPPORT_DIVISION
1902 s4 builtin_idiv(s4 a, s4 b)
1911 s4 builtin_irem(s4 a, s4 b)
1919 #endif /* !SUPPORT_DIVISION */
1922 /* functions for long arithmetics **********************************************
1924 On systems where 64 bit Integers are not supported by the CPU,
1925 these functions are needed.
1927 ******************************************************************************/
1929 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1930 s8 builtin_ladd(s8 a, s8 b)
1943 s8 builtin_lsub(s8 a, s8 b)
1956 s8 builtin_lneg(s8 a)
1968 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1971 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1972 s8 builtin_lmul(s8 a, s8 b)
1984 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1987 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1988 s8 builtin_ldiv(s8 a, s8 b)
2001 s8 builtin_lrem(s8 a, s8 b)
2013 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
2016 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
2017 s8 builtin_lshl(s8 a, s4 b)
2030 s8 builtin_lshr(s8 a, s4 b)
2043 s8 builtin_lushr(s8 a, s4 b)
2048 c = ((u8) a) >> (b & 63);
2055 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
2058 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
2059 s8 builtin_land(s8 a, s8 b)
2072 s8 builtin_lor(s8 a, s8 b)
2085 s8 builtin_lxor(s8 a, s8 b)
2097 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2100 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2101 s4 builtin_lcmp(s8 a, s8 b)
2115 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2118 /* functions for unsupported floating instructions ****************************/
2120 /* used to convert FLT_xxx defines into float values */
2122 static inline float intBitsToFloat(s4 i)
2131 /* used to convert DBL_xxx defines into double values */
2133 static inline float longBitsToDouble(s8 l)
2143 float builtin_fadd(float a, float b)
2145 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2146 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2157 if (copysignf(1.0, a) == copysignf(1.0, b))
2160 return intBitsToFloat(FLT_NAN);
2166 float builtin_fsub(float a, float b)
2168 return builtin_fadd(a, builtin_fneg(b));
2172 float builtin_fmul(float a, float b)
2174 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2175 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2177 if (finitef(b)) return a * b;
2179 if (a == 0) return intBitsToFloat(FLT_NAN);
2180 else return copysignf(b, copysignf(1.0, b)*a);
2185 if (b == 0) return intBitsToFloat(FLT_NAN);
2186 else return copysignf(a, copysignf(1.0, a)*b);
2189 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2195 /* builtin_ddiv ****************************************************************
2197 Implementation as described in VM Spec.
2199 *******************************************************************************/
2201 float builtin_fdiv(float a, float b)
2205 /* If neither value1' nor value2' is NaN, the sign of the result */
2206 /* is positive if both values have the same sign, negative if the */
2207 /* values have different signs. */
2213 /* If either value1' or value2' is NaN, the result is NaN. */
2215 return intBitsToFloat(FLT_NAN);
2218 /* Division of a finite value by an infinity results in a */
2219 /* signed zero, with the sign-producing rule just given. */
2221 /* is sign equal? */
2223 if (copysignf(1.0, a) == copysignf(1.0, b))
2232 /* If either value1' or value2' is NaN, the result is NaN. */
2234 return intBitsToFloat(FLT_NAN);
2236 } else if (finitef(b)) {
2237 /* Division of an infinity by a finite value results in a signed */
2238 /* infinity, with the sign-producing rule just given. */
2240 /* is sign equal? */
2242 if (copysignf(1.0, a) == copysignf(1.0, b))
2243 return intBitsToFloat(FLT_POSINF);
2245 return intBitsToFloat(FLT_NEGINF);
2248 /* Division of an infinity by an infinity results in NaN. */
2250 return intBitsToFloat(FLT_NAN);
2256 float builtin_fneg(float a)
2258 if (isnanf(a)) return a;
2260 if (finitef(a)) return -a;
2261 else return copysignf(a, -copysignf(1.0, a));
2264 #endif /* !SUPPORT_FLOAT */
2267 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2268 s4 builtin_fcmpl(float a, float b)
2270 if (isnanf(a)) return -1;
2271 if (isnanf(b)) return -1;
2272 if (!finitef(a) || !finitef(b)) {
2273 a = finitef(a) ? 0 : copysignf(1.0, a);
2274 b = finitef(b) ? 0 : copysignf(1.0, b);
2276 if (a > b) return 1;
2277 if (a == b) return 0;
2282 s4 builtin_fcmpg(float a, float b)
2284 if (isnanf(a)) return 1;
2285 if (isnanf(b)) return 1;
2286 if (!finitef(a) || !finitef(b)) {
2287 a = finitef(a) ? 0 : copysignf(1.0, a);
2288 b = finitef(b) ? 0 : copysignf(1.0, b);
2290 if (a > b) return 1;
2291 if (a == b) return 0;
2294 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2297 float builtin_frem(float a, float b)
2303 /* functions for unsupported double instructions ******************************/
2306 double builtin_dadd(double a, double b)
2308 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2309 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2311 if (finite(b)) return a + b;
2315 if (finite(b)) return a;
2317 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2318 else return longBitsToDouble(DBL_NAN);
2324 double builtin_dsub(double a, double b)
2326 return builtin_dadd(a, builtin_dneg(b));
2330 double builtin_dmul(double a, double b)
2332 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2333 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2335 if (finite(b)) return a * b;
2337 if (a == 0) return longBitsToDouble(DBL_NAN);
2338 else return copysign(b, copysign(1.0, b) * a);
2343 if (b == 0) return longBitsToDouble(DBL_NAN);
2344 else return copysign(a, copysign(1.0, a) * b);
2347 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2353 /* builtin_ddiv ****************************************************************
2355 Implementation as described in VM Spec.
2357 *******************************************************************************/
2359 double builtin_ddiv(double a, double b)
2363 /* If neither value1' nor value2' is NaN, the sign of the result */
2364 /* is positive if both values have the same sign, negative if the */
2365 /* values have different signs. */
2371 /* If either value1' or value2' is NaN, the result is NaN. */
2373 return longBitsToDouble(DBL_NAN);
2376 /* Division of a finite value by an infinity results in a */
2377 /* signed zero, with the sign-producing rule just given. */
2379 /* is sign equal? */
2381 if (copysign(1.0, a) == copysign(1.0, b))
2390 /* If either value1' or value2' is NaN, the result is NaN. */
2392 return longBitsToDouble(DBL_NAN);
2394 } else if (finite(b)) {
2395 /* Division of an infinity by a finite value results in a signed */
2396 /* infinity, with the sign-producing rule just given. */
2398 /* is sign equal? */
2400 if (copysign(1.0, a) == copysign(1.0, b))
2401 return longBitsToDouble(DBL_POSINF);
2403 return longBitsToDouble(DBL_NEGINF);
2406 /* Division of an infinity by an infinity results in NaN. */
2408 return longBitsToDouble(DBL_NAN);
2414 /* builtin_dneg ****************************************************************
2416 Implemented as described in VM Spec.
2418 *******************************************************************************/
2420 double builtin_dneg(double a)
2423 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2430 /* If the operand is a zero, the result is the zero of opposite */
2436 /* If the operand is an infinity, the result is the infinity of */
2437 /* opposite sign. */
2439 return copysign(a, -copysign(1.0, a));
2443 #endif /* !SUPPORT_DOUBLE */
2446 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2447 s4 builtin_dcmpl(double a, double b)
2449 if (isnan(a)) return -1;
2450 if (isnan(b)) return -1;
2451 if (!finite(a) || !finite(b)) {
2452 a = finite(a) ? 0 : copysign(1.0, a);
2453 b = finite(b) ? 0 : copysign(1.0, b);
2455 if (a > b) return 1;
2456 if (a == b) return 0;
2461 s4 builtin_dcmpg(double a, double b)
2463 if (isnan(a)) return 1;
2464 if (isnan(b)) return 1;
2465 if (!finite(a) || !finite(b)) {
2466 a = finite(a) ? 0 : copysign(1.0, a);
2467 b = finite(b) ? 0 : copysign(1.0, b);
2469 if (a > b) return 1;
2470 if (a == b) return 0;
2473 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2476 double builtin_drem(double a, double b)
2482 /* conversion operations ******************************************************/
2485 s8 builtin_i2l(s4 i)
2497 s4 builtin_l2i(s8 l)
2508 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2509 float builtin_i2f(s4 a)
2511 float f = (float) a;
2514 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2517 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2518 double builtin_i2d(s4 a)
2520 double d = (double) a;
2523 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2526 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2527 float builtin_l2f(s8 a)
2530 float f = (float) a;
2536 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2539 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2540 double builtin_l2d(s8 a)
2543 double d = (double) a;
2549 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2552 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
2553 s4 builtin_f2i(float a)
2557 i = builtin_d2i((double) a);
2568 if (a < (-2147483648))
2569 return (-2147483648);
2572 f = copysignf((float) 1.0, a);
2575 return (-2147483648); */
2577 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
2580 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2581 s8 builtin_f2l(float a)
2585 l = builtin_d2l((double) a);
2592 if (a > 9223372036854775807L)
2593 return 9223372036854775807L;
2594 if (a < (-9223372036854775808L))
2595 return (-9223372036854775808L);
2600 f = copysignf((float) 1.0, a);
2602 return 9223372036854775807L;
2603 return (-9223372036854775808L); */
2605 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2608 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
2609 s4 builtin_d2i(double a)
2614 if (a >= 2147483647)
2616 if (a <= (-2147483647-1))
2617 return (-2147483647-1);
2622 d = copysign(1.0, a);
2625 return (-2147483647-1);
2627 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
2630 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2631 s8 builtin_d2l(double a)
2636 if (a >= 9223372036854775807LL)
2637 return 9223372036854775807LL;
2638 if (a <= (-9223372036854775807LL-1))
2639 return (-9223372036854775807LL-1);
2644 d = copysign(1.0, a);
2646 return 9223372036854775807LL;
2647 return (-9223372036854775807LL-1);
2649 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2652 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2653 double builtin_f2d(float a)
2655 if (finitef(a)) return (double) a;
2658 return longBitsToDouble(DBL_NAN);
2660 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2664 float builtin_d2f(double a)
2670 return intBitsToFloat(FLT_NAN);
2672 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2675 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2678 /* builtin_clone_array *********************************************************
2680 Wrapper function for cloning arrays.
2682 *******************************************************************************/
2684 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2686 java_arrayheader *ah;
2687 java_lang_Cloneable *c;
2689 c = (java_lang_Cloneable *) o;
2691 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2697 /* builtin_asm_get_exceptionptrptr *********************************************
2699 this is a wrapper for calls from asmpart
2701 *******************************************************************************/
2703 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2704 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2706 return builtin_get_exceptionptrptr();
2712 * These are local overrides for various environment variables in Emacs.
2713 * Please do not remove this and leave it at the end of the file, where
2714 * Emacs will automagically detect them.
2715 * ---------------------------------------------------------------------
2718 * indent-tabs-mode: t
2722 * vim:noexpandtab:sw=4:ts=4: