1 /* src/vm/builtin.c - functions for unsupported operations
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
33 Contains C functions for JavaVM Instructions that cannot be
34 translated to machine language directly. Consequently, the
35 generated machine code for these instructions contains function
36 calls instead of machine instructions, using the C calling
39 $Id: builtin.c 4208 2006-01-15 01:56:42Z twisti $
56 #include "fdlibm/fdlibm.h"
59 #include "mm/memory.h"
60 #include "native/native.h"
61 #include "native/include/java_lang_Cloneable.h"
62 #include "native/include/java_lang_Object.h" /* required by VMObject */
63 #include "native/include/java_lang_VMObject.h"
65 #if defined(USE_THREADS)
66 # if defined(NATIVE_THREADS)
67 # include "threads/native/threads.h"
69 # include "threads/green/threads.h"
70 # include "threads/green/locks.h"
74 #include "toolbox/logging.h"
75 #include "toolbox/util.h"
76 #include "vm/builtin.h"
78 #include "vm/exceptions.h"
79 #include "vm/global.h"
80 #include "vm/initialize.h"
81 #include "vm/loader.h"
82 #include "vm/options.h"
83 #include "vm/stringlocal.h"
84 #include "vm/jit/asmpart.h"
85 #include "vm/jit/patcher.h"
88 /* include builtin tables *****************************************************/
90 #include "vm/builtintable.inc"
93 /* builtintable_init ***********************************************************
95 Parse the descriptors of builtin functions and create the parsed
98 *******************************************************************************/
100 static bool builtintable_init(void)
102 descriptor_pool *descpool;
106 s4 entries_automatic;
109 /* mark start of dump memory area */
111 dumpsize = dump_size();
113 /* create a new descriptor pool */
115 descpool = descriptor_pool_new(class_java_lang_Object);
117 /* add some entries we need */
119 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
122 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
125 /* calculate table entries statically */
128 sizeof(builtintable_internal) / sizeof(builtintable_entry);
131 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
132 - 1; /* last filler entry (comment see builtintable.inc) */
134 /* first add all descriptors to the pool */
136 for (i = 0; i < entries_internal; i++) {
137 /* create a utf8 string from descriptor */
139 descriptor = utf_new_char(builtintable_internal[i].descriptor);
141 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
142 /* release dump area */
144 dump_release(dumpsize);
150 for (i = 0; i < entries_automatic; i++) {
151 /* create a utf8 string from descriptor */
153 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
155 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
156 /* release dump area */
158 dump_release(dumpsize);
164 /* create the class reference table */
166 (void) descriptor_pool_create_classrefs(descpool, NULL);
168 /* allocate space for the parsed descriptors */
170 descriptor_pool_alloc_parsed_descriptors(descpool);
172 /* now parse all descriptors */
174 for (i = 0; i < entries_internal; i++) {
175 /* create a utf8 string from descriptor */
177 descriptor = utf_new_char(builtintable_internal[i].descriptor);
179 /* parse the descriptor, builtin is always static (no `this' pointer) */
181 builtintable_internal[i].md =
182 descriptor_pool_parse_method_descriptor(descpool, descriptor,
186 for (i = 0; i < entries_automatic; i++) {
187 /* create a utf8 string from descriptor */
189 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
191 /* parse the descriptor, builtin is always static (no `this' pointer) */
193 builtintable_automatic[i].md =
194 descriptor_pool_parse_method_descriptor(descpool, descriptor,
198 /* release dump area */
200 dump_release(dumpsize);
206 /* builtintable_comparator *****************************************************
208 qsort comparator for the automatic builtin table.
210 *******************************************************************************/
212 static int builtintable_comparator(const void *a, const void *b)
214 builtintable_entry *bte1;
215 builtintable_entry *bte2;
217 bte1 = (builtintable_entry *) a;
218 bte2 = (builtintable_entry *) b;
220 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
224 /* builtintable_sort_automatic *************************************************
226 Sorts the automatic builtin table.
228 *******************************************************************************/
230 static void builtintable_sort_automatic(void)
234 /* calculate table size statically (`- 1' comment see builtintable.inc) */
236 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
238 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
239 builtintable_comparator);
243 /* builtin_init ****************************************************************
247 *******************************************************************************/
249 bool builtin_init(void)
251 /* initialize the builtin tables */
253 if (!builtintable_init())
256 /* sort builtin tables */
258 builtintable_sort_automatic();
264 /* builtintable_get_internal ***************************************************
266 Finds an entry in the builtintable for internal functions and
267 returns the a pointer to the structure.
269 *******************************************************************************/
271 builtintable_entry *builtintable_get_internal(functionptr fp)
275 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
276 if (builtintable_internal[i].fp == fp)
277 return &builtintable_internal[i];
284 /* builtintable_get_automatic **************************************************
286 Finds an entry in the builtintable for functions which are replaced
287 automatically and returns the a pointer to the structure.
289 *******************************************************************************/
291 builtintable_entry *builtintable_get_automatic(s4 opcode)
293 builtintable_entry *first;
294 builtintable_entry *last;
295 builtintable_entry *middle;
299 /* calculate table size statically (`- 1' comment see builtintable.inc) */
301 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
303 first = builtintable_automatic;
304 last = builtintable_automatic + entries;
306 while (entries > 0) {
308 middle = first + half;
310 if (middle->opcode < opcode) {
317 return (first != last ? first : NULL);
321 /*****************************************************************************
323 *****************************************************************************/
327 /*************** internal function: builtin_isanysubclass *********************
329 Checks a subclass relation between two classes. Implemented interfaces
330 are interpreted as super classes.
331 Return value: 1 ... sub is subclass of super
334 *****************************************************************************/
335 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
338 castinfo classvalues;
343 if (super->flags & ACC_INTERFACE) {
344 res = (sub->vftbl->interfacetablelength > super->index) &&
345 (sub->vftbl->interfacetable[-super->index] != NULL);
348 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
350 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
351 (u4) classvalues.super_diffval;
358 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
362 castinfo classvalues;
367 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
369 if ((base = classvalues.super_baseval) <= 0) {
370 /* super is an interface */
371 res = (sub->interfacetablelength > -base) &&
372 (sub->interfacetable[base] != NULL);
374 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
375 <= (u4) classvalues.super_diffval;
382 /****************** function: builtin_instanceof *****************************
384 Checks if an object is an instance of some given class (or subclass of
385 that class). If class is an interface, checks if the interface is
387 Return value: 1 ... obj is an instance of class or implements the interface
388 0 ... otherwise or if obj == NULL
390 *****************************************************************************/
392 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
397 return builtin_isanysubclass(obj->vftbl->class, class);
402 /**************** function: builtin_checkcast *******************************
404 The same as builtin_instanceof except that 1 is returned when
407 ****************************************************************************/
409 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
414 if (builtin_isanysubclass(obj->vftbl->class, class))
421 /* builtin_descriptorscompatible ***********************************************
423 Checks if two array type descriptors are assignment compatible
425 Return value: 1 ... target = desc is possible
428 *******************************************************************************/
430 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
431 arraydescriptor *target)
436 if (desc->arraytype != target->arraytype)
439 if (desc->arraytype != ARRAYTYPE_OBJECT)
442 /* {both arrays are arrays of references} */
444 if (desc->dimension == target->dimension) {
445 /* an array which contains elements of interface types is
446 allowed to be casted to Object (JOWENN)*/
448 if ((desc->elementvftbl->baseval < 0) &&
449 (target->elementvftbl->baseval == 1))
452 return builtin_isanysubclass_vftbl(desc->elementvftbl,
453 target->elementvftbl);
456 if (desc->dimension < target->dimension)
459 /* {desc has higher dimension than target} */
461 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
462 target->elementvftbl);
466 /* builtin_arraycheckcast ******************************************************
468 Checks if an object is really a subtype of the requested array
469 type. The object has to be an array to begin with. For simple
470 arrays (int, short, double, etc.) the types have to match exactly.
471 For arrays of objects, the type of elements in the array has to be
472 a subtype (or the same type) of the requested element type. For
473 arrays of arrays (which in turn can again be arrays of arrays), the
474 types at the lowest level have to satisfy the corresponding sub
477 *******************************************************************************/
479 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
481 arraydescriptor *desc;
486 if ((desc = o->vftbl->arraydesc) == NULL)
489 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
493 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
498 return builtin_arraycheckcast(o, targetclass);
502 /************************** exception functions *******************************
504 ******************************************************************************/
507 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
509 java_lang_Throwable *t;
515 t = (java_lang_Throwable *) xptr;
517 /* calculate message length */
519 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
523 utf_strlen(xptr->vftbl->class->name) +
525 javastring_strlen(t->detailMessage);
528 logtextlen += strlen("(nil)");
530 /* allocate memory */
532 dumpsize = dump_size();
534 logtext = DMNEW(char, logtextlen);
536 strcpy(logtext, "Builtin exception thrown: ");
539 utf_sprint_classname(logtext + strlen(logtext),
540 xptr->vftbl->class->name);
542 if (t->detailMessage) {
545 buf = javastring_tochar((java_objectheader *) t->detailMessage);
546 strcat(logtext, ": ");
547 strcat(logtext, buf);
548 MFREE(buf, char, strlen(buf));
552 strcat(logtext, "(nil)");
559 dump_release(dumpsize);
562 *exceptionptr = xptr;
566 #endif /* !defined(NDEBUG) */
569 /* builtin_canstore ************************************************************
571 Checks, if an object can be stored in an array.
573 Return value: 1 ... possible
576 *******************************************************************************/
578 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
580 arraydescriptor *desc;
581 arraydescriptor *valuedesc;
582 vftbl_t *componentvftbl;
585 castinfo classvalues;
590 /* The following is guaranteed (by verifier checks):
592 * *) oa->...vftbl->arraydesc != NULL
593 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
594 * *) o->vftbl is not an interface vftbl
597 desc = oa->header.objheader.vftbl->arraydesc;
598 componentvftbl = desc->componentvftbl;
599 valuevftbl = o->vftbl;
601 if ((desc->dimension - 1) == 0) {
604 /* {oa is a one-dimensional array} */
605 /* {oa is an array of references} */
607 if (valuevftbl == componentvftbl)
610 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
612 if ((base = classvalues.super_baseval) <= 0)
613 /* an array of interface references */
614 return (valuevftbl->interfacetablelength > -base &&
615 valuevftbl->interfacetable[base] != NULL);
617 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
618 <= (unsigned) classvalues.super_diffval);
623 /* {oa has dimension > 1} */
624 /* {componentvftbl->arraydesc != NULL} */
626 /* check if o is an array */
628 if ((valuedesc = valuevftbl->arraydesc) == NULL)
631 /* {o is an array} */
633 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
637 /* This is an optimized version where a is guaranteed to be one-dimensional */
638 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
640 arraydescriptor *desc;
641 vftbl_t *elementvftbl;
645 castinfo classvalues;
649 /* The following is guaranteed (by verifier checks):
651 * *) a->...vftbl->arraydesc != NULL
652 * *) a->...vftbl->arraydesc->elementvftbl != NULL
653 * *) a->...vftbl->arraydesc->dimension == 1
654 * *) o->vftbl is not an interface vftbl
657 desc = a->header.objheader.vftbl->arraydesc;
658 elementvftbl = desc->elementvftbl;
659 valuevftbl = o->vftbl;
661 /* {a is a one-dimensional array} */
663 if (valuevftbl == elementvftbl)
666 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
668 if ((base = classvalues.super_baseval) <= 0)
669 /* an array of interface references */
670 return (valuevftbl->interfacetablelength > -base &&
671 valuevftbl->interfacetable[base] != NULL);
673 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
674 <= (unsigned) classvalues.super_diffval;
680 /* This is an optimized version where a is guaranteed to be a
681 * one-dimensional array of a class type */
682 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
684 vftbl_t *elementvftbl;
687 castinfo classvalues;
691 /* The following is guaranteed (by verifier checks):
693 * *) a->...vftbl->arraydesc != NULL
694 * *) a->...vftbl->arraydesc->elementvftbl != NULL
695 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
696 * *) a->...vftbl->arraydesc->dimension == 1
697 * *) o->vftbl is not an interface vftbl
700 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
701 valuevftbl = o->vftbl;
703 /* {a is a one-dimensional array} */
705 if (valuevftbl == elementvftbl)
708 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
710 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
711 <= (unsigned) classvalues.super_diffval;
717 /* builtin_new *****************************************************************
719 Creates a new instance of class c on the heap.
721 Return value: pointer to the object or NULL if no memory is
724 *******************************************************************************/
726 java_objectheader *builtin_new(classinfo *c)
728 java_objectheader *o;
730 /* is the class loaded */
732 assert(c->state & CLASS_LOADED);
734 /* check if we can instantiate this class */
736 if (c->flags & ACC_ABSTRACT) {
738 new_exception_utfmessage(string_java_lang_InstantiationError,
743 /* is the class linked */
745 if (!(c->state & CLASS_LINKED))
749 if (!(c->state & CLASS_INITIALIZED)) {
751 log_message_class("Initialize class (from builtin_new): ", c);
753 if (!initialize_class(c))
757 o = heap_allocate(c->instancesize, true, c->finalizer);
764 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
772 /* builtin_newarray ************************************************************
774 Creates an array with the given vftbl on the heap. This function
775 takes as class argument an array class.
777 Return value: pointer to the array or NULL if no memory is available
779 *******************************************************************************/
781 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
783 arraydescriptor *desc;
789 desc = arrayclass->vftbl->arraydesc;
790 dataoffset = desc->dataoffset;
791 componentsize = desc->componentsize;
794 exceptions_throw_negativearraysizeexception();
798 actualsize = dataoffset + size * componentsize;
800 if (((u4) actualsize) < ((u4) size)) { /* overflow */
801 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
805 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
810 a->objheader.vftbl = arrayclass->vftbl;
812 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
813 initObjectLock(&a->objheader);
822 /* builtin_anewarray ***********************************************************
824 Creates an array of references to the given class type on the heap.
826 Return value: pointer to the array or NULL if no memory is
829 *******************************************************************************/
831 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
833 classinfo *arrayclass;
835 /* is class loaded */
837 assert(componentclass->state & CLASS_LOADED);
839 /* is class linked */
841 if (!(componentclass->state & CLASS_LINKED))
842 if (!link_class(componentclass))
845 arrayclass = class_array_of(componentclass, true);
850 return (java_objectarray *) builtin_newarray(size, arrayclass);
854 /* builtin_newarray_boolean ****************************************************
856 Creates an array of bytes on the heap. The array is designated as
857 an array of booleans (important for casts)
859 Return value: pointer to the array or NULL if no memory is
862 *******************************************************************************/
864 java_booleanarray *builtin_newarray_boolean(s4 size)
866 return (java_booleanarray *)
867 builtin_newarray(size,
868 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
872 /* builtin_newarray_byte *******************************************************
874 Creates an array of 8 bit Integers on the heap.
876 Return value: pointer to the array or NULL if no memory is
879 *******************************************************************************/
881 java_bytearray *builtin_newarray_byte(s4 size)
883 return (java_bytearray *)
884 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
888 /* builtin_newarray_char *******************************************************
890 Creates an array of characters on the heap.
892 Return value: pointer to the array or NULL if no memory is
895 *******************************************************************************/
897 java_chararray *builtin_newarray_char(s4 size)
899 return (java_chararray *)
900 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
904 /* builtin_newarray_short ******************************************************
906 Creates an array of 16 bit Integers on the heap.
908 Return value: pointer to the array or NULL if no memory is
911 *******************************************************************************/
913 java_shortarray *builtin_newarray_short(s4 size)
915 return (java_shortarray *)
916 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
920 /* builtin_newarray_int ********************************************************
922 Creates an array of 32 bit Integers on the heap.
924 Return value: pointer to the array or NULL if no memory is
927 *******************************************************************************/
929 java_intarray *builtin_newarray_int(s4 size)
931 return (java_intarray *)
932 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
936 /* builtin_newarray_long *******************************************************
938 Creates an array of 64 bit Integers on the heap.
940 Return value: pointer to the array or NULL if no memory is
943 *******************************************************************************/
945 java_longarray *builtin_newarray_long(s4 size)
947 return (java_longarray *)
948 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
952 /* builtin_newarray_float ******************************************************
954 Creates an array of 32 bit IEEE floats on the heap.
956 Return value: pointer to the array or NULL if no memory is
959 *******************************************************************************/
961 java_floatarray *builtin_newarray_float(s4 size)
963 return (java_floatarray *)
964 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
968 /* builtin_newarray_double *****************************************************
970 Creates an array of 64 bit IEEE floats on the heap.
972 Return value: pointer to the array or NULL if no memory is
975 *******************************************************************************/
977 java_doublearray *builtin_newarray_double(s4 size)
979 return (java_doublearray *)
980 builtin_newarray(size,
981 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
985 /* builtin_multianewarray_intern ***********************************************
987 Creates a multi-dimensional array on the heap. The dimensions are
988 passed in an array of longs.
991 n............number of dimensions to create
992 arrayvftbl...vftbl of the array class
993 dims.........array containing the size of each dimension to create
995 Return value: pointer to the array or NULL if no memory is
998 ******************************************************************************/
1000 static java_arrayheader *builtin_multianewarray_intern(int n,
1001 classinfo *arrayclass,
1005 java_arrayheader *a;
1006 classinfo *componentclass;
1009 /* create this dimension */
1011 size = (s4) dims[0];
1012 a = builtin_newarray(size, arrayclass);
1017 /* if this is the last dimension return */
1022 /* get the class of the components to create */
1024 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1026 /* The verifier guarantees that the dimension count is in the range. */
1028 /* create the component arrays */
1030 for (i = 0; i < size; i++) {
1031 java_arrayheader *ea =
1032 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1033 /* we save an s4 to a s8 slot, 8-byte aligned */
1035 builtin_multianewarray_intern(n, componentclass, dims + 2);
1037 builtin_multianewarray_intern(n, componentclass, dims + 1);
1043 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1050 /* builtin_multianewarray ******************************************************
1052 Wrapper for builtin_multianewarray_intern which checks all
1053 dimensions before we start allocating.
1055 ******************************************************************************/
1057 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1063 /* check all dimensions before doing anything */
1065 for (i = 0; i < n; i++) {
1066 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1067 /* we save an s4 to a s8 slot, 8-byte aligned */
1068 size = (s4) dims[i * 2];
1070 size = (s4) dims[i];
1074 exceptions_throw_negativearraysizeexception();
1079 /* now call the real function */
1081 return builtin_multianewarray_intern(n, arrayclass, dims);
1085 /*****************************************************************************
1088 Various functions for printing a message at method entry or exit (for
1091 *****************************************************************************/
1093 #if !defined(NDEBUG)
1094 static s4 methodindent = 0;
1095 static u4 callcount = 0;
1097 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1106 if (runverbose && indent)
1109 /* calculate message length */
1113 strlen("Exception ") +
1114 utf_strlen(xptr->vftbl->class->name);
1117 logtextlen = strlen("Some Throwable");
1120 logtextlen += strlen(" thrown in ");
1124 utf_strlen(m->class->name) +
1126 utf_strlen(m->name) +
1127 utf_strlen(m->descriptor) +
1128 strlen("(NOSYNC,NATIVE");
1130 #if SIZEOF_VOID_P == 8
1132 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1134 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1137 if (m->class->sourcefile == NULL)
1138 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1140 logtextlen += utf_strlen(m->class->sourcefile);
1142 logtextlen += strlen(":65536)");
1145 logtextlen += strlen("call_java_method");
1147 logtextlen += strlen("0");
1149 /* allocate memory */
1151 dumpsize = dump_size();
1153 logtext = DMNEW(char, logtextlen);
1156 strcpy(logtext, "Exception ");
1157 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1160 strcpy(logtext, "Some Throwable");
1163 strcat(logtext, " thrown in ");
1166 utf_strcat_classname(logtext, m->class->name);
1167 strcat(logtext, ".");
1168 utf_strcat(logtext, m->name);
1169 utf_strcat(logtext, m->descriptor);
1171 if (m->flags & ACC_SYNCHRONIZED)
1172 strcat(logtext, "(SYNC");
1174 strcat(logtext, "(NOSYNC");
1176 if (m->flags & ACC_NATIVE) {
1177 strcat(logtext, ",NATIVE");
1179 #if SIZEOF_VOID_P == 8
1180 sprintf(logtext + strlen(logtext),
1181 ")(0x%016lx) at position 0x%016lx",
1182 (ptrint) m->entrypoint, (ptrint) pos);
1184 sprintf(logtext + strlen(logtext),
1185 ")(0x%08x) at position 0x%08x",
1186 (ptrint) m->entrypoint, (ptrint) pos);
1190 #if SIZEOF_VOID_P == 8
1191 sprintf(logtext + strlen(logtext),
1192 ")(0x%016lx) at position 0x%016lx (",
1193 (ptrint) m->entrypoint, (ptrint) pos);
1195 sprintf(logtext + strlen(logtext),
1196 ")(0x%08x) at position 0x%08x (",
1197 (ptrint) m->entrypoint, (ptrint) pos);
1200 if (m->class->sourcefile == NULL)
1201 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1203 utf_strcat(logtext, m->class->sourcefile);
1205 sprintf(logtext + strlen(logtext), ":%d)", 0);
1209 strcat(logtext, "call_java_method");
1213 /* release memory */
1215 dump_release(dumpsize);
1217 /* print stacktrace for exception */
1219 if (opt_verboseexception) {
1220 exceptions_print_exception(xptr);
1221 stacktrace_print_trace(xptr);
1226 #endif /* !defined(NDEBUG) */
1229 /* builtin_trace_args **********************************************************
1233 *******************************************************************************/
1235 #if !defined(NDEBUG)
1237 #ifdef TRACE_ARGS_NUM
1238 void builtin_trace_args(s8 a0, s8 a1,
1239 #if TRACE_ARGS_NUM >= 4
1241 #endif /* TRACE_ARGS_NUM >= 4 */
1242 #if TRACE_ARGS_NUM >= 6
1244 #endif /* TRACE_ARGS_NUM >= 6 */
1245 #if TRACE_ARGS_NUM == 8
1247 #endif /* TRACE_ARGS_NUM == 8 */
1259 /* calculate message length */
1262 strlen("4294967295 ") +
1263 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1265 strlen("called: ") +
1266 utf_strlen(m->class->name) +
1268 utf_strlen(m->name) +
1269 utf_strlen(m->descriptor) +
1270 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1272 /* add maximal argument length */
1274 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1276 /* allocate memory */
1278 dumpsize = dump_size();
1280 logtext = DMNEW(char, logtextlen);
1284 sprintf(logtext, "%10d ", callcount);
1285 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1287 pos = strlen(logtext);
1289 for (i = 0; i < methodindent; i++)
1290 logtext[pos++] = '\t';
1292 strcpy(logtext + pos, "called: ");
1294 utf_strcat_classname(logtext, m->class->name);
1295 strcat(logtext, ".");
1296 utf_strcat(logtext, m->name);
1297 utf_strcat(logtext, m->descriptor);
1299 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1300 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1301 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1302 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1303 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1304 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1305 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1306 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1307 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1308 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1309 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1311 strcat(logtext, "(");
1313 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1314 /* Only Arguments in integer Registers are passed correctly here */
1315 /* long longs spilled on Stack have an wrong offset of +4 */
1316 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1317 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1318 switch (md->paramcount) {
1322 #if SIZEOF_VOID_P == 4
1324 sprintf(logtext + strlen(logtext),
1330 sprintf(logtext + strlen(logtext),
1335 #if TRACE_ARGS_NUM >= 4
1337 sprintf(logtext + strlen(logtext),
1338 "0x%llx, 0x%llx, 0x%llx",
1343 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1345 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1348 #endif /* TRACE_ARGS_NUM >= 4 */
1350 #if TRACE_ARGS_NUM >= 6
1352 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1354 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1359 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1361 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1364 #endif /* TRACE_ARGS_NUM >= 6 */
1366 #if TRACE_ARGS_NUM == 8
1368 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1370 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1372 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1376 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1378 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1380 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1382 #endif /* TRACE_ARGS_NUM == 8 */
1385 #if TRACE_ARGS_NUM == 2
1386 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1388 #elif TRACE_ARGS_NUM == 4
1389 sprintf(logtext + strlen(logtext),
1390 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1391 a0, a1, a2, a3, md->paramcount - 4);
1393 #elif TRACE_ARGS_NUM == 6
1394 sprintf(logtext + strlen(logtext),
1395 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1396 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1398 #elif TRACE_ARGS_NUM == 8
1399 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1401 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1403 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1404 , a6, a7, md->paramcount - 8);
1408 #else /* SIZEOF_VOID_P == 4 */
1411 sprintf(logtext + strlen(logtext),
1417 sprintf(logtext + strlen(logtext),
1423 sprintf(logtext + strlen(logtext),
1424 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1428 sprintf(logtext + strlen(logtext),
1429 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1433 #if TRACE_ARGS_NUM >= 6
1435 sprintf(logtext + strlen(logtext),
1436 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1437 a0, a1, a2, a3, a4);
1441 sprintf(logtext + strlen(logtext),
1442 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1443 a0, a1, a2, a3, a4, a5);
1445 #endif /* TRACE_ARGS_NUM >= 6 */
1447 #if TRACE_ARGS_NUM == 8
1449 sprintf(logtext + strlen(logtext),
1450 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1451 a0, a1, a2, a3, a4, a5, a6);
1455 sprintf(logtext + strlen(logtext),
1456 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1457 a0, a1, a2, a3, a4, a5, a6, a7);
1459 #endif /* TRACE_ARGS_NUM == 8 */
1462 #if TRACE_ARGS_NUM == 4
1463 sprintf(logtext + strlen(logtext),
1464 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1465 a0, a1, a2, a3, md->paramcount - 4);
1467 #elif TRACE_ARGS_NUM == 6
1468 sprintf(logtext + strlen(logtext),
1469 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1470 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1472 #elif TRACE_ARGS_NUM == 8
1473 sprintf(logtext + strlen(logtext),
1474 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1475 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1478 #endif /* SIZEOF_VOID_P == 4 */
1481 strcat(logtext, ")");
1485 /* release memory */
1487 dump_release(dumpsize);
1492 #endif /* !defined(NDEBUG) */
1495 /* builtin_displaymethodstop ***************************************************
1499 *******************************************************************************/
1501 #if !defined(NDEBUG)
1502 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1510 java_objectheader *o;
1511 java_lang_String *s;
1519 /* calculate message length */
1522 strlen("4294967295 ") +
1523 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1525 strlen("finished: ") +
1526 utf_strlen(m->class->name) +
1528 utf_strlen(m->name) +
1529 utf_strlen(m->descriptor) +
1530 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1532 /* add maximal argument length */
1534 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1536 /* allocate memory */
1538 dumpsize = dump_size();
1540 logtext = DMNEW(char, logtextlen);
1542 /* outdent the log message */
1547 log_text("WARNING: unmatched methodindent--");
1549 /* generate the message */
1551 sprintf(logtext, " ");
1552 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1554 pos = strlen(logtext);
1556 for (i = 0; i < methodindent; i++)
1557 logtext[pos++] = '\t';
1559 strcpy(logtext + pos, "finished: ");
1560 utf_strcat_classname(logtext, m->class->name);
1561 strcat(logtext, ".");
1562 utf_strcat(logtext, m->name);
1563 utf_strcat(logtext, m->descriptor);
1565 switch (md->returntype.type) {
1567 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1571 #if SIZEOF_VOID_P == 4
1572 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1574 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1579 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1581 /* check return argument for java.lang.Class or java.lang.String */
1583 o = (java_objectheader *) (ptrint) l;
1586 if (o->vftbl->class == class_java_lang_String) {
1587 /* get java.lang.String object and the length of the
1590 s= (java_lang_String *) (ptrint) l;
1592 len = strlen(", String = \"") + javastring_strlen(s) +
1595 /* realloc memory for string length */
1597 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1599 /* convert to utf8 string and strcat it to the logtext */
1601 u = javastring_toutf(s, false);
1603 strcat(logtext, ", String = \"");
1604 utf_strcat(logtext, u);
1605 strcat(logtext, "\"");
1608 if (o->vftbl->class == class_java_lang_Class) {
1609 /* if the object returned is a java.lang.Class
1610 cast it to classinfo structure and get the name
1613 c = (classinfo *) (ptrint) l;
1618 /* if the object returned is not a java.lang.String or
1619 a java.lang.Class just print the name of the class */
1621 u = o->vftbl->class->name;
1624 len = strlen(", Class = \"") + utf_strlen(u) + strlen("\"");
1626 /* realloc memory for string length */
1628 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1630 /* strcat to the logtext */
1632 strcat(logtext, ", Class = \"");
1633 utf_strcat(logtext, u);
1634 strcat(logtext, "\"");
1641 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1646 #if SIZEOF_VOID_P == 4
1647 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1649 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1656 /* release memory */
1658 dump_release(dumpsize);
1660 #endif /* !defined(NDEBUG) */
1663 /****************************************************************************
1664 SYNCHRONIZATION FUNCTIONS
1665 *****************************************************************************/
1667 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1669 * Lock the mutex of an object.
1671 void internal_lock_mutex_for_object(java_objectheader *object)
1673 mutexHashEntry *entry;
1676 assert(object != 0);
1678 hashValue = MUTEX_HASH_VALUE(object);
1679 entry = &mutexHashTable[hashValue];
1681 if (entry->object != 0) {
1682 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1684 entry->mutex.holder = 0;
1685 entry->mutex.count = 0;
1686 entry->mutex.muxWaiters = 0;
1689 while (entry->next != 0 && entry->object != object)
1690 entry = entry->next;
1692 if (entry->object != object) {
1693 entry->next = firstFreeOverflowEntry;
1694 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1696 entry = entry->next;
1699 assert(entry->conditionCount == 0);
1704 entry->mutex.holder = 0;
1705 entry->mutex.count = 0;
1706 entry->mutex.muxWaiters = 0;
1709 if (entry->object == 0)
1710 entry->object = object;
1712 internal_lock_mutex(&entry->mutex);
1717 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1719 * Unlocks the mutex of an object.
1721 void internal_unlock_mutex_for_object (java_objectheader *object)
1724 mutexHashEntry *entry;
1726 hashValue = MUTEX_HASH_VALUE(object);
1727 entry = &mutexHashTable[hashValue];
1729 if (entry->object == object) {
1730 internal_unlock_mutex(&entry->mutex);
1733 while (entry->next != 0 && entry->next->object != object)
1734 entry = entry->next;
1736 assert(entry->next != 0);
1738 internal_unlock_mutex(&entry->next->mutex);
1740 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1741 mutexHashEntry *unlinked = entry->next;
1743 entry->next = unlinked->next;
1744 unlinked->next = firstFreeOverflowEntry;
1745 firstFreeOverflowEntry = unlinked;
1752 #if defined(USE_THREADS)
1753 void builtin_monitorenter(java_objectheader *o)
1755 #if !defined(NATIVE_THREADS)
1760 hashValue = MUTEX_HASH_VALUE(o);
1761 if (mutexHashTable[hashValue].object == o
1762 && mutexHashTable[hashValue].mutex.holder == currentThread)
1763 ++mutexHashTable[hashValue].mutex.count;
1765 internal_lock_mutex_for_object(o);
1769 monitorEnter((threadobject *) THREADOBJECT, o);
1775 #if defined(USE_THREADS)
1777 * Locks the class object - needed for static synchronized methods.
1779 void builtin_staticmonitorenter(classinfo *c)
1781 builtin_monitorenter(&c->object.header);
1786 #if defined(USE_THREADS)
1787 void builtin_monitorexit(java_objectheader *o)
1789 #if !defined(NATIVE_THREADS)
1794 hashValue = MUTEX_HASH_VALUE(o);
1795 if (mutexHashTable[hashValue].object == o) {
1796 if (mutexHashTable[hashValue].mutex.count == 1
1797 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1798 internal_unlock_mutex_for_object(o);
1800 --mutexHashTable[hashValue].mutex.count;
1803 internal_unlock_mutex_for_object(o);
1807 monitorExit((threadobject *) THREADOBJECT, o);
1813 /*****************************************************************************
1814 MISCELLANEOUS HELPER FUNCTIONS
1815 *****************************************************************************/
1819 /*********** Functions for integer divisions *****************************
1821 On some systems (eg. DEC ALPHA), integer division is not supported by the
1822 CPU. These helper functions implement the missing functionality.
1824 ******************************************************************************/
1826 #if !SUPPORT_DIVISION
1827 s4 builtin_idiv(s4 a, s4 b)
1836 s4 builtin_irem(s4 a, s4 b)
1844 #endif /* !SUPPORT_DIVISION */
1847 /* functions for long arithmetics **********************************************
1849 On systems where 64 bit Integers are not supported by the CPU,
1850 these functions are needed.
1852 ******************************************************************************/
1854 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1855 s8 builtin_ladd(s8 a, s8 b)
1868 s8 builtin_lsub(s8 a, s8 b)
1881 s8 builtin_lneg(s8 a)
1893 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1896 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1897 s8 builtin_lmul(s8 a, s8 b)
1909 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1912 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1913 s8 builtin_ldiv(s8 a, s8 b)
1926 s8 builtin_lrem(s8 a, s8 b)
1938 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1941 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1942 s8 builtin_lshl(s8 a, s4 b)
1955 s8 builtin_lshr(s8 a, s4 b)
1968 s8 builtin_lushr(s8 a, s4 b)
1973 c = ((u8) a) >> (b & 63);
1980 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1983 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1984 s8 builtin_land(s8 a, s8 b)
1997 s8 builtin_lor(s8 a, s8 b)
2010 s8 builtin_lxor(s8 a, s8 b)
2022 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2025 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2026 s4 builtin_lcmp(s8 a, s8 b)
2040 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2043 /* functions for unsupported floating instructions ****************************/
2045 /* used to convert FLT_xxx defines into float values */
2047 static inline float intBitsToFloat(s4 i)
2056 /* used to convert DBL_xxx defines into double values */
2058 static inline float longBitsToDouble(s8 l)
2068 float builtin_fadd(float a, float b)
2070 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2071 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2082 if (copysignf(1.0, a) == copysignf(1.0, b))
2085 return intBitsToFloat(FLT_NAN);
2091 float builtin_fsub(float a, float b)
2093 return builtin_fadd(a, builtin_fneg(b));
2097 float builtin_fmul(float a, float b)
2099 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2100 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2102 if (finitef(b)) return a * b;
2104 if (a == 0) return intBitsToFloat(FLT_NAN);
2105 else return copysignf(b, copysignf(1.0, b)*a);
2110 if (b == 0) return intBitsToFloat(FLT_NAN);
2111 else return copysignf(a, copysignf(1.0, a)*b);
2114 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2120 /* builtin_ddiv ****************************************************************
2122 Implementation as described in VM Spec.
2124 *******************************************************************************/
2126 float builtin_fdiv(float a, float b)
2130 /* If neither value1' nor value2' is NaN, the sign of the result */
2131 /* is positive if both values have the same sign, negative if the */
2132 /* values have different signs. */
2138 /* If either value1' or value2' is NaN, the result is NaN. */
2140 return intBitsToFloat(FLT_NAN);
2143 /* Division of a finite value by an infinity results in a */
2144 /* signed zero, with the sign-producing rule just given. */
2146 /* is sign equal? */
2148 if (copysignf(1.0, a) == copysignf(1.0, b))
2157 /* If either value1' or value2' is NaN, the result is NaN. */
2159 return intBitsToFloat(FLT_NAN);
2161 } else if (finitef(b)) {
2162 /* Division of an infinity by a finite value results in a signed */
2163 /* infinity, with the sign-producing rule just given. */
2165 /* is sign equal? */
2167 if (copysignf(1.0, a) == copysignf(1.0, b))
2168 return intBitsToFloat(FLT_POSINF);
2170 return intBitsToFloat(FLT_NEGINF);
2173 /* Division of an infinity by an infinity results in NaN. */
2175 return intBitsToFloat(FLT_NAN);
2181 float builtin_fneg(float a)
2183 if (isnanf(a)) return a;
2185 if (finitef(a)) return -a;
2186 else return copysignf(a, -copysignf(1.0, a));
2189 #endif /* !SUPPORT_FLOAT */
2192 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2193 s4 builtin_fcmpl(float a, float b)
2195 if (isnanf(a)) return -1;
2196 if (isnanf(b)) return -1;
2197 if (!finitef(a) || !finitef(b)) {
2198 a = finitef(a) ? 0 : copysignf(1.0, a);
2199 b = finitef(b) ? 0 : copysignf(1.0, b);
2201 if (a > b) return 1;
2202 if (a == b) return 0;
2207 s4 builtin_fcmpg(float a, float b)
2209 if (isnanf(a)) return 1;
2210 if (isnanf(b)) return 1;
2211 if (!finitef(a) || !finitef(b)) {
2212 a = finitef(a) ? 0 : copysignf(1.0, a);
2213 b = finitef(b) ? 0 : copysignf(1.0, b);
2215 if (a > b) return 1;
2216 if (a == b) return 0;
2219 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2222 float builtin_frem(float a, float b)
2228 /* functions for unsupported double instructions ******************************/
2231 double builtin_dadd(double a, double b)
2233 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2234 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2236 if (finite(b)) return a + b;
2240 if (finite(b)) return a;
2242 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2243 else return longBitsToDouble(DBL_NAN);
2249 double builtin_dsub(double a, double b)
2251 return builtin_dadd(a, builtin_dneg(b));
2255 double builtin_dmul(double a, double b)
2257 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2258 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2260 if (finite(b)) return a * b;
2262 if (a == 0) return longBitsToDouble(DBL_NAN);
2263 else return copysign(b, copysign(1.0, b) * a);
2268 if (b == 0) return longBitsToDouble(DBL_NAN);
2269 else return copysign(a, copysign(1.0, a) * b);
2272 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2278 /* builtin_ddiv ****************************************************************
2280 Implementation as described in VM Spec.
2282 *******************************************************************************/
2284 double builtin_ddiv(double a, double b)
2288 /* If neither value1' nor value2' is NaN, the sign of the result */
2289 /* is positive if both values have the same sign, negative if the */
2290 /* values have different signs. */
2296 /* If either value1' or value2' is NaN, the result is NaN. */
2298 return longBitsToDouble(DBL_NAN);
2301 /* Division of a finite value by an infinity results in a */
2302 /* signed zero, with the sign-producing rule just given. */
2304 /* is sign equal? */
2306 if (copysign(1.0, a) == copysign(1.0, b))
2315 /* If either value1' or value2' is NaN, the result is NaN. */
2317 return longBitsToDouble(DBL_NAN);
2319 } else if (finite(b)) {
2320 /* Division of an infinity by a finite value results in a signed */
2321 /* infinity, with the sign-producing rule just given. */
2323 /* is sign equal? */
2325 if (copysign(1.0, a) == copysign(1.0, b))
2326 return longBitsToDouble(DBL_POSINF);
2328 return longBitsToDouble(DBL_NEGINF);
2331 /* Division of an infinity by an infinity results in NaN. */
2333 return longBitsToDouble(DBL_NAN);
2339 /* builtin_dneg ****************************************************************
2341 Implemented as described in VM Spec.
2343 *******************************************************************************/
2345 double builtin_dneg(double a)
2348 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2355 /* If the operand is a zero, the result is the zero of opposite */
2361 /* If the operand is an infinity, the result is the infinity of */
2362 /* opposite sign. */
2364 return copysign(a, -copysign(1.0, a));
2368 #endif /* !SUPPORT_DOUBLE */
2371 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2372 s4 builtin_dcmpl(double a, double b)
2374 if (isnan(a)) return -1;
2375 if (isnan(b)) return -1;
2376 if (!finite(a) || !finite(b)) {
2377 a = finite(a) ? 0 : copysign(1.0, a);
2378 b = finite(b) ? 0 : copysign(1.0, b);
2380 if (a > b) return 1;
2381 if (a == b) return 0;
2386 s4 builtin_dcmpg(double a, double b)
2388 if (isnan(a)) return 1;
2389 if (isnan(b)) return 1;
2390 if (!finite(a) || !finite(b)) {
2391 a = finite(a) ? 0 : copysign(1.0, a);
2392 b = finite(b) ? 0 : copysign(1.0, b);
2394 if (a > b) return 1;
2395 if (a == b) return 0;
2398 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2401 double builtin_drem(double a, double b)
2407 /* conversion operations ******************************************************/
2410 s8 builtin_i2l(s4 i)
2422 s4 builtin_l2i(s8 l)
2433 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2434 float builtin_i2f(s4 a)
2436 float f = (float) a;
2439 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2442 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2443 double builtin_i2d(s4 a)
2445 double d = (double) a;
2448 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2451 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2452 float builtin_l2f(s8 a)
2455 float f = (float) a;
2461 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2464 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2465 double builtin_l2d(s8 a)
2468 double d = (double) a;
2474 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2477 #if !(SUPPORT_FLOAT && SUPPORT_F2I)
2478 s4 builtin_f2i(float a)
2482 i = builtin_d2i((double) a);
2493 if (a < (-2147483648))
2494 return (-2147483648);
2497 f = copysignf((float) 1.0, a);
2500 return (-2147483648); */
2502 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) */
2505 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2506 s8 builtin_f2l(float a)
2510 l = builtin_d2l((double) a);
2517 if (a > 9223372036854775807L)
2518 return 9223372036854775807L;
2519 if (a < (-9223372036854775808L))
2520 return (-9223372036854775808L);
2525 f = copysignf((float) 1.0, a);
2527 return 9223372036854775807L;
2528 return (-9223372036854775808L); */
2530 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2533 #if !(SUPPORT_DOUBLE && SUPPORT_D2I)
2534 s4 builtin_d2i(double a)
2539 if (a >= 2147483647)
2541 if (a <= (-2147483647-1))
2542 return (-2147483647-1);
2547 d = copysign(1.0, a);
2550 return (-2147483647-1);
2552 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) */
2555 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2556 s8 builtin_d2l(double a)
2561 if (a >= 9223372036854775807LL)
2562 return 9223372036854775807LL;
2563 if (a <= (-9223372036854775807LL-1))
2564 return (-9223372036854775807LL-1);
2569 d = copysign(1.0, a);
2571 return 9223372036854775807LL;
2572 return (-9223372036854775807LL-1);
2574 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2577 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2578 double builtin_f2d(float a)
2580 if (finitef(a)) return (double) a;
2583 return longBitsToDouble(DBL_NAN);
2585 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2589 float builtin_d2f(double a)
2595 return intBitsToFloat(FLT_NAN);
2597 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2600 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2603 /* builtin_clone_array *********************************************************
2605 Wrapper function for cloning arrays.
2607 *******************************************************************************/
2609 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2611 java_arrayheader *ah;
2612 java_lang_Cloneable *c;
2614 c = (java_lang_Cloneable *) o;
2616 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2622 /* builtin_asm_get_exceptionptrptr *********************************************
2624 this is a wrapper for calls from asmpart
2626 *******************************************************************************/
2628 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2629 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2631 return builtin_get_exceptionptrptr();
2637 * These are local overrides for various environment variables in Emacs.
2638 * Please do not remove this and leave it at the end of the file, where
2639 * Emacs will automagically detect them.
2640 * ---------------------------------------------------------------------
2643 * indent-tabs-mode: t