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 4016 2005-12-30 14:28:35Z 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 ******************************************************************************/
505 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
507 java_lang_Throwable *t;
513 t = (java_lang_Throwable *) xptr;
515 /* calculate message length */
517 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
521 utf_strlen(xptr->vftbl->class->name) +
523 javastring_strlen(t->detailMessage);
526 logtextlen += strlen("(nil)");
528 /* allocate memory */
530 dumpsize = dump_size();
532 logtext = DMNEW(char, logtextlen);
534 strcpy(logtext, "Builtin exception thrown: ");
537 utf_sprint_classname(logtext + strlen(logtext),
538 xptr->vftbl->class->name);
540 if (t->detailMessage) {
543 buf = javastring_tochar((java_objectheader *) t->detailMessage);
544 strcat(logtext, ": ");
545 strcat(logtext, buf);
546 MFREE(buf, char, strlen(buf));
550 strcat(logtext, "(nil)");
557 dump_release(dumpsize);
560 *exceptionptr = xptr;
567 /* builtin_canstore ************************************************************
569 Checks, if an object can be stored in an array.
571 Return value: 1 ... possible
574 *******************************************************************************/
576 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
578 arraydescriptor *desc;
579 arraydescriptor *valuedesc;
580 vftbl_t *componentvftbl;
583 castinfo classvalues;
588 /* The following is guaranteed (by verifier checks):
590 * *) oa->...vftbl->arraydesc != NULL
591 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
592 * *) o->vftbl is not an interface vftbl
595 desc = oa->header.objheader.vftbl->arraydesc;
596 componentvftbl = desc->componentvftbl;
597 valuevftbl = o->vftbl;
599 if ((desc->dimension - 1) == 0) {
602 /* {oa is a one-dimensional array} */
603 /* {oa is an array of references} */
605 if (valuevftbl == componentvftbl)
608 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
610 if ((base = classvalues.super_baseval) <= 0)
611 /* an array of interface references */
612 return (valuevftbl->interfacetablelength > -base &&
613 valuevftbl->interfacetable[base] != NULL);
615 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
616 <= (unsigned) classvalues.super_diffval);
621 /* {oa has dimension > 1} */
622 /* {componentvftbl->arraydesc != NULL} */
624 /* check if o is an array */
626 if ((valuedesc = valuevftbl->arraydesc) == NULL)
629 /* {o is an array} */
631 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
635 /* This is an optimized version where a is guaranteed to be one-dimensional */
636 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
638 arraydescriptor *desc;
639 vftbl_t *elementvftbl;
643 castinfo classvalues;
647 /* The following is guaranteed (by verifier checks):
649 * *) a->...vftbl->arraydesc != NULL
650 * *) a->...vftbl->arraydesc->elementvftbl != NULL
651 * *) a->...vftbl->arraydesc->dimension == 1
652 * *) o->vftbl is not an interface vftbl
655 desc = a->header.objheader.vftbl->arraydesc;
656 elementvftbl = desc->elementvftbl;
657 valuevftbl = o->vftbl;
659 /* {a is a one-dimensional array} */
661 if (valuevftbl == elementvftbl)
664 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
666 if ((base = classvalues.super_baseval) <= 0)
667 /* an array of interface references */
668 return (valuevftbl->interfacetablelength > -base &&
669 valuevftbl->interfacetable[base] != NULL);
671 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
672 <= (unsigned) classvalues.super_diffval;
678 /* This is an optimized version where a is guaranteed to be a
679 * one-dimensional array of a class type */
680 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
682 vftbl_t *elementvftbl;
685 castinfo classvalues;
689 /* The following is guaranteed (by verifier checks):
691 * *) a->...vftbl->arraydesc != NULL
692 * *) a->...vftbl->arraydesc->elementvftbl != NULL
693 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
694 * *) a->...vftbl->arraydesc->dimension == 1
695 * *) o->vftbl is not an interface vftbl
698 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
699 valuevftbl = o->vftbl;
701 /* {a is a one-dimensional array} */
703 if (valuevftbl == elementvftbl)
706 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
708 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
709 <= (unsigned) classvalues.super_diffval;
715 /* builtin_new *****************************************************************
717 Creates a new instance of class c on the heap.
719 Return value: pointer to the object or NULL if no memory is
722 *******************************************************************************/
724 java_objectheader *builtin_new(classinfo *c)
726 java_objectheader *o;
728 /* is the class loaded */
730 assert(c->state & CLASS_LOADED);
732 /* check if we can instantiate this class */
734 if (c->flags & ACC_ABSTRACT) {
736 new_exception_utfmessage(string_java_lang_InstantiationError,
741 /* is the class linked */
743 if (!(c->state & CLASS_LINKED))
747 if (!(c->state & CLASS_INITIALIZED)) {
749 log_message_class("Initialize class (from builtin_new): ", c);
751 if (!initialize_class(c))
755 o = heap_allocate(c->instancesize, true, c->finalizer);
762 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
770 /* builtin_newarray ************************************************************
772 Creates an array with the given vftbl on the heap. This function
773 takes as class argument an array class.
775 Return value: pointer to the array or NULL if no memory is available
777 *******************************************************************************/
779 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
781 arraydescriptor *desc;
787 desc = arrayclass->vftbl->arraydesc;
788 dataoffset = desc->dataoffset;
789 componentsize = desc->componentsize;
792 *exceptionptr = new_negativearraysizeexception();
796 actualsize = dataoffset + size * componentsize;
798 if (((u4) actualsize) < ((u4) size)) { /* overflow */
799 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
803 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
808 a->objheader.vftbl = arrayclass->vftbl;
810 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
811 initObjectLock(&a->objheader);
820 /* builtin_anewarray ***********************************************************
822 Creates an array of references to the given class type on the heap.
824 Return value: pointer to the array or NULL if no memory is
827 *******************************************************************************/
829 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
831 classinfo *arrayclass;
833 /* is class loaded */
835 assert(componentclass->state & CLASS_LOADED);
837 /* is class linked */
839 if (!(componentclass->state & CLASS_LINKED))
840 if (!link_class(componentclass))
843 arrayclass = class_array_of(componentclass, true);
848 return (java_objectarray *) builtin_newarray(size, arrayclass);
852 /* builtin_newarray_boolean ****************************************************
854 Creates an array of bytes on the heap. The array is designated as
855 an array of booleans (important for casts)
857 Return value: pointer to the array or NULL if no memory is
860 *******************************************************************************/
862 java_booleanarray *builtin_newarray_boolean(s4 size)
864 return (java_booleanarray *)
865 builtin_newarray(size,
866 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
870 /* builtin_newarray_byte *******************************************************
872 Creates an array of 8 bit Integers on the heap.
874 Return value: pointer to the array or NULL if no memory is
877 *******************************************************************************/
879 java_bytearray *builtin_newarray_byte(s4 size)
881 return (java_bytearray *)
882 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
886 /* builtin_newarray_char *******************************************************
888 Creates an array of characters on the heap.
890 Return value: pointer to the array or NULL if no memory is
893 *******************************************************************************/
895 java_chararray *builtin_newarray_char(s4 size)
897 return (java_chararray *)
898 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
902 /* builtin_newarray_short ******************************************************
904 Creates an array of 16 bit Integers on the heap.
906 Return value: pointer to the array or NULL if no memory is
909 *******************************************************************************/
911 java_shortarray *builtin_newarray_short(s4 size)
913 return (java_shortarray *)
914 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
918 /* builtin_newarray_int ********************************************************
920 Creates an array of 32 bit Integers on the heap.
922 Return value: pointer to the array or NULL if no memory is
925 *******************************************************************************/
927 java_intarray *builtin_newarray_int(s4 size)
929 return (java_intarray *)
930 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
934 /* builtin_newarray_long *******************************************************
936 Creates an array of 64 bit Integers on the heap.
938 Return value: pointer to the array or NULL if no memory is
941 *******************************************************************************/
943 java_longarray *builtin_newarray_long(s4 size)
945 return (java_longarray *)
946 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
950 /* builtin_newarray_float ******************************************************
952 Creates an array of 32 bit IEEE floats on the heap.
954 Return value: pointer to the array or NULL if no memory is
957 *******************************************************************************/
959 java_floatarray *builtin_newarray_float(s4 size)
961 return (java_floatarray *)
962 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
966 /* builtin_newarray_double *****************************************************
968 Creates an array of 64 bit IEEE floats on the heap.
970 Return value: pointer to the array or NULL if no memory is
973 *******************************************************************************/
975 java_doublearray *builtin_newarray_double(s4 size)
977 return (java_doublearray *)
978 builtin_newarray(size,
979 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
983 /* builtin_multianewarray_intern ***********************************************
985 Creates a multi-dimensional array on the heap. The dimensions are
986 passed in an array of longs.
989 n............number of dimensions to create
990 arrayvftbl...vftbl of the array class
991 dims.........array containing the size of each dimension to create
993 Return value: pointer to the array or NULL if no memory is
996 ******************************************************************************/
998 static java_arrayheader *builtin_multianewarray_intern(int n,
999 classinfo *arrayclass,
1003 java_arrayheader *a;
1004 classinfo *componentclass;
1007 /* create this dimension */
1009 size = (s4) dims[0];
1010 a = builtin_newarray(size, arrayclass);
1015 /* if this is the last dimension return */
1020 /* get the class of the components to create */
1022 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1024 /* The verifier guarantees that the dimension count is in the range. */
1026 /* create the component arrays */
1028 for (i = 0; i < size; i++) {
1029 java_arrayheader *ea =
1030 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1031 /* we save an s4 to a s8 slot, 8-byte aligned */
1033 builtin_multianewarray_intern(n, componentclass, dims + 2);
1035 builtin_multianewarray_intern(n, componentclass, dims + 1);
1041 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1048 /* builtin_multianewarray ******************************************************
1050 Wrapper for builtin_multianewarray_intern which checks all
1051 dimensions before we start allocating.
1053 ******************************************************************************/
1055 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1061 /* check all dimensions before doing anything */
1063 for (i = 0; i < n; i++) {
1064 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1065 /* we save an s4 to a s8 slot, 8-byte aligned */
1066 size = (s4) dims[i * 2];
1068 size = (s4) dims[i];
1072 *exceptionptr = new_negativearraysizeexception();
1077 /* now call the real function */
1079 return builtin_multianewarray_intern(n, arrayclass, dims);
1083 /*****************************************************************************
1086 Various functions for printing a message at method entry or exit (for
1089 *****************************************************************************/
1091 s4 methodindent = 0;
1093 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1102 if (runverbose && indent)
1105 /* calculate message length */
1109 strlen("Exception ") +
1110 utf_strlen(xptr->vftbl->class->name);
1113 logtextlen = strlen("Some Throwable");
1116 logtextlen += strlen(" thrown in ");
1120 utf_strlen(m->class->name) +
1122 utf_strlen(m->name) +
1123 utf_strlen(m->descriptor) +
1124 strlen("(NOSYNC,NATIVE");
1126 #if SIZEOF_VOID_P == 8
1128 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1130 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1133 if (m->class->sourcefile == NULL)
1134 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1136 logtextlen += utf_strlen(m->class->sourcefile);
1138 logtextlen += strlen(":65536)");
1141 logtextlen += strlen("call_java_method");
1143 logtextlen += strlen("0");
1145 /* allocate memory */
1147 dumpsize = dump_size();
1149 logtext = DMNEW(char, logtextlen);
1152 strcpy(logtext, "Exception ");
1153 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1156 strcpy(logtext, "Some Throwable");
1159 strcat(logtext, " thrown in ");
1162 utf_strcat_classname(logtext, m->class->name);
1163 strcat(logtext, ".");
1164 utf_strcat(logtext, m->name);
1165 utf_strcat(logtext, m->descriptor);
1167 if (m->flags & ACC_SYNCHRONIZED)
1168 strcat(logtext, "(SYNC");
1170 strcat(logtext, "(NOSYNC");
1172 if (m->flags & ACC_NATIVE) {
1173 strcat(logtext, ",NATIVE");
1175 #if SIZEOF_VOID_P == 8
1176 sprintf(logtext + strlen(logtext),
1177 ")(0x%016lx) at position 0x%016lx",
1178 (ptrint) m->entrypoint, (ptrint) pos);
1180 sprintf(logtext + strlen(logtext),
1181 ")(0x%08x) at position 0x%08x",
1182 (ptrint) m->entrypoint, (ptrint) pos);
1186 #if SIZEOF_VOID_P == 8
1187 sprintf(logtext + strlen(logtext),
1188 ")(0x%016lx) at position 0x%016lx (",
1189 (ptrint) m->entrypoint, (ptrint) pos);
1191 sprintf(logtext + strlen(logtext),
1192 ")(0x%08x) at position 0x%08x (",
1193 (ptrint) m->entrypoint, (ptrint) pos);
1196 if (m->class->sourcefile == NULL)
1197 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1199 utf_strcat(logtext, m->class->sourcefile);
1201 sprintf(logtext + strlen(logtext), ":%d)", 0);
1205 strcat(logtext, "call_java_method");
1209 /* release memory */
1211 dump_release(dumpsize);
1213 /* print stacktrace for exception */
1215 if (opt_verboseexception) {
1216 exceptions_print_exception(xptr);
1217 stacktrace_print_trace(xptr);
1224 /* builtin_trace_args **********************************************************
1228 *******************************************************************************/
1230 #ifdef TRACE_ARGS_NUM
1231 void builtin_trace_args(s8 a0, s8 a1,
1232 #if TRACE_ARGS_NUM >= 4
1234 #endif /* TRACE_ARGS_NUM >= 4 */
1235 #if TRACE_ARGS_NUM >= 6
1237 #endif /* TRACE_ARGS_NUM >= 6 */
1238 #if TRACE_ARGS_NUM == 8
1240 #endif /* TRACE_ARGS_NUM == 8 */
1252 /* calculate message length */
1255 6 + methodindent + strlen("called: ") +
1256 utf_strlen(m->class->name) +
1258 utf_strlen(m->name) +
1259 utf_strlen(m->descriptor) +
1260 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1262 /* add maximal argument length */
1264 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1266 /* allocate memory */
1268 dumpsize = dump_size();
1270 logtext = DMNEW(char, logtextlen);
1272 sprintf(logtext,"-%d-",methodindent);
1273 pos = strlen(logtext);
1275 for (i = 0; i < methodindent; i++)
1276 logtext[pos++] = '\t';
1278 strcpy(logtext + pos, "called: ");
1280 utf_strcat_classname(logtext, m->class->name);
1281 strcat(logtext, ".");
1282 utf_strcat(logtext, m->name);
1283 utf_strcat(logtext, m->descriptor);
1285 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1286 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1287 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1288 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1289 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1290 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1291 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1292 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1293 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1294 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1295 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1297 strcat(logtext, "(");
1299 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1300 /* Only Arguments in integer Registers are passed correctly here */
1301 /* long longs spilled on Stack have an wrong offset of +4 */
1302 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1303 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1304 switch (md->paramcount) {
1308 #if SIZEOF_VOID_P == 4
1310 sprintf(logtext + strlen(logtext),
1316 sprintf(logtext + strlen(logtext),
1321 #if TRACE_ARGS_NUM >= 4
1323 sprintf(logtext + strlen(logtext),
1324 "0x%llx, 0x%llx, 0x%llx",
1329 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1331 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1334 #endif /* TRACE_ARGS_NUM >= 4 */
1336 #if TRACE_ARGS_NUM >= 6
1338 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1340 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1345 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1347 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1350 #endif /* TRACE_ARGS_NUM >= 6 */
1352 #if TRACE_ARGS_NUM == 8
1354 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1356 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1358 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1362 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1364 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1366 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1368 #endif /* TRACE_ARGS_NUM == 8 */
1371 #if TRACE_ARGS_NUM == 2
1372 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1374 #elif TRACE_ARGS_NUM == 4
1375 sprintf(logtext + strlen(logtext),
1376 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1377 a0, a1, a2, a3, md->paramcount - 4);
1379 #elif TRACE_ARGS_NUM == 6
1380 sprintf(logtext + strlen(logtext),
1381 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1382 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1384 #elif TRACE_ARGS_NUM == 8
1385 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1387 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1389 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1390 , a6, a7, md->paramcount - 8);
1394 #else /* SIZEOF_VOID_P == 4 */
1397 sprintf(logtext + strlen(logtext),
1403 sprintf(logtext + strlen(logtext),
1409 sprintf(logtext + strlen(logtext),
1410 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1414 sprintf(logtext + strlen(logtext),
1415 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1419 #if TRACE_ARGS_NUM >= 6
1421 sprintf(logtext + strlen(logtext),
1422 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1423 a0, a1, a2, a3, a4);
1427 sprintf(logtext + strlen(logtext),
1428 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1429 a0, a1, a2, a3, a4, a5);
1431 #endif /* TRACE_ARGS_NUM >= 6 */
1433 #if TRACE_ARGS_NUM == 8
1435 sprintf(logtext + strlen(logtext),
1436 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1437 a0, a1, a2, a3, a4, a5, a6);
1441 sprintf(logtext + strlen(logtext),
1442 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1443 a0, a1, a2, a3, a4, a5, a6, a7);
1445 #endif /* TRACE_ARGS_NUM == 8 */
1448 #if TRACE_ARGS_NUM == 4
1449 sprintf(logtext + strlen(logtext),
1450 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1451 a0, a1, a2, a3, md->paramcount - 4);
1453 #elif TRACE_ARGS_NUM == 6
1454 sprintf(logtext + strlen(logtext),
1455 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1456 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1458 #elif TRACE_ARGS_NUM == 8
1459 sprintf(logtext + strlen(logtext),
1460 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1461 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1464 #endif /* SIZEOF_VOID_P == 4 */
1467 strcat(logtext, ")");
1471 /* release memory */
1473 dump_release(dumpsize);
1480 /* builtin_displaymethodstop ***************************************************
1484 *******************************************************************************/
1486 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1494 java_objectheader *o;
1495 java_lang_String *s;
1503 /* calculate message length */
1506 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1508 strlen("finished: ") +
1509 utf_strlen(m->class->name) +
1511 utf_strlen(m->name) +
1512 utf_strlen(m->descriptor) +
1513 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1515 /* add maximal argument length */
1517 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1519 /* allocate memory */
1521 dumpsize = dump_size();
1523 logtext = DMNEW(char, logtextlen);
1525 /* outdent the log message */
1530 log_text("WARNING: unmatched methodindent--");
1532 /* generate the message */
1534 sprintf(logtext, "-%d-", methodindent);
1536 pos = strlen(logtext);
1538 for (i = 0; i < methodindent; i++)
1539 logtext[pos++] = '\t';
1541 strcpy(logtext + pos, "finished: ");
1542 utf_strcat_classname(logtext, m->class->name);
1543 strcat(logtext, ".");
1544 utf_strcat(logtext, m->name);
1545 utf_strcat(logtext, m->descriptor);
1547 switch (md->returntype.type) {
1549 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1553 #if SIZEOF_VOID_P == 4
1554 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1556 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1561 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1563 /* check return argument for java.lang.Class or java.lang.String */
1565 o = (java_objectheader *) (ptrint) l;
1568 if (o->vftbl->class == class_java_lang_String) {
1569 /* get java.lang.String object and the length of the
1572 s= (java_lang_String *) (ptrint) l;
1574 len = strlen(", String = \"") + javastring_strlen(s) +
1577 /* realloc memory for string length */
1579 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1581 /* convert to utf8 string and strcat it to the logtext */
1583 u = javastring_toutf(s, false);
1585 strcat(logtext, ", String = \"");
1586 utf_strcat(logtext, u);
1587 strcat(logtext, "\"");
1590 if (o->vftbl->class == class_java_lang_Class) {
1591 /* if the object returned is a java.lang.Class
1592 cast it to classinfo structure and get the name
1595 c = (classinfo *) (ptrint) l;
1600 /* if the object returned is not a java.lang.String or
1601 a java.lang.Class just print the name of the class */
1603 u = o->vftbl->class->name;
1606 len = strlen(", Class = \"") + utf_strlen(u) + strlen("\"");
1608 /* realloc memory for string length */
1610 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1612 /* strcat to the logtext */
1614 strcat(logtext, ", Class = \"");
1615 utf_strcat(logtext, u);
1616 strcat(logtext, "\"");
1623 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1628 #if SIZEOF_VOID_P == 4
1629 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1631 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1638 /* release memory */
1640 dump_release(dumpsize);
1644 /****************************************************************************
1645 SYNCHRONIZATION FUNCTIONS
1646 *****************************************************************************/
1648 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1650 * Lock the mutex of an object.
1652 void internal_lock_mutex_for_object(java_objectheader *object)
1654 mutexHashEntry *entry;
1657 assert(object != 0);
1659 hashValue = MUTEX_HASH_VALUE(object);
1660 entry = &mutexHashTable[hashValue];
1662 if (entry->object != 0) {
1663 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1665 entry->mutex.holder = 0;
1666 entry->mutex.count = 0;
1667 entry->mutex.muxWaiters = 0;
1670 while (entry->next != 0 && entry->object != object)
1671 entry = entry->next;
1673 if (entry->object != object) {
1674 entry->next = firstFreeOverflowEntry;
1675 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1677 entry = entry->next;
1680 assert(entry->conditionCount == 0);
1685 entry->mutex.holder = 0;
1686 entry->mutex.count = 0;
1687 entry->mutex.muxWaiters = 0;
1690 if (entry->object == 0)
1691 entry->object = object;
1693 internal_lock_mutex(&entry->mutex);
1698 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1700 * Unlocks the mutex of an object.
1702 void internal_unlock_mutex_for_object (java_objectheader *object)
1705 mutexHashEntry *entry;
1707 hashValue = MUTEX_HASH_VALUE(object);
1708 entry = &mutexHashTable[hashValue];
1710 if (entry->object == object) {
1711 internal_unlock_mutex(&entry->mutex);
1714 while (entry->next != 0 && entry->next->object != object)
1715 entry = entry->next;
1717 assert(entry->next != 0);
1719 internal_unlock_mutex(&entry->next->mutex);
1721 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1722 mutexHashEntry *unlinked = entry->next;
1724 entry->next = unlinked->next;
1725 unlinked->next = firstFreeOverflowEntry;
1726 firstFreeOverflowEntry = unlinked;
1733 #if defined(USE_THREADS)
1734 void builtin_monitorenter(java_objectheader *o)
1736 #if !defined(NATIVE_THREADS)
1741 hashValue = MUTEX_HASH_VALUE(o);
1742 if (mutexHashTable[hashValue].object == o
1743 && mutexHashTable[hashValue].mutex.holder == currentThread)
1744 ++mutexHashTable[hashValue].mutex.count;
1746 internal_lock_mutex_for_object(o);
1750 monitorEnter((threadobject *) THREADOBJECT, o);
1756 #if defined(USE_THREADS)
1758 * Locks the class object - needed for static synchronized methods.
1760 void builtin_staticmonitorenter(classinfo *c)
1762 builtin_monitorenter(&c->object.header);
1767 #if defined(USE_THREADS)
1768 void builtin_monitorexit(java_objectheader *o)
1770 #if !defined(NATIVE_THREADS)
1775 hashValue = MUTEX_HASH_VALUE(o);
1776 if (mutexHashTable[hashValue].object == o) {
1777 if (mutexHashTable[hashValue].mutex.count == 1
1778 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1779 internal_unlock_mutex_for_object(o);
1781 --mutexHashTable[hashValue].mutex.count;
1784 internal_unlock_mutex_for_object(o);
1788 monitorExit((threadobject *) THREADOBJECT, o);
1794 /*****************************************************************************
1795 MISCELLANEOUS HELPER FUNCTIONS
1796 *****************************************************************************/
1800 /*********** Functions for integer divisions *****************************
1802 On some systems (eg. DEC ALPHA), integer division is not supported by the
1803 CPU. These helper functions implement the missing functionality.
1805 ******************************************************************************/
1807 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1808 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1811 /************** Functions for long arithmetics *******************************
1813 On systems where 64 bit Integers are not supported by the CPU, these
1814 functions are needed.
1816 ******************************************************************************/
1818 s8 builtin_ladd(s8 a, s8 b)
1831 s8 builtin_lsub(s8 a, s8 b)
1844 s8 builtin_lmul(s8 a, s8 b)
1857 s8 builtin_ldiv(s8 a, s8 b)
1870 s8 builtin_lrem(s8 a, s8 b)
1883 s8 builtin_lshl(s8 a, s4 b)
1896 s8 builtin_lshr(s8 a, s4 b)
1909 s8 builtin_lushr(s8 a, s4 b)
1914 c = ((u8) a) >> (b & 63);
1922 s8 builtin_land(s8 a, s8 b)
1935 s8 builtin_lor(s8 a, s8 b)
1948 s8 builtin_lxor(s8 a, s8 b)
1961 s8 builtin_lneg(s8 a)
1974 s4 builtin_lcmp(s8 a, s8 b)
1977 if (a < b) return -1;
1978 if (a > b) return 1;
1989 /*********** Functions for floating point operations *************************/
1991 /* used to convert FLT_xxx defines into float values */
1993 static inline float intBitsToFloat(s4 i)
2002 /* used to convert DBL_xxx defines into double values */
2004 static inline float longBitsToDouble(s8 l)
2013 float builtin_fadd(float a, float b)
2015 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2016 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2027 if (copysignf(1.0, a) == copysignf(1.0, b))
2030 return intBitsToFloat(FLT_NAN);
2036 float builtin_fsub(float a, float b)
2038 return builtin_fadd(a, builtin_fneg(b));
2042 float builtin_fmul(float a, float b)
2044 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2045 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2047 if (finitef(b)) return a * b;
2049 if (a == 0) return intBitsToFloat(FLT_NAN);
2050 else return copysignf(b, copysignf(1.0, b)*a);
2055 if (b == 0) return intBitsToFloat(FLT_NAN);
2056 else return copysignf(a, copysignf(1.0, a)*b);
2059 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2065 /* builtin_ddiv ****************************************************************
2067 Implementation as described in VM Spec.
2069 *******************************************************************************/
2071 float builtin_fdiv(float a, float b)
2075 /* If neither value1' nor value2' is NaN, the sign of the result */
2076 /* is positive if both values have the same sign, negative if the */
2077 /* values have different signs. */
2083 /* If either value1' or value2' is NaN, the result is NaN. */
2085 return intBitsToFloat(FLT_NAN);
2088 /* Division of a finite value by an infinity results in a */
2089 /* signed zero, with the sign-producing rule just given. */
2091 /* is sign equal? */
2093 if (copysignf(1.0, a) == copysignf(1.0, b))
2102 /* If either value1' or value2' is NaN, the result is NaN. */
2104 return intBitsToFloat(FLT_NAN);
2106 } else if (finitef(b)) {
2107 /* Division of an infinity by a finite value results in a signed */
2108 /* infinity, with the sign-producing rule just given. */
2110 /* is sign equal? */
2112 if (copysignf(1.0, a) == copysignf(1.0, b))
2113 return intBitsToFloat(FLT_POSINF);
2115 return intBitsToFloat(FLT_NEGINF);
2118 /* Division of an infinity by an infinity results in NaN. */
2120 return intBitsToFloat(FLT_NAN);
2126 float builtin_frem(float a, float b)
2132 float builtin_fneg(float a)
2134 if (isnanf(a)) return a;
2136 if (finitef(a)) return -a;
2137 else return copysignf(a, -copysignf(1.0, a));
2142 s4 builtin_fcmpl(float a, float b)
2144 if (isnanf(a)) return -1;
2145 if (isnanf(b)) return -1;
2146 if (!finitef(a) || !finitef(b)) {
2147 a = finitef(a) ? 0 : copysignf(1.0, a);
2148 b = finitef(b) ? 0 : copysignf(1.0, b);
2150 if (a > b) return 1;
2151 if (a == b) return 0;
2156 s4 builtin_fcmpg(float a, float b)
2158 if (isnanf(a)) return 1;
2159 if (isnanf(b)) return 1;
2160 if (!finitef(a) || !finitef(b)) {
2161 a = finitef(a) ? 0 : copysignf(1.0, a);
2162 b = finitef(b) ? 0 : copysignf(1.0, b);
2164 if (a > b) return 1;
2165 if (a == b) return 0;
2171 /************************* Functions for doubles ****************************/
2173 double builtin_dadd(double a, double b)
2175 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2176 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2178 if (finite(b)) return a + b;
2182 if (finite(b)) return a;
2184 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2185 else return longBitsToDouble(DBL_NAN);
2191 double builtin_dsub(double a, double b)
2193 return builtin_dadd(a, builtin_dneg(b));
2197 double builtin_dmul(double a, double b)
2199 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2200 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2202 if (finite(b)) return a * b;
2204 if (a == 0) return longBitsToDouble(DBL_NAN);
2205 else return copysign(b, copysign(1.0, b) * a);
2210 if (b == 0) return longBitsToDouble(DBL_NAN);
2211 else return copysign(a, copysign(1.0, a) * b);
2214 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2220 /* builtin_ddiv ****************************************************************
2222 Implementation as described in VM Spec.
2224 *******************************************************************************/
2226 double builtin_ddiv(double a, double b)
2230 /* If neither value1' nor value2' is NaN, the sign of the result */
2231 /* is positive if both values have the same sign, negative if the */
2232 /* values have different signs. */
2238 /* If either value1' or value2' is NaN, the result is NaN. */
2240 return longBitsToDouble(DBL_NAN);
2243 /* Division of a finite value by an infinity results in a */
2244 /* signed zero, with the sign-producing rule just given. */
2246 /* is sign equal? */
2248 if (copysign(1.0, a) == copysign(1.0, b))
2257 /* If either value1' or value2' is NaN, the result is NaN. */
2259 return longBitsToDouble(DBL_NAN);
2261 } else if (finite(b)) {
2262 /* Division of an infinity by a finite value results in a signed */
2263 /* infinity, with the sign-producing rule just given. */
2265 /* is sign equal? */
2267 if (copysign(1.0, a) == copysign(1.0, b))
2268 return longBitsToDouble(DBL_POSINF);
2270 return longBitsToDouble(DBL_NEGINF);
2273 /* Division of an infinity by an infinity results in NaN. */
2275 return longBitsToDouble(DBL_NAN);
2281 double builtin_drem(double a, double b)
2286 /* builtin_dneg ****************************************************************
2288 Implemented as described in VM Spec.
2290 *******************************************************************************/
2292 double builtin_dneg(double a)
2295 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2302 /* If the operand is a zero, the result is the zero of opposite */
2308 /* If the operand is an infinity, the result is the infinity of */
2309 /* opposite sign. */
2311 return copysign(a, -copysign(1.0, a));
2317 s4 builtin_dcmpl(double a, double b)
2319 if (isnan(a)) return -1;
2320 if (isnan(b)) return -1;
2321 if (!finite(a) || !finite(b)) {
2322 a = finite(a) ? 0 : copysign(1.0, a);
2323 b = finite(b) ? 0 : copysign(1.0, b);
2325 if (a > b) return 1;
2326 if (a == b) return 0;
2331 s4 builtin_dcmpg(double a, double b)
2333 if (isnan(a)) return 1;
2334 if (isnan(b)) return 1;
2335 if (!finite(a) || !finite(b)) {
2336 a = finite(a) ? 0 : copysign(1.0, a);
2337 b = finite(b) ? 0 : copysign(1.0, b);
2339 if (a > b) return 1;
2340 if (a == b) return 0;
2345 /*********************** Conversion operations ****************************/
2347 s8 builtin_i2l(s4 i)
2360 float builtin_i2f(s4 a)
2362 float f = (float) a;
2367 double builtin_i2d(s4 a)
2369 double d = (double) a;
2374 s4 builtin_l2i(s8 l)
2384 float builtin_l2f(s8 a)
2387 float f = (float) a;
2395 double builtin_l2d(s8 a)
2398 double d = (double) a;
2406 s4 builtin_f2i(float a)
2410 i = builtin_d2i((double) a);
2421 if (a < (-2147483648))
2422 return (-2147483648);
2425 f = copysignf((float) 1.0, a);
2428 return (-2147483648); */
2432 s8 builtin_f2l(float a)
2436 l = builtin_d2l((double) a);
2443 if (a > 9223372036854775807L)
2444 return 9223372036854775807L;
2445 if (a < (-9223372036854775808L))
2446 return (-9223372036854775808L);
2451 f = copysignf((float) 1.0, a);
2453 return 9223372036854775807L;
2454 return (-9223372036854775808L); */
2458 double builtin_f2d(float a)
2460 if (finitef(a)) return (double) a;
2463 return longBitsToDouble(DBL_NAN);
2465 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2470 s4 builtin_d2i(double a)
2475 if (a >= 2147483647)
2477 if (a <= (-2147483647-1))
2478 return (-2147483647-1);
2483 d = copysign(1.0, a);
2486 return (-2147483647-1);
2490 s8 builtin_d2l(double a)
2495 if (a >= 9223372036854775807LL)
2496 return 9223372036854775807LL;
2497 if (a <= (-9223372036854775807LL-1))
2498 return (-9223372036854775807LL-1);
2503 d = copysign(1.0, a);
2505 return 9223372036854775807LL;
2506 return (-9223372036854775807LL-1);
2510 float builtin_d2f(double a)
2516 return intBitsToFloat(FLT_NAN);
2518 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2523 /* builtin_clone_array *********************************************************
2525 Wrapper function for cloning arrays.
2527 *******************************************************************************/
2529 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2531 java_arrayheader *ah;
2532 java_lang_Cloneable *c;
2534 c = (java_lang_Cloneable *) o;
2536 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2542 /* builtin_asm_get_exceptionptrptr *********************************************
2544 this is a wrapper for calls from asmpart
2546 *******************************************************************************/
2548 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2549 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2551 return builtin_get_exceptionptrptr();
2557 * These are local overrides for various environment variables in Emacs.
2558 * Please do not remove this and leave it at the end of the file, where
2559 * Emacs will automagically detect them.
2560 * ---------------------------------------------------------------------
2563 * indent-tabs-mode: t