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 4132 2006-01-10 22:11:36Z twisti $
55 #include "fdlibm/fdlibm.h"
58 #include "mm/memory.h"
59 #include "native/native.h"
60 #include "native/include/java_lang_Cloneable.h"
61 #include "native/include/java_lang_Object.h" /* required by VMObject */
62 #include "native/include/java_lang_VMObject.h"
64 #if defined(USE_THREADS)
65 # if defined(NATIVE_THREADS)
66 # include "threads/native/threads.h"
68 # include "threads/green/threads.h"
69 # include "threads/green/locks.h"
73 #include "toolbox/logging.h"
74 #include "toolbox/util.h"
75 #include "vm/builtin.h"
77 #include "vm/exceptions.h"
78 #include "vm/global.h"
79 #include "vm/initialize.h"
80 #include "vm/loader.h"
81 #include "vm/options.h"
82 #include "vm/stringlocal.h"
83 #include "vm/jit/asmpart.h"
84 #include "vm/jit/patcher.h"
87 /* include builtin tables *****************************************************/
89 #include "vm/builtintable.inc"
92 /* builtintable_init ***********************************************************
94 Parse the descriptors of builtin functions and create the parsed
97 *******************************************************************************/
99 static bool builtintable_init(void)
101 descriptor_pool *descpool;
105 s4 entries_automatic;
108 /* mark start of dump memory area */
110 dumpsize = dump_size();
112 /* create a new descriptor pool */
114 descpool = descriptor_pool_new(class_java_lang_Object);
116 /* add some entries we need */
118 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
124 /* calculate table entries statically */
127 sizeof(builtintable_internal) / sizeof(builtintable_entry);
130 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
131 - 1; /* last filler entry (comment see builtintable.inc) */
133 /* first add all descriptors to the pool */
135 for (i = 0; i < entries_internal; i++) {
136 /* create a utf8 string from descriptor */
138 descriptor = utf_new_char(builtintable_internal[i].descriptor);
140 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
141 /* release dump area */
143 dump_release(dumpsize);
149 for (i = 0; i < entries_automatic; i++) {
150 /* create a utf8 string from descriptor */
152 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
154 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
155 /* release dump area */
157 dump_release(dumpsize);
163 /* create the class reference table */
165 (void) descriptor_pool_create_classrefs(descpool, NULL);
167 /* allocate space for the parsed descriptors */
169 descriptor_pool_alloc_parsed_descriptors(descpool);
171 /* now parse all descriptors */
173 for (i = 0; i < entries_internal; i++) {
174 /* create a utf8 string from descriptor */
176 descriptor = utf_new_char(builtintable_internal[i].descriptor);
178 /* parse the descriptor, builtin is always static (no `this' pointer) */
180 builtintable_internal[i].md =
181 descriptor_pool_parse_method_descriptor(descpool, descriptor,
185 for (i = 0; i < entries_automatic; i++) {
186 /* create a utf8 string from descriptor */
188 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
190 /* parse the descriptor, builtin is always static (no `this' pointer) */
192 builtintable_automatic[i].md =
193 descriptor_pool_parse_method_descriptor(descpool, descriptor,
197 /* release dump area */
199 dump_release(dumpsize);
205 /* builtintable_comparator *****************************************************
207 qsort comparator for the automatic builtin table.
209 *******************************************************************************/
211 static int builtintable_comparator(const void *a, const void *b)
213 builtintable_entry *bte1;
214 builtintable_entry *bte2;
216 bte1 = (builtintable_entry *) a;
217 bte2 = (builtintable_entry *) b;
219 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
223 /* builtintable_sort_automatic *************************************************
225 Sorts the automatic builtin table.
227 *******************************************************************************/
229 static void builtintable_sort_automatic(void)
233 /* calculate table size statically (`- 1' comment see builtintable.inc) */
235 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
237 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
238 builtintable_comparator);
242 /* builtin_init ****************************************************************
246 *******************************************************************************/
248 bool builtin_init(void)
250 /* initialize the builtin tables */
252 if (!builtintable_init())
255 /* sort builtin tables */
257 builtintable_sort_automatic();
263 /* builtintable_get_internal ***************************************************
265 Finds an entry in the builtintable for internal functions and
266 returns the a pointer to the structure.
268 *******************************************************************************/
270 builtintable_entry *builtintable_get_internal(functionptr fp)
274 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
275 if (builtintable_internal[i].fp == fp)
276 return &builtintable_internal[i];
283 /* builtintable_get_automatic **************************************************
285 Finds an entry in the builtintable for functions which are replaced
286 automatically and returns the a pointer to the structure.
288 *******************************************************************************/
290 builtintable_entry *builtintable_get_automatic(s4 opcode)
292 builtintable_entry *first;
293 builtintable_entry *last;
294 builtintable_entry *middle;
298 /* calculate table size statically (`- 1' comment see builtintable.inc) */
300 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
302 first = builtintable_automatic;
303 last = builtintable_automatic + entries;
305 while (entries > 0) {
307 middle = first + half;
309 if (middle->opcode < opcode) {
316 return (first != last ? first : NULL);
320 /*****************************************************************************
322 *****************************************************************************/
326 /*************** internal function: builtin_isanysubclass *********************
328 Checks a subclass relation between two classes. Implemented interfaces
329 are interpreted as super classes.
330 Return value: 1 ... sub is subclass of super
333 *****************************************************************************/
334 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
337 castinfo classvalues;
342 if (super->flags & ACC_INTERFACE) {
343 res = (sub->vftbl->interfacetablelength > super->index) &&
344 (sub->vftbl->interfacetable[-super->index] != NULL);
347 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
349 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
350 (u4) classvalues.super_diffval;
357 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
361 castinfo classvalues;
366 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
368 if ((base = classvalues.super_baseval) <= 0) {
369 /* super is an interface */
370 res = (sub->interfacetablelength > -base) &&
371 (sub->interfacetable[base] != NULL);
373 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
374 <= (u4) classvalues.super_diffval;
381 /****************** function: builtin_instanceof *****************************
383 Checks if an object is an instance of some given class (or subclass of
384 that class). If class is an interface, checks if the interface is
386 Return value: 1 ... obj is an instance of class or implements the interface
387 0 ... otherwise or if obj == NULL
389 *****************************************************************************/
391 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
396 return builtin_isanysubclass(obj->vftbl->class, class);
401 /**************** function: builtin_checkcast *******************************
403 The same as builtin_instanceof except that 1 is returned when
406 ****************************************************************************/
408 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
413 if (builtin_isanysubclass(obj->vftbl->class, class))
420 /* builtin_descriptorscompatible ***********************************************
422 Checks if two array type descriptors are assignment compatible
424 Return value: 1 ... target = desc is possible
427 *******************************************************************************/
429 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
430 arraydescriptor *target)
435 if (desc->arraytype != target->arraytype)
438 if (desc->arraytype != ARRAYTYPE_OBJECT)
441 /* {both arrays are arrays of references} */
443 if (desc->dimension == target->dimension) {
444 /* an array which contains elements of interface types is
445 allowed to be casted to Object (JOWENN)*/
447 if ((desc->elementvftbl->baseval < 0) &&
448 (target->elementvftbl->baseval == 1))
451 return builtin_isanysubclass_vftbl(desc->elementvftbl,
452 target->elementvftbl);
455 if (desc->dimension < target->dimension)
458 /* {desc has higher dimension than target} */
460 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
461 target->elementvftbl);
465 /* builtin_arraycheckcast ******************************************************
467 Checks if an object is really a subtype of the requested array
468 type. The object has to be an array to begin with. For simple
469 arrays (int, short, double, etc.) the types have to match exactly.
470 For arrays of objects, the type of elements in the array has to be
471 a subtype (or the same type) of the requested element type. For
472 arrays of arrays (which in turn can again be arrays of arrays), the
473 types at the lowest level have to satisfy the corresponding sub
476 *******************************************************************************/
478 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
480 arraydescriptor *desc;
485 if ((desc = o->vftbl->arraydesc) == NULL)
488 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
492 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
497 return builtin_arraycheckcast(o, targetclass);
501 /************************** exception functions *******************************
503 ******************************************************************************/
506 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
508 java_lang_Throwable *t;
514 t = (java_lang_Throwable *) xptr;
516 /* calculate message length */
518 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
522 utf_strlen(xptr->vftbl->class->name) +
524 javastring_strlen(t->detailMessage);
527 logtextlen += strlen("(nil)");
529 /* allocate memory */
531 dumpsize = dump_size();
533 logtext = DMNEW(char, logtextlen);
535 strcpy(logtext, "Builtin exception thrown: ");
538 utf_sprint_classname(logtext + strlen(logtext),
539 xptr->vftbl->class->name);
541 if (t->detailMessage) {
544 buf = javastring_tochar((java_objectheader *) t->detailMessage);
545 strcat(logtext, ": ");
546 strcat(logtext, buf);
547 MFREE(buf, char, strlen(buf));
551 strcat(logtext, "(nil)");
558 dump_release(dumpsize);
561 *exceptionptr = xptr;
565 #endif /* !defined(NDEBUG) */
568 /* builtin_canstore ************************************************************
570 Checks, if an object can be stored in an array.
572 Return value: 1 ... possible
575 *******************************************************************************/
577 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
579 arraydescriptor *desc;
580 arraydescriptor *valuedesc;
581 vftbl_t *componentvftbl;
584 castinfo classvalues;
589 /* The following is guaranteed (by verifier checks):
591 * *) oa->...vftbl->arraydesc != NULL
592 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
593 * *) o->vftbl is not an interface vftbl
596 desc = oa->header.objheader.vftbl->arraydesc;
597 componentvftbl = desc->componentvftbl;
598 valuevftbl = o->vftbl;
600 if ((desc->dimension - 1) == 0) {
603 /* {oa is a one-dimensional array} */
604 /* {oa is an array of references} */
606 if (valuevftbl == componentvftbl)
609 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
611 if ((base = classvalues.super_baseval) <= 0)
612 /* an array of interface references */
613 return (valuevftbl->interfacetablelength > -base &&
614 valuevftbl->interfacetable[base] != NULL);
616 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
617 <= (unsigned) classvalues.super_diffval);
622 /* {oa has dimension > 1} */
623 /* {componentvftbl->arraydesc != NULL} */
625 /* check if o is an array */
627 if ((valuedesc = valuevftbl->arraydesc) == NULL)
630 /* {o is an array} */
632 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
636 /* This is an optimized version where a is guaranteed to be one-dimensional */
637 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
639 arraydescriptor *desc;
640 vftbl_t *elementvftbl;
644 castinfo classvalues;
648 /* The following is guaranteed (by verifier checks):
650 * *) a->...vftbl->arraydesc != NULL
651 * *) a->...vftbl->arraydesc->elementvftbl != NULL
652 * *) a->...vftbl->arraydesc->dimension == 1
653 * *) o->vftbl is not an interface vftbl
656 desc = a->header.objheader.vftbl->arraydesc;
657 elementvftbl = desc->elementvftbl;
658 valuevftbl = o->vftbl;
660 /* {a is a one-dimensional array} */
662 if (valuevftbl == elementvftbl)
665 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
667 if ((base = classvalues.super_baseval) <= 0)
668 /* an array of interface references */
669 return (valuevftbl->interfacetablelength > -base &&
670 valuevftbl->interfacetable[base] != NULL);
672 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
673 <= (unsigned) classvalues.super_diffval;
679 /* This is an optimized version where a is guaranteed to be a
680 * one-dimensional array of a class type */
681 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
683 vftbl_t *elementvftbl;
686 castinfo classvalues;
690 /* The following is guaranteed (by verifier checks):
692 * *) a->...vftbl->arraydesc != NULL
693 * *) a->...vftbl->arraydesc->elementvftbl != NULL
694 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
695 * *) a->...vftbl->arraydesc->dimension == 1
696 * *) o->vftbl is not an interface vftbl
699 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
700 valuevftbl = o->vftbl;
702 /* {a is a one-dimensional array} */
704 if (valuevftbl == elementvftbl)
707 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
709 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
710 <= (unsigned) classvalues.super_diffval;
716 /* builtin_new *****************************************************************
718 Creates a new instance of class c on the heap.
720 Return value: pointer to the object or NULL if no memory is
723 *******************************************************************************/
725 java_objectheader *builtin_new(classinfo *c)
727 java_objectheader *o;
729 /* is the class loaded */
731 assert(c->state & CLASS_LOADED);
733 /* check if we can instantiate this class */
735 if (c->flags & ACC_ABSTRACT) {
737 new_exception_utfmessage(string_java_lang_InstantiationError,
742 /* is the class linked */
744 if (!(c->state & CLASS_LINKED))
748 if (!(c->state & CLASS_INITIALIZED)) {
750 log_message_class("Initialize class (from builtin_new): ", c);
752 if (!initialize_class(c))
756 o = heap_allocate(c->instancesize, true, c->finalizer);
763 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
771 /* builtin_newarray ************************************************************
773 Creates an array with the given vftbl on the heap. This function
774 takes as class argument an array class.
776 Return value: pointer to the array or NULL if no memory is available
778 *******************************************************************************/
780 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
782 arraydescriptor *desc;
788 desc = arrayclass->vftbl->arraydesc;
789 dataoffset = desc->dataoffset;
790 componentsize = desc->componentsize;
793 exceptions_throw_negativearraysizeexception();
797 actualsize = dataoffset + size * componentsize;
799 if (((u4) actualsize) < ((u4) size)) { /* overflow */
800 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
804 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
809 a->objheader.vftbl = arrayclass->vftbl;
811 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
812 initObjectLock(&a->objheader);
821 /* builtin_anewarray ***********************************************************
823 Creates an array of references to the given class type on the heap.
825 Return value: pointer to the array or NULL if no memory is
828 *******************************************************************************/
830 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
832 classinfo *arrayclass;
834 /* is class loaded */
836 assert(componentclass->state & CLASS_LOADED);
838 /* is class linked */
840 if (!(componentclass->state & CLASS_LINKED))
841 if (!link_class(componentclass))
844 arrayclass = class_array_of(componentclass, true);
849 return (java_objectarray *) builtin_newarray(size, arrayclass);
853 /* builtin_newarray_boolean ****************************************************
855 Creates an array of bytes on the heap. The array is designated as
856 an array of booleans (important for casts)
858 Return value: pointer to the array or NULL if no memory is
861 *******************************************************************************/
863 java_booleanarray *builtin_newarray_boolean(s4 size)
865 return (java_booleanarray *)
866 builtin_newarray(size,
867 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
871 /* builtin_newarray_byte *******************************************************
873 Creates an array of 8 bit Integers on the heap.
875 Return value: pointer to the array or NULL if no memory is
878 *******************************************************************************/
880 java_bytearray *builtin_newarray_byte(s4 size)
882 return (java_bytearray *)
883 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
887 /* builtin_newarray_char *******************************************************
889 Creates an array of characters on the heap.
891 Return value: pointer to the array or NULL if no memory is
894 *******************************************************************************/
896 java_chararray *builtin_newarray_char(s4 size)
898 return (java_chararray *)
899 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
903 /* builtin_newarray_short ******************************************************
905 Creates an array of 16 bit Integers on the heap.
907 Return value: pointer to the array or NULL if no memory is
910 *******************************************************************************/
912 java_shortarray *builtin_newarray_short(s4 size)
914 return (java_shortarray *)
915 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
919 /* builtin_newarray_int ********************************************************
921 Creates an array of 32 bit Integers on the heap.
923 Return value: pointer to the array or NULL if no memory is
926 *******************************************************************************/
928 java_intarray *builtin_newarray_int(s4 size)
930 return (java_intarray *)
931 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
935 /* builtin_newarray_long *******************************************************
937 Creates an array of 64 bit Integers on the heap.
939 Return value: pointer to the array or NULL if no memory is
942 *******************************************************************************/
944 java_longarray *builtin_newarray_long(s4 size)
946 return (java_longarray *)
947 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
951 /* builtin_newarray_float ******************************************************
953 Creates an array of 32 bit IEEE floats on the heap.
955 Return value: pointer to the array or NULL if no memory is
958 *******************************************************************************/
960 java_floatarray *builtin_newarray_float(s4 size)
962 return (java_floatarray *)
963 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
967 /* builtin_newarray_double *****************************************************
969 Creates an array of 64 bit IEEE floats on the heap.
971 Return value: pointer to the array or NULL if no memory is
974 *******************************************************************************/
976 java_doublearray *builtin_newarray_double(s4 size)
978 return (java_doublearray *)
979 builtin_newarray(size,
980 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
984 /* builtin_multianewarray_intern ***********************************************
986 Creates a multi-dimensional array on the heap. The dimensions are
987 passed in an array of longs.
990 n............number of dimensions to create
991 arrayvftbl...vftbl of the array class
992 dims.........array containing the size of each dimension to create
994 Return value: pointer to the array or NULL if no memory is
997 ******************************************************************************/
999 static java_arrayheader *builtin_multianewarray_intern(int n,
1000 classinfo *arrayclass,
1004 java_arrayheader *a;
1005 classinfo *componentclass;
1008 /* create this dimension */
1010 size = (s4) dims[0];
1011 a = builtin_newarray(size, arrayclass);
1016 /* if this is the last dimension return */
1021 /* get the class of the components to create */
1023 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1025 /* The verifier guarantees that the dimension count is in the range. */
1027 /* create the component arrays */
1029 for (i = 0; i < size; i++) {
1030 java_arrayheader *ea =
1031 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1032 /* we save an s4 to a s8 slot, 8-byte aligned */
1034 builtin_multianewarray_intern(n, componentclass, dims + 2);
1036 builtin_multianewarray_intern(n, componentclass, dims + 1);
1042 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1049 /* builtin_multianewarray ******************************************************
1051 Wrapper for builtin_multianewarray_intern which checks all
1052 dimensions before we start allocating.
1054 ******************************************************************************/
1056 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1062 /* check all dimensions before doing anything */
1064 for (i = 0; i < n; i++) {
1065 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1066 /* we save an s4 to a s8 slot, 8-byte aligned */
1067 size = (s4) dims[i * 2];
1069 size = (s4) dims[i];
1073 exceptions_throw_negativearraysizeexception();
1078 /* now call the real function */
1080 return builtin_multianewarray_intern(n, arrayclass, dims);
1084 /*****************************************************************************
1087 Various functions for printing a message at method entry or exit (for
1090 *****************************************************************************/
1092 #if !defined(NDEBUG)
1093 s4 methodindent = 0;
1095 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1104 if (runverbose && indent)
1107 /* calculate message length */
1111 strlen("Exception ") +
1112 utf_strlen(xptr->vftbl->class->name);
1115 logtextlen = strlen("Some Throwable");
1118 logtextlen += strlen(" thrown in ");
1122 utf_strlen(m->class->name) +
1124 utf_strlen(m->name) +
1125 utf_strlen(m->descriptor) +
1126 strlen("(NOSYNC,NATIVE");
1128 #if SIZEOF_VOID_P == 8
1130 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1132 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1135 if (m->class->sourcefile == NULL)
1136 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1138 logtextlen += utf_strlen(m->class->sourcefile);
1140 logtextlen += strlen(":65536)");
1143 logtextlen += strlen("call_java_method");
1145 logtextlen += strlen("0");
1147 /* allocate memory */
1149 dumpsize = dump_size();
1151 logtext = DMNEW(char, logtextlen);
1154 strcpy(logtext, "Exception ");
1155 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1158 strcpy(logtext, "Some Throwable");
1161 strcat(logtext, " thrown in ");
1164 utf_strcat_classname(logtext, m->class->name);
1165 strcat(logtext, ".");
1166 utf_strcat(logtext, m->name);
1167 utf_strcat(logtext, m->descriptor);
1169 if (m->flags & ACC_SYNCHRONIZED)
1170 strcat(logtext, "(SYNC");
1172 strcat(logtext, "(NOSYNC");
1174 if (m->flags & ACC_NATIVE) {
1175 strcat(logtext, ",NATIVE");
1177 #if SIZEOF_VOID_P == 8
1178 sprintf(logtext + strlen(logtext),
1179 ")(0x%016lx) at position 0x%016lx",
1180 (ptrint) m->entrypoint, (ptrint) pos);
1182 sprintf(logtext + strlen(logtext),
1183 ")(0x%08x) at position 0x%08x",
1184 (ptrint) m->entrypoint, (ptrint) pos);
1188 #if SIZEOF_VOID_P == 8
1189 sprintf(logtext + strlen(logtext),
1190 ")(0x%016lx) at position 0x%016lx (",
1191 (ptrint) m->entrypoint, (ptrint) pos);
1193 sprintf(logtext + strlen(logtext),
1194 ")(0x%08x) at position 0x%08x (",
1195 (ptrint) m->entrypoint, (ptrint) pos);
1198 if (m->class->sourcefile == NULL)
1199 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1201 utf_strcat(logtext, m->class->sourcefile);
1203 sprintf(logtext + strlen(logtext), ":%d)", 0);
1207 strcat(logtext, "call_java_method");
1211 /* release memory */
1213 dump_release(dumpsize);
1215 /* print stacktrace for exception */
1217 if (opt_verboseexception) {
1218 exceptions_print_exception(xptr);
1219 stacktrace_print_trace(xptr);
1224 #endif /* !defined(NDEBUG) */
1227 /* builtin_trace_args **********************************************************
1231 *******************************************************************************/
1233 #if !defined(NDEBUG)
1235 #ifdef TRACE_ARGS_NUM
1236 void builtin_trace_args(s8 a0, s8 a1,
1237 #if TRACE_ARGS_NUM >= 4
1239 #endif /* TRACE_ARGS_NUM >= 4 */
1240 #if TRACE_ARGS_NUM >= 6
1242 #endif /* TRACE_ARGS_NUM >= 6 */
1243 #if TRACE_ARGS_NUM == 8
1245 #endif /* TRACE_ARGS_NUM == 8 */
1257 /* calculate message length */
1260 6 + methodindent + strlen("called: ") +
1261 utf_strlen(m->class->name) +
1263 utf_strlen(m->name) +
1264 utf_strlen(m->descriptor) +
1265 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1267 /* add maximal argument length */
1269 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1271 /* allocate memory */
1273 dumpsize = dump_size();
1275 logtext = DMNEW(char, logtextlen);
1277 sprintf(logtext,"-%d-",methodindent);
1278 pos = strlen(logtext);
1280 for (i = 0; i < methodindent; i++)
1281 logtext[pos++] = '\t';
1283 strcpy(logtext + pos, "called: ");
1285 utf_strcat_classname(logtext, m->class->name);
1286 strcat(logtext, ".");
1287 utf_strcat(logtext, m->name);
1288 utf_strcat(logtext, m->descriptor);
1290 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1291 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1292 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1293 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1294 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1295 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1296 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1297 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1298 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1299 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1300 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1302 strcat(logtext, "(");
1304 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1305 /* Only Arguments in integer Registers are passed correctly here */
1306 /* long longs spilled on Stack have an wrong offset of +4 */
1307 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1308 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1309 switch (md->paramcount) {
1313 #if SIZEOF_VOID_P == 4
1315 sprintf(logtext + strlen(logtext),
1321 sprintf(logtext + strlen(logtext),
1326 #if TRACE_ARGS_NUM >= 4
1328 sprintf(logtext + strlen(logtext),
1329 "0x%llx, 0x%llx, 0x%llx",
1334 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1336 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1339 #endif /* TRACE_ARGS_NUM >= 4 */
1341 #if TRACE_ARGS_NUM >= 6
1343 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1345 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1350 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1352 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1355 #endif /* TRACE_ARGS_NUM >= 6 */
1357 #if TRACE_ARGS_NUM == 8
1359 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1361 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1363 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1367 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1369 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1371 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1373 #endif /* TRACE_ARGS_NUM == 8 */
1376 #if TRACE_ARGS_NUM == 2
1377 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1379 #elif TRACE_ARGS_NUM == 4
1380 sprintf(logtext + strlen(logtext),
1381 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1382 a0, a1, a2, a3, md->paramcount - 4);
1384 #elif TRACE_ARGS_NUM == 6
1385 sprintf(logtext + strlen(logtext),
1386 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1387 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1389 #elif TRACE_ARGS_NUM == 8
1390 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1392 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1394 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1395 , a6, a7, md->paramcount - 8);
1399 #else /* SIZEOF_VOID_P == 4 */
1402 sprintf(logtext + strlen(logtext),
1408 sprintf(logtext + strlen(logtext),
1414 sprintf(logtext + strlen(logtext),
1415 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1419 sprintf(logtext + strlen(logtext),
1420 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1424 #if TRACE_ARGS_NUM >= 6
1426 sprintf(logtext + strlen(logtext),
1427 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1428 a0, a1, a2, a3, a4);
1432 sprintf(logtext + strlen(logtext),
1433 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1434 a0, a1, a2, a3, a4, a5);
1436 #endif /* TRACE_ARGS_NUM >= 6 */
1438 #if TRACE_ARGS_NUM == 8
1440 sprintf(logtext + strlen(logtext),
1441 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1442 a0, a1, a2, a3, a4, a5, a6);
1446 sprintf(logtext + strlen(logtext),
1447 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1448 a0, a1, a2, a3, a4, a5, a6, a7);
1450 #endif /* TRACE_ARGS_NUM == 8 */
1453 #if TRACE_ARGS_NUM == 4
1454 sprintf(logtext + strlen(logtext),
1455 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1456 a0, a1, a2, a3, md->paramcount - 4);
1458 #elif TRACE_ARGS_NUM == 6
1459 sprintf(logtext + strlen(logtext),
1460 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1461 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1463 #elif TRACE_ARGS_NUM == 8
1464 sprintf(logtext + strlen(logtext),
1465 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1466 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1469 #endif /* SIZEOF_VOID_P == 4 */
1472 strcat(logtext, ")");
1476 /* release memory */
1478 dump_release(dumpsize);
1483 #endif /* !defined(NDEBUG) */
1486 /* builtin_displaymethodstop ***************************************************
1490 *******************************************************************************/
1492 #if !defined(NDEBUG)
1493 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1501 java_objectheader *o;
1502 java_lang_String *s;
1510 /* calculate message length */
1513 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1515 strlen("finished: ") +
1516 utf_strlen(m->class->name) +
1518 utf_strlen(m->name) +
1519 utf_strlen(m->descriptor) +
1520 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1522 /* add maximal argument length */
1524 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1526 /* allocate memory */
1528 dumpsize = dump_size();
1530 logtext = DMNEW(char, logtextlen);
1532 /* outdent the log message */
1537 log_text("WARNING: unmatched methodindent--");
1539 /* generate the message */
1541 sprintf(logtext, "-%d-", methodindent);
1543 pos = strlen(logtext);
1545 for (i = 0; i < methodindent; i++)
1546 logtext[pos++] = '\t';
1548 strcpy(logtext + pos, "finished: ");
1549 utf_strcat_classname(logtext, m->class->name);
1550 strcat(logtext, ".");
1551 utf_strcat(logtext, m->name);
1552 utf_strcat(logtext, m->descriptor);
1554 switch (md->returntype.type) {
1556 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1560 #if SIZEOF_VOID_P == 4
1561 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1563 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1568 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1570 /* check return argument for java.lang.Class or java.lang.String */
1572 o = (java_objectheader *) (ptrint) l;
1575 if (o->vftbl->class == class_java_lang_String) {
1576 /* get java.lang.String object and the length of the
1579 s= (java_lang_String *) (ptrint) l;
1581 len = strlen(", String = \"") + javastring_strlen(s) +
1584 /* realloc memory for string length */
1586 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1588 /* convert to utf8 string and strcat it to the logtext */
1590 u = javastring_toutf(s, false);
1592 strcat(logtext, ", String = \"");
1593 utf_strcat(logtext, u);
1594 strcat(logtext, "\"");
1597 if (o->vftbl->class == class_java_lang_Class) {
1598 /* if the object returned is a java.lang.Class
1599 cast it to classinfo structure and get the name
1602 c = (classinfo *) (ptrint) l;
1607 /* if the object returned is not a java.lang.String or
1608 a java.lang.Class just print the name of the class */
1610 u = o->vftbl->class->name;
1613 len = strlen(", Class = \"") + utf_strlen(u) + strlen("\"");
1615 /* realloc memory for string length */
1617 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1619 /* strcat to the logtext */
1621 strcat(logtext, ", Class = \"");
1622 utf_strcat(logtext, u);
1623 strcat(logtext, "\"");
1630 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1635 #if SIZEOF_VOID_P == 4
1636 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1638 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1645 /* release memory */
1647 dump_release(dumpsize);
1649 #endif /* !defined(NDEBUG) */
1652 /****************************************************************************
1653 SYNCHRONIZATION FUNCTIONS
1654 *****************************************************************************/
1656 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1658 * Lock the mutex of an object.
1660 void internal_lock_mutex_for_object(java_objectheader *object)
1662 mutexHashEntry *entry;
1665 assert(object != 0);
1667 hashValue = MUTEX_HASH_VALUE(object);
1668 entry = &mutexHashTable[hashValue];
1670 if (entry->object != 0) {
1671 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1673 entry->mutex.holder = 0;
1674 entry->mutex.count = 0;
1675 entry->mutex.muxWaiters = 0;
1678 while (entry->next != 0 && entry->object != object)
1679 entry = entry->next;
1681 if (entry->object != object) {
1682 entry->next = firstFreeOverflowEntry;
1683 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1685 entry = entry->next;
1688 assert(entry->conditionCount == 0);
1693 entry->mutex.holder = 0;
1694 entry->mutex.count = 0;
1695 entry->mutex.muxWaiters = 0;
1698 if (entry->object == 0)
1699 entry->object = object;
1701 internal_lock_mutex(&entry->mutex);
1706 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1708 * Unlocks the mutex of an object.
1710 void internal_unlock_mutex_for_object (java_objectheader *object)
1713 mutexHashEntry *entry;
1715 hashValue = MUTEX_HASH_VALUE(object);
1716 entry = &mutexHashTable[hashValue];
1718 if (entry->object == object) {
1719 internal_unlock_mutex(&entry->mutex);
1722 while (entry->next != 0 && entry->next->object != object)
1723 entry = entry->next;
1725 assert(entry->next != 0);
1727 internal_unlock_mutex(&entry->next->mutex);
1729 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1730 mutexHashEntry *unlinked = entry->next;
1732 entry->next = unlinked->next;
1733 unlinked->next = firstFreeOverflowEntry;
1734 firstFreeOverflowEntry = unlinked;
1741 #if defined(USE_THREADS)
1742 void builtin_monitorenter(java_objectheader *o)
1744 #if !defined(NATIVE_THREADS)
1749 hashValue = MUTEX_HASH_VALUE(o);
1750 if (mutexHashTable[hashValue].object == o
1751 && mutexHashTable[hashValue].mutex.holder == currentThread)
1752 ++mutexHashTable[hashValue].mutex.count;
1754 internal_lock_mutex_for_object(o);
1758 monitorEnter((threadobject *) THREADOBJECT, o);
1764 #if defined(USE_THREADS)
1766 * Locks the class object - needed for static synchronized methods.
1768 void builtin_staticmonitorenter(classinfo *c)
1770 builtin_monitorenter(&c->object.header);
1775 #if defined(USE_THREADS)
1776 void builtin_monitorexit(java_objectheader *o)
1778 #if !defined(NATIVE_THREADS)
1783 hashValue = MUTEX_HASH_VALUE(o);
1784 if (mutexHashTable[hashValue].object == o) {
1785 if (mutexHashTable[hashValue].mutex.count == 1
1786 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1787 internal_unlock_mutex_for_object(o);
1789 --mutexHashTable[hashValue].mutex.count;
1792 internal_unlock_mutex_for_object(o);
1796 monitorExit((threadobject *) THREADOBJECT, o);
1802 /*****************************************************************************
1803 MISCELLANEOUS HELPER FUNCTIONS
1804 *****************************************************************************/
1808 /*********** Functions for integer divisions *****************************
1810 On some systems (eg. DEC ALPHA), integer division is not supported by the
1811 CPU. These helper functions implement the missing functionality.
1813 ******************************************************************************/
1815 #if !SUPPORT_DIVISION
1816 s4 builtin_idiv(s4 a, s4 b)
1825 s4 builtin_irem(s4 a, s4 b)
1833 #endif /* !SUPPORT_DIVISION */
1836 /* functions for long arithmetics **********************************************
1838 On systems where 64 bit Integers are not supported by the CPU,
1839 these functions are needed.
1841 ******************************************************************************/
1843 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1844 s8 builtin_ladd(s8 a, s8 b)
1857 s8 builtin_lsub(s8 a, s8 b)
1870 s8 builtin_lneg(s8 a)
1882 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1885 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1886 s8 builtin_lmul(s8 a, s8 b)
1898 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1901 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1902 s8 builtin_ldiv(s8 a, s8 b)
1915 s8 builtin_lrem(s8 a, s8 b)
1927 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1930 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1931 s8 builtin_lshl(s8 a, s4 b)
1944 s8 builtin_lshr(s8 a, s4 b)
1957 s8 builtin_lushr(s8 a, s4 b)
1962 c = ((u8) a) >> (b & 63);
1969 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1972 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1973 s8 builtin_land(s8 a, s8 b)
1986 s8 builtin_lor(s8 a, s8 b)
1999 s8 builtin_lxor(s8 a, s8 b)
2011 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2014 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2015 s4 builtin_lcmp(s8 a, s8 b)
2029 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2032 /* functions for unsupported floating instructions ****************************/
2034 /* used to convert FLT_xxx defines into float values */
2036 static inline float intBitsToFloat(s4 i)
2045 /* used to convert DBL_xxx defines into double values */
2047 static inline float longBitsToDouble(s8 l)
2057 float builtin_fadd(float a, float b)
2059 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2060 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2071 if (copysignf(1.0, a) == copysignf(1.0, b))
2074 return intBitsToFloat(FLT_NAN);
2080 float builtin_fsub(float a, float b)
2082 return builtin_fadd(a, builtin_fneg(b));
2086 float builtin_fmul(float a, float b)
2088 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2089 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2091 if (finitef(b)) return a * b;
2093 if (a == 0) return intBitsToFloat(FLT_NAN);
2094 else return copysignf(b, copysignf(1.0, b)*a);
2099 if (b == 0) return intBitsToFloat(FLT_NAN);
2100 else return copysignf(a, copysignf(1.0, a)*b);
2103 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2109 /* builtin_ddiv ****************************************************************
2111 Implementation as described in VM Spec.
2113 *******************************************************************************/
2115 float builtin_fdiv(float a, float b)
2119 /* If neither value1' nor value2' is NaN, the sign of the result */
2120 /* is positive if both values have the same sign, negative if the */
2121 /* values have different signs. */
2127 /* If either value1' or value2' is NaN, the result is NaN. */
2129 return intBitsToFloat(FLT_NAN);
2132 /* Division of a finite value by an infinity results in a */
2133 /* signed zero, with the sign-producing rule just given. */
2135 /* is sign equal? */
2137 if (copysignf(1.0, a) == copysignf(1.0, b))
2146 /* If either value1' or value2' is NaN, the result is NaN. */
2148 return intBitsToFloat(FLT_NAN);
2150 } else if (finitef(b)) {
2151 /* Division of an infinity by a finite value results in a signed */
2152 /* infinity, with the sign-producing rule just given. */
2154 /* is sign equal? */
2156 if (copysignf(1.0, a) == copysignf(1.0, b))
2157 return intBitsToFloat(FLT_POSINF);
2159 return intBitsToFloat(FLT_NEGINF);
2162 /* Division of an infinity by an infinity results in NaN. */
2164 return intBitsToFloat(FLT_NAN);
2170 float builtin_fneg(float a)
2172 if (isnanf(a)) return a;
2174 if (finitef(a)) return -a;
2175 else return copysignf(a, -copysignf(1.0, a));
2180 s4 builtin_fcmpl(float a, float b)
2182 if (isnanf(a)) return -1;
2183 if (isnanf(b)) return -1;
2184 if (!finitef(a) || !finitef(b)) {
2185 a = finitef(a) ? 0 : copysignf(1.0, a);
2186 b = finitef(b) ? 0 : copysignf(1.0, b);
2188 if (a > b) return 1;
2189 if (a == b) return 0;
2194 s4 builtin_fcmpg(float a, float b)
2196 if (isnanf(a)) return 1;
2197 if (isnanf(b)) return 1;
2198 if (!finitef(a) || !finitef(b)) {
2199 a = finitef(a) ? 0 : copysignf(1.0, a);
2200 b = finitef(b) ? 0 : copysignf(1.0, b);
2202 if (a > b) return 1;
2203 if (a == b) return 0;
2206 #endif /* !SUPPORT_FLOAT */
2209 float builtin_frem(float a, float b)
2215 /* functions for unsupported double instructions ******************************/
2218 double builtin_dadd(double a, double b)
2220 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2221 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2223 if (finite(b)) return a + b;
2227 if (finite(b)) return a;
2229 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2230 else return longBitsToDouble(DBL_NAN);
2236 double builtin_dsub(double a, double b)
2238 return builtin_dadd(a, builtin_dneg(b));
2242 double builtin_dmul(double a, double b)
2244 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2245 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2247 if (finite(b)) return a * b;
2249 if (a == 0) return longBitsToDouble(DBL_NAN);
2250 else return copysign(b, copysign(1.0, b) * a);
2255 if (b == 0) return longBitsToDouble(DBL_NAN);
2256 else return copysign(a, copysign(1.0, a) * b);
2259 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2265 /* builtin_ddiv ****************************************************************
2267 Implementation as described in VM Spec.
2269 *******************************************************************************/
2271 double builtin_ddiv(double a, double b)
2275 /* If neither value1' nor value2' is NaN, the sign of the result */
2276 /* is positive if both values have the same sign, negative if the */
2277 /* values have different signs. */
2283 /* If either value1' or value2' is NaN, the result is NaN. */
2285 return longBitsToDouble(DBL_NAN);
2288 /* Division of a finite value by an infinity results in a */
2289 /* signed zero, with the sign-producing rule just given. */
2291 /* is sign equal? */
2293 if (copysign(1.0, a) == copysign(1.0, b))
2302 /* If either value1' or value2' is NaN, the result is NaN. */
2304 return longBitsToDouble(DBL_NAN);
2306 } else if (finite(b)) {
2307 /* Division of an infinity by a finite value results in a signed */
2308 /* infinity, with the sign-producing rule just given. */
2310 /* is sign equal? */
2312 if (copysign(1.0, a) == copysign(1.0, b))
2313 return longBitsToDouble(DBL_POSINF);
2315 return longBitsToDouble(DBL_NEGINF);
2318 /* Division of an infinity by an infinity results in NaN. */
2320 return longBitsToDouble(DBL_NAN);
2326 /* builtin_dneg ****************************************************************
2328 Implemented as described in VM Spec.
2330 *******************************************************************************/
2332 double builtin_dneg(double a)
2335 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2342 /* If the operand is a zero, the result is the zero of opposite */
2348 /* If the operand is an infinity, the result is the infinity of */
2349 /* opposite sign. */
2351 return copysign(a, -copysign(1.0, a));
2357 s4 builtin_dcmpl(double a, double b)
2359 if (isnan(a)) return -1;
2360 if (isnan(b)) return -1;
2361 if (!finite(a) || !finite(b)) {
2362 a = finite(a) ? 0 : copysign(1.0, a);
2363 b = finite(b) ? 0 : copysign(1.0, b);
2365 if (a > b) return 1;
2366 if (a == b) return 0;
2371 s4 builtin_dcmpg(double a, double b)
2373 if (isnan(a)) return 1;
2374 if (isnan(b)) return 1;
2375 if (!finite(a) || !finite(b)) {
2376 a = finite(a) ? 0 : copysign(1.0, a);
2377 b = finite(b) ? 0 : copysign(1.0, b);
2379 if (a > b) return 1;
2380 if (a == b) return 0;
2383 #endif /* !SUPPORT_DOUBLE */
2386 double builtin_drem(double a, double b)
2392 /* conversion operations ******************************************************/
2395 s8 builtin_i2l(s4 i)
2407 s4 builtin_l2i(s8 l)
2418 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2419 float builtin_i2f(s4 a)
2421 float f = (float) a;
2424 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2427 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2428 double builtin_i2d(s4 a)
2430 double d = (double) a;
2433 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2436 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2437 float builtin_l2f(s8 a)
2440 float f = (float) a;
2446 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2449 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2450 double builtin_l2d(s8 a)
2453 double d = (double) a;
2459 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2462 #if !(SUPPORT_FLOAT && SUPPORT_F2I)
2463 s4 builtin_f2i(float a)
2467 i = builtin_d2i((double) a);
2478 if (a < (-2147483648))
2479 return (-2147483648);
2482 f = copysignf((float) 1.0, a);
2485 return (-2147483648); */
2487 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) */
2490 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2491 s8 builtin_f2l(float a)
2495 l = builtin_d2l((double) a);
2502 if (a > 9223372036854775807L)
2503 return 9223372036854775807L;
2504 if (a < (-9223372036854775808L))
2505 return (-9223372036854775808L);
2510 f = copysignf((float) 1.0, a);
2512 return 9223372036854775807L;
2513 return (-9223372036854775808L); */
2515 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2518 #if !(SUPPORT_DOUBLE && SUPPORT_D2I)
2519 s4 builtin_d2i(double a)
2524 if (a >= 2147483647)
2526 if (a <= (-2147483647-1))
2527 return (-2147483647-1);
2532 d = copysign(1.0, a);
2535 return (-2147483647-1);
2537 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) */
2540 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2541 s8 builtin_d2l(double a)
2546 if (a >= 9223372036854775807LL)
2547 return 9223372036854775807LL;
2548 if (a <= (-9223372036854775807LL-1))
2549 return (-9223372036854775807LL-1);
2554 d = copysign(1.0, a);
2556 return 9223372036854775807LL;
2557 return (-9223372036854775807LL-1);
2559 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2562 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2563 double builtin_f2d(float a)
2565 if (finitef(a)) return (double) a;
2568 return longBitsToDouble(DBL_NAN);
2570 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2574 float builtin_d2f(double a)
2580 return intBitsToFloat(FLT_NAN);
2582 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2585 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2588 /* builtin_clone_array *********************************************************
2590 Wrapper function for cloning arrays.
2592 *******************************************************************************/
2594 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2596 java_arrayheader *ah;
2597 java_lang_Cloneable *c;
2599 c = (java_lang_Cloneable *) o;
2601 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2607 /* builtin_asm_get_exceptionptrptr *********************************************
2609 this is a wrapper for calls from asmpart
2611 *******************************************************************************/
2613 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2614 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2616 return builtin_get_exceptionptrptr();
2622 * These are local overrides for various environment variables in Emacs.
2623 * Please do not remove this and leave it at the end of the file, where
2624 * Emacs will automagically detect them.
2625 * ---------------------------------------------------------------------
2628 * indent-tabs-mode: t