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 3654 2005-11-11 11:17:33Z twisti $
54 #include "fdlibm/fdlibm.h"
57 #include "mm/memory.h"
58 #include "native/native.h"
59 #include "native/include/java_lang_Cloneable.h"
60 #include "native/include/java_lang_Object.h" /* required by VMObject */
61 #include "native/include/java_lang_VMObject.h"
63 #if defined(USE_THREADS)
64 # if defined(NATIVE_THREADS)
65 # include "threads/native/threads.h"
67 # include "threads/green/threads.h"
68 # include "threads/green/locks.h"
72 #include "toolbox/logging.h"
73 #include "toolbox/util.h"
74 #include "vm/builtin.h"
75 #include "vm/exceptions.h"
76 #include "vm/global.h"
77 #include "vm/initialize.h"
78 #include "vm/loader.h"
79 #include "vm/options.h"
80 #include "vm/stringlocal.h"
81 #include "vm/tables.h"
82 #include "vm/jit/asmpart.h"
83 #include "vm/jit/patcher.h"
86 /* include builtin tables *****************************************************/
88 #include "vm/builtintable.inc"
91 /* builtintable_init ***********************************************************
93 Parse the descriptors of builtin functions and create the parsed
96 *******************************************************************************/
98 static bool builtintable_init(void)
100 descriptor_pool *descpool;
104 s4 entries_automatic;
107 /* mark start of dump memory area */
109 dumpsize = dump_size();
111 /* create a new descriptor pool */
113 descpool = descriptor_pool_new(class_java_lang_Object);
115 /* add some entries we need */
117 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
120 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
123 /* calculate table entries statically */
126 sizeof(builtintable_internal) / sizeof(builtintable_entry);
129 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
130 - 1; /* last filler entry (comment see builtintable.inc) */
132 /* first add all descriptors to the pool */
134 for (i = 0; i < entries_internal; i++) {
135 /* create a utf8 string from descriptor */
137 descriptor = utf_new_char(builtintable_internal[i].descriptor);
139 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
140 /* release dump area */
142 dump_release(dumpsize);
148 for (i = 0; i < entries_automatic; i++) {
149 /* create a utf8 string from descriptor */
151 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
153 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
154 /* release dump area */
156 dump_release(dumpsize);
162 /* create the class reference table */
164 (void) descriptor_pool_create_classrefs(descpool, NULL);
166 /* allocate space for the parsed descriptors */
168 descriptor_pool_alloc_parsed_descriptors(descpool);
170 /* now parse all descriptors */
172 for (i = 0; i < entries_internal; i++) {
173 /* create a utf8 string from descriptor */
175 descriptor = utf_new_char(builtintable_internal[i].descriptor);
177 /* parse the descriptor, builtin is always static (no `this' pointer) */
179 builtintable_internal[i].md =
180 descriptor_pool_parse_method_descriptor(descpool, descriptor,
184 for (i = 0; i < entries_automatic; i++) {
185 /* create a utf8 string from descriptor */
187 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
189 /* parse the descriptor, builtin is always static (no `this' pointer) */
191 builtintable_automatic[i].md =
192 descriptor_pool_parse_method_descriptor(descpool, descriptor,
196 /* release dump area */
198 dump_release(dumpsize);
204 /* builtintable_comparator *****************************************************
206 qsort comparator for the automatic builtin table.
208 *******************************************************************************/
210 static int builtintable_comparator(const void *a, const void *b)
212 builtintable_entry *bte1;
213 builtintable_entry *bte2;
215 bte1 = (builtintable_entry *) a;
216 bte2 = (builtintable_entry *) b;
218 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
222 /* builtintable_sort_automatic *************************************************
224 Sorts the automatic builtin table.
226 *******************************************************************************/
228 static void builtintable_sort_automatic(void)
232 /* calculate table size statically (`- 1' comment see builtintable.inc) */
234 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
236 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
237 builtintable_comparator);
241 /* builtin_init ****************************************************************
245 *******************************************************************************/
247 bool builtin_init(void)
249 /* initialize the builtin tables */
251 if (!builtintable_init())
254 /* sort builtin tables */
256 builtintable_sort_automatic();
262 /* builtintable_get_internal ***************************************************
264 Finds an entry in the builtintable for internal functions and
265 returns the a pointer to the structure.
267 *******************************************************************************/
269 builtintable_entry *builtintable_get_internal(functionptr fp)
273 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
274 if (builtintable_internal[i].fp == fp)
275 return &builtintable_internal[i];
282 /* builtintable_get_automatic **************************************************
284 Finds an entry in the builtintable for functions which are replaced
285 automatically and returns the a pointer to the structure.
287 *******************************************************************************/
289 builtintable_entry *builtintable_get_automatic(s4 opcode)
291 builtintable_entry *first;
292 builtintable_entry *last;
293 builtintable_entry *middle;
297 /* calculate table size statically (`- 1' comment see builtintable.inc) */
299 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
301 first = builtintable_automatic;
302 last = builtintable_automatic + entries;
304 while (entries > 0) {
306 middle = first + half;
308 if (middle->opcode < opcode) {
315 return (first != last ? first : NULL);
319 /*****************************************************************************
321 *****************************************************************************/
325 /*************** internal function: builtin_isanysubclass *********************
327 Checks a subclass relation between two classes. Implemented interfaces
328 are interpreted as super classes.
329 Return value: 1 ... sub is subclass of super
332 *****************************************************************************/
333 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
336 castinfo classvalues;
341 if (super->flags & ACC_INTERFACE) {
342 res = (sub->vftbl->interfacetablelength > super->index) &&
343 (sub->vftbl->interfacetable[-super->index] != NULL);
346 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
348 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
349 (u4) classvalues.super_diffval;
356 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
360 castinfo classvalues;
365 asm_getclassvalues_atomic(super, sub, &classvalues);
367 if ((base = classvalues.super_baseval) <= 0) {
368 /* super is an interface */
369 res = (sub->interfacetablelength > -base) &&
370 (sub->interfacetable[base] != NULL);
372 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
373 <= (u4) classvalues.super_diffval;
380 /****************** function: builtin_instanceof *****************************
382 Checks if an object is an instance of some given class (or subclass of
383 that class). If class is an interface, checks if the interface is
385 Return value: 1 ... obj is an instance of class or implements the interface
386 0 ... otherwise or if obj == NULL
388 *****************************************************************************/
390 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
395 return builtin_isanysubclass(obj->vftbl->class, class);
400 /**************** function: builtin_checkcast *******************************
402 The same as builtin_instanceof except that 1 is returned when
405 ****************************************************************************/
407 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
412 if (builtin_isanysubclass(obj->vftbl->class, class))
419 /* builtin_descriptorscompatible ***********************************************
421 Checks if two array type descriptors are assignment compatible
423 Return value: 1 ... target = desc is possible
426 *******************************************************************************/
428 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
429 arraydescriptor *target)
434 if (desc->arraytype != target->arraytype)
437 if (desc->arraytype != ARRAYTYPE_OBJECT)
440 /* {both arrays are arrays of references} */
442 if (desc->dimension == target->dimension) {
443 /* an array which contains elements of interface types is
444 allowed to be casted to Object (JOWENN)*/
446 if ((desc->elementvftbl->baseval < 0) &&
447 (target->elementvftbl->baseval == 1))
450 return builtin_isanysubclass_vftbl(desc->elementvftbl,
451 target->elementvftbl);
454 if (desc->dimension < target->dimension)
457 /* {desc has higher dimension than target} */
459 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
460 target->elementvftbl);
464 /* builtin_arraycheckcast ******************************************************
466 Checks if an object is really a subtype of the requested array
467 type. The object has to be an array to begin with. For simple
468 arrays (int, short, double, etc.) the types have to match exactly.
469 For arrays of objects, the type of elements in the array has to be
470 a subtype (or the same type) of the requested element type. For
471 arrays of arrays (which in turn can again be arrays of arrays), the
472 types at the lowest level have to satisfy the corresponding sub
475 *******************************************************************************/
477 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
479 arraydescriptor *desc;
484 if ((desc = o->vftbl->arraydesc) == NULL)
487 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
491 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
496 return builtin_arraycheckcast(o, targetclass);
500 /************************** exception functions *******************************
502 ******************************************************************************/
504 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
506 java_lang_Throwable *t;
512 t = (java_lang_Throwable *) xptr;
514 /* calculate message length */
516 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
520 utf_strlen(xptr->vftbl->class->name) +
522 javastring_strlen((java_objectheader *) t->detailMessage);
525 logtextlen += strlen("(nil)");
527 /* allocate memory */
529 dumpsize = dump_size();
531 logtext = DMNEW(char, logtextlen);
533 strcpy(logtext, "Builtin exception thrown: ");
536 utf_sprint_classname(logtext + strlen(logtext),
537 xptr->vftbl->class->name);
539 if (t->detailMessage) {
542 buf = javastring_tochar((java_objectheader *) t->detailMessage);
543 strcat(logtext, ": ");
544 strcat(logtext, buf);
545 MFREE(buf, char, strlen(buf));
549 strcat(logtext, "(nil)");
556 dump_release(dumpsize);
559 *exceptionptr = xptr;
566 /* builtin_canstore ************************************************************
568 Checks, if an object can be stored in an array.
570 Return value: 1 ... possible
573 *******************************************************************************/
575 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
577 arraydescriptor *desc;
578 arraydescriptor *valuedesc;
579 vftbl_t *componentvftbl;
582 castinfo classvalues;
587 /* The following is guaranteed (by verifier checks):
589 * *) a->...vftbl->arraydesc != NULL
590 * *) a->...vftbl->arraydesc->componentvftbl != NULL
591 * *) o->vftbl is not an interface vftbl
594 desc = oa->header.objheader.vftbl->arraydesc;
595 componentvftbl = desc->componentvftbl;
596 valuevftbl = o->vftbl;
598 if ((desc->dimension - 1) == 0) {
601 /* {a is a one-dimensional array} */
602 /* {a is an array of references} */
604 if (valuevftbl == componentvftbl)
607 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
609 if ((base = classvalues.super_baseval) <= 0)
610 /* an array of interface references */
611 return (valuevftbl->interfacetablelength > -base &&
612 valuevftbl->interfacetable[base] != NULL);
614 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
615 <= (unsigned) classvalues.super_diffval);
620 /* {a has dimension > 1} */
621 /* {componentvftbl->arraydesc != NULL} */
623 /* check if o is an array */
625 if ((valuedesc = valuevftbl->arraydesc) == NULL)
628 /* {o is an array} */
630 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
634 /* This is an optimized version where a is guaranteed to be one-dimensional */
635 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
637 arraydescriptor *desc;
638 vftbl_t *elementvftbl;
642 castinfo classvalues;
646 /* The following is guaranteed (by verifier checks):
648 * *) a->...vftbl->arraydesc != NULL
649 * *) a->...vftbl->arraydesc->elementvftbl != NULL
650 * *) a->...vftbl->arraydesc->dimension == 1
651 * *) o->vftbl is not an interface vftbl
654 desc = a->header.objheader.vftbl->arraydesc;
655 elementvftbl = desc->elementvftbl;
656 valuevftbl = o->vftbl;
658 /* {a is a one-dimensional array} */
660 if (valuevftbl == elementvftbl)
663 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
665 if ((base = classvalues.super_baseval) <= 0)
666 /* an array of interface references */
667 return (valuevftbl->interfacetablelength > -base &&
668 valuevftbl->interfacetable[base] != NULL);
670 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
671 <= (unsigned) classvalues.super_diffval;
677 /* This is an optimized version where a is guaranteed to be a
678 * one-dimensional array of a class type */
679 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
681 vftbl_t *elementvftbl;
684 castinfo classvalues;
688 /* The following is guaranteed (by verifier checks):
690 * *) a->...vftbl->arraydesc != NULL
691 * *) a->...vftbl->arraydesc->elementvftbl != NULL
692 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
693 * *) a->...vftbl->arraydesc->dimension == 1
694 * *) o->vftbl is not an interface vftbl
697 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
698 valuevftbl = o->vftbl;
700 /* {a is a one-dimensional array} */
702 if (valuevftbl == elementvftbl)
705 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
707 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
708 <= (unsigned) classvalues.super_diffval;
714 /* builtin_new *****************************************************************
716 Creates a new instance of class c on the heap.
718 Return value: pointer to the object or NULL if no memory is
721 *******************************************************************************/
723 java_objectheader *builtin_new(classinfo *c)
725 java_objectheader *o;
727 /* is the class loaded */
731 /* check if we can instantiate this class */
733 if (c->flags & ACC_ABSTRACT) {
735 new_exception_utfmessage(string_java_lang_InstantiationError,
740 /* is the class linked */
745 if (!c->initialized) {
747 log_message_class("Initialize class (from builtin_new): ", c);
749 if (!initialize_class(c))
753 o = heap_allocate(c->instancesize, true, c->finalizer);
760 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
768 /* builtin_newarray ************************************************************
770 Creates an array with the given vftbl on the heap. This function
771 takes as class argument an array class.
773 Return value: pointer to the array or NULL if no memory is available
775 *******************************************************************************/
777 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
779 arraydescriptor *desc;
785 desc = arrayclass->vftbl->arraydesc;
786 dataoffset = desc->dataoffset;
787 componentsize = desc->componentsize;
790 *exceptionptr = new_negativearraysizeexception();
794 actualsize = dataoffset + size * componentsize;
796 if (((u4) actualsize) < ((u4) size)) { /* overflow */
797 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
801 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
806 a->objheader.vftbl = arrayclass->vftbl;
808 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
809 initObjectLock(&a->objheader);
818 /* builtin_anewarray ***********************************************************
820 Creates an array of references to the given class type on the heap.
822 Return value: pointer to the array or NULL if no memory is
825 *******************************************************************************/
827 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
829 classinfo *arrayclass;
831 /* is class loaded */
833 assert(componentclass->loaded);
835 /* is class linked */
837 if (!componentclass->linked)
838 if (!link_class(componentclass))
841 arrayclass = class_array_of(componentclass, true);
846 return (java_objectarray *) builtin_newarray(size, arrayclass);
850 /* builtin_newarray_boolean ****************************************************
852 Creates an array of bytes on the heap. The array is designated as
853 an array of booleans (important for casts)
855 Return value: pointer to the array or NULL if no memory is
858 *******************************************************************************/
860 java_booleanarray *builtin_newarray_boolean(s4 size)
862 return (java_booleanarray *)
863 builtin_newarray(size,
864 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
868 /* builtin_newarray_byte *******************************************************
870 Creates an array of 8 bit Integers on the heap.
872 Return value: pointer to the array or NULL if no memory is
875 *******************************************************************************/
877 java_bytearray *builtin_newarray_byte(s4 size)
879 return (java_bytearray *)
880 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
884 /* builtin_newarray_char *******************************************************
886 Creates an array of characters on the heap.
888 Return value: pointer to the array or NULL if no memory is
891 *******************************************************************************/
893 java_chararray *builtin_newarray_char(s4 size)
895 return (java_chararray *)
896 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
900 /* builtin_newarray_short ******************************************************
902 Creates an array of 16 bit Integers on the heap.
904 Return value: pointer to the array or NULL if no memory is
907 *******************************************************************************/
909 java_shortarray *builtin_newarray_short(s4 size)
911 return (java_shortarray *)
912 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
916 /* builtin_newarray_int ********************************************************
918 Creates an array of 32 bit Integers on the heap.
920 Return value: pointer to the array or NULL if no memory is
923 *******************************************************************************/
925 java_intarray *builtin_newarray_int(s4 size)
927 return (java_intarray *)
928 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
932 /* builtin_newarray_long *******************************************************
934 Creates an array of 64 bit Integers on the heap.
936 Return value: pointer to the array or NULL if no memory is
939 *******************************************************************************/
941 java_longarray *builtin_newarray_long(s4 size)
943 return (java_longarray *)
944 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
948 /* builtin_newarray_float ******************************************************
950 Creates an array of 32 bit IEEE floats on the heap.
952 Return value: pointer to the array or NULL if no memory is
955 *******************************************************************************/
957 java_floatarray *builtin_newarray_float(s4 size)
959 return (java_floatarray *)
960 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
964 /* builtin_newarray_double *****************************************************
966 Creates an array of 64 bit IEEE floats on the heap.
968 Return value: pointer to the array or NULL if no memory is
971 *******************************************************************************/
973 java_doublearray *builtin_newarray_double(s4 size)
975 return (java_doublearray *)
976 builtin_newarray(size,
977 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
981 /* builtin_multianewarray_intern ***********************************************
983 Creates a multi-dimensional array on the heap. The dimensions are
984 passed in an array of longs.
987 n............number of dimensions to create
988 arrayvftbl...vftbl of the array class
989 dims.........array containing the size of each dimension to create
991 Return value: pointer to the array or NULL if no memory is
994 ******************************************************************************/
996 static java_arrayheader *builtin_multianewarray_intern(int n,
997 classinfo *arrayclass,
1001 java_arrayheader *a;
1002 classinfo *componentclass;
1005 /* create this dimension */
1007 size = (s4) dims[0];
1008 a = builtin_newarray(size, arrayclass);
1013 /* if this is the last dimension return */
1018 /* get the class of the components to create */
1020 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1022 /* The verifier guarantees that the dimension count is in the range. */
1024 /* create the component arrays */
1026 for (i = 0; i < size; i++) {
1027 java_arrayheader *ea =
1028 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1029 /* we save an s4 to a s8 slot, 8-byte aligned */
1031 builtin_multianewarray_intern(n, componentclass, dims + 2);
1033 builtin_multianewarray_intern(n, componentclass, dims + 1);
1039 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1046 /* builtin_multianewarray ******************************************************
1048 Wrapper for builtin_multianewarray_intern which checks all
1049 dimensions before we start allocating.
1051 ******************************************************************************/
1053 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1059 /* check all dimensions before doing anything */
1061 for (i = 0; i < n; i++) {
1062 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1063 /* we save an s4 to a s8 slot, 8-byte aligned */
1064 size = (s4) dims[i * 2];
1066 size = (s4) dims[i];
1070 *exceptionptr = new_negativearraysizeexception();
1075 /* now call the real function */
1077 return builtin_multianewarray_intern(n, arrayclass, dims);
1081 /*****************************************************************************
1084 Various functions for printing a message at method entry or exit (for
1087 *****************************************************************************/
1089 s4 methodindent = 0;
1091 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1100 if (opt_verbose || runverbose || opt_verboseexception) {
1101 /* when running with verbosecall we remove one indent level */
1103 if (runverbose && indent)
1106 /* calculate message length */
1110 strlen("Exception ") +
1111 utf_strlen(xptr->vftbl->class->name);
1114 logtextlen = strlen("Some Throwable");
1117 logtextlen += strlen(" thrown in ");
1121 utf_strlen(m->class->name) +
1123 utf_strlen(m->name) +
1124 utf_strlen(m->descriptor) +
1125 strlen("(NOSYNC,NATIVE");
1127 #if SIZEOF_VOID_P == 8
1129 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1131 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1134 if (m->class->sourcefile == NULL)
1135 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1137 logtextlen += utf_strlen(m->class->sourcefile);
1139 logtextlen += strlen(":65536)");
1142 logtextlen += strlen("call_java_method");
1144 logtextlen += strlen("0");
1146 /* allocate memory */
1148 dumpsize = dump_size();
1150 logtext = DMNEW(char, logtextlen);
1153 strcpy(logtext, "Exception ");
1154 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1157 strcpy(logtext, "Some Throwable");
1160 strcat(logtext, " thrown in ");
1163 utf_strcat_classname(logtext, m->class->name);
1164 strcat(logtext, ".");
1165 utf_strcat(logtext, m->name);
1166 utf_strcat(logtext, m->descriptor);
1168 if (m->flags & ACC_SYNCHRONIZED)
1169 strcat(logtext, "(SYNC");
1171 strcat(logtext, "(NOSYNC");
1173 if (m->flags & ACC_NATIVE) {
1174 strcat(logtext, ",NATIVE");
1176 #if SIZEOF_VOID_P == 8
1177 sprintf(logtext + strlen(logtext),
1178 ")(0x%016lx) at position 0x%016lx",
1179 (ptrint) m->entrypoint, (ptrint) pos);
1181 sprintf(logtext + strlen(logtext),
1182 ")(0x%08x) at position 0x%08x",
1183 (ptrint) m->entrypoint, (ptrint) pos);
1187 #if SIZEOF_VOID_P == 8
1188 sprintf(logtext + strlen(logtext),
1189 ")(0x%016lx) at position 0x%016lx (",
1190 (ptrint) m->entrypoint, (ptrint) pos);
1192 sprintf(logtext + strlen(logtext),
1193 ")(0x%08x) at position 0x%08x (",
1194 (ptrint) m->entrypoint, (ptrint) pos);
1197 if (m->class->sourcefile == NULL)
1198 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1200 utf_strcat(logtext, m->class->sourcefile);
1202 sprintf(logtext + strlen(logtext), ":%d)", 0);
1206 strcat(logtext, "call_java_method");
1210 /* release memory */
1212 dump_release(dumpsize);
1214 /* print stacktrace for exception */
1216 if (opt_verboseexception) {
1217 exceptions_print_exception(xptr);
1218 stacktrace_print_trace(xptr);
1226 /* builtin_trace_args **********************************************************
1230 *******************************************************************************/
1232 #ifdef TRACE_ARGS_NUM
1233 void builtin_trace_args(s8 a0, s8 a1,
1234 #if TRACE_ARGS_NUM >= 4
1236 #endif /* TRACE_ARGS_NUM >= 4 */
1237 #if TRACE_ARGS_NUM >= 6
1239 #endif /* TRACE_ARGS_NUM >= 6 */
1240 #if TRACE_ARGS_NUM == 8
1242 #endif /* TRACE_ARGS_NUM == 8 */
1254 /* calculate message length */
1257 6 + methodindent + strlen("called: ") +
1258 utf_strlen(m->class->name) +
1260 utf_strlen(m->name) +
1261 utf_strlen(m->descriptor) +
1262 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1264 /* add maximal argument length */
1266 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1268 /* allocate memory */
1270 dumpsize = dump_size();
1272 logtext = DMNEW(char, logtextlen);
1274 sprintf(logtext,"-%d-",methodindent);
1275 pos = strlen(logtext);
1277 for (i = 0; i < methodindent; i++)
1278 logtext[pos++] = '\t';
1280 strcpy(logtext + pos, "called: ");
1282 utf_strcat_classname(logtext, m->class->name);
1283 strcat(logtext, ".");
1284 utf_strcat(logtext, m->name);
1285 utf_strcat(logtext, m->descriptor);
1287 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1288 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1289 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1290 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1291 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1292 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1293 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1294 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1295 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1296 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1297 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1299 strcat(logtext, "(");
1301 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1302 /* Only Arguments in integer Registers are passed correctly here */
1303 /* long longs spilled on Stack have an wrong offset of +4 */
1304 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1305 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1306 switch (md->paramcount) {
1310 #if SIZEOF_VOID_P == 4
1312 sprintf(logtext + strlen(logtext),
1318 sprintf(logtext + strlen(logtext),
1323 #if TRACE_ARGS_NUM >= 4
1325 sprintf(logtext + strlen(logtext),
1326 "0x%llx, 0x%llx, 0x%llx",
1331 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1333 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1336 #endif /* TRACE_ARGS_NUM >= 4 */
1338 #if TRACE_ARGS_NUM >= 6
1340 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1342 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1347 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1349 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1352 #endif /* TRACE_ARGS_NUM >= 6 */
1354 #if TRACE_ARGS_NUM == 8
1356 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1358 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1360 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1364 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1366 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1368 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1370 #endif /* TRACE_ARGS_NUM == 8 */
1373 #if TRACE_ARGS_NUM == 2
1374 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1376 #elif TRACE_ARGS_NUM == 4
1377 sprintf(logtext + strlen(logtext),
1378 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1379 a0, a1, a2, a3, md->paramcount - 4);
1381 #elif TRACE_ARGS_NUM == 6
1382 sprintf(logtext + strlen(logtext),
1383 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1384 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1386 #elif TRACE_ARGS_NUM == 8
1387 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1389 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1391 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1392 , a6, a7, md->paramcount - 8);
1396 #else /* SIZEOF_VOID_P == 4 */
1399 sprintf(logtext + strlen(logtext),
1405 sprintf(logtext + strlen(logtext),
1411 sprintf(logtext + strlen(logtext),
1412 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1416 sprintf(logtext + strlen(logtext),
1417 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1421 #if TRACE_ARGS_NUM >= 6
1423 sprintf(logtext + strlen(logtext),
1424 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1425 a0, a1, a2, a3, a4);
1429 sprintf(logtext + strlen(logtext),
1430 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1431 a0, a1, a2, a3, a4, a5);
1433 #endif /* TRACE_ARGS_NUM >= 6 */
1435 #if TRACE_ARGS_NUM == 8
1437 sprintf(logtext + strlen(logtext),
1438 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1439 a0, a1, a2, a3, a4, a5, a6);
1443 sprintf(logtext + strlen(logtext),
1444 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1445 a0, a1, a2, a3, a4, a5, a6, a7);
1447 #endif /* TRACE_ARGS_NUM == 8 */
1450 #if TRACE_ARGS_NUM == 4
1451 sprintf(logtext + strlen(logtext),
1452 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1453 a0, a1, a2, a3, md->paramcount - 4);
1455 #elif TRACE_ARGS_NUM == 6
1456 sprintf(logtext + strlen(logtext),
1457 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1458 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1460 #elif TRACE_ARGS_NUM == 8
1461 sprintf(logtext + strlen(logtext),
1462 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1463 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1466 #endif /* SIZEOF_VOID_P == 4 */
1469 strcat(logtext, ")");
1473 /* release memory */
1475 dump_release(dumpsize);
1482 /* builtin_displaymethodstop ***************************************************
1486 *******************************************************************************/
1488 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1500 /* calculate message length */
1503 6 + methodindent + strlen("finished: ") +
1504 utf_strlen(m->class->name) +
1506 utf_strlen(m->name) +
1507 utf_strlen(m->descriptor) +
1508 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1510 /* add maximal argument length */
1512 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1514 /* allocate memory */
1516 dumpsize = dump_size();
1518 logtext = DMNEW(char, logtextlen);
1520 /* outdent the log message */
1525 log_text("WARNING: unmatched methodindent--");
1527 /* generate the message */
1529 sprintf(logtext,"-%d-",methodindent);
1530 pos = strlen(logtext);
1532 for (i = 0; i < methodindent; i++)
1533 logtext[pos++] = '\t';
1535 strcpy(logtext + pos, "finished: ");
1536 utf_strcat_classname(logtext, m->class->name);
1537 strcat(logtext, ".");
1538 utf_strcat(logtext, m->name);
1539 utf_strcat(logtext, m->descriptor);
1541 switch (md->returntype.type) {
1543 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1547 #if SIZEOF_VOID_P == 4
1548 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1550 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1555 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1560 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1565 #if SIZEOF_VOID_P == 4
1566 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1568 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1575 /* release memory */
1577 dump_release(dumpsize);
1581 /****************************************************************************
1582 SYNCHRONIZATION FUNCTIONS
1583 *****************************************************************************/
1585 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1587 * Lock the mutex of an object.
1589 void internal_lock_mutex_for_object(java_objectheader *object)
1591 mutexHashEntry *entry;
1594 assert(object != 0);
1596 hashValue = MUTEX_HASH_VALUE(object);
1597 entry = &mutexHashTable[hashValue];
1599 if (entry->object != 0) {
1600 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1602 entry->mutex.holder = 0;
1603 entry->mutex.count = 0;
1604 entry->mutex.muxWaiters = 0;
1607 while (entry->next != 0 && entry->object != object)
1608 entry = entry->next;
1610 if (entry->object != object) {
1611 entry->next = firstFreeOverflowEntry;
1612 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1614 entry = entry->next;
1617 assert(entry->conditionCount == 0);
1622 entry->mutex.holder = 0;
1623 entry->mutex.count = 0;
1624 entry->mutex.muxWaiters = 0;
1627 if (entry->object == 0)
1628 entry->object = object;
1630 internal_lock_mutex(&entry->mutex);
1635 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1637 * Unlocks the mutex of an object.
1639 void internal_unlock_mutex_for_object (java_objectheader *object)
1642 mutexHashEntry *entry;
1644 hashValue = MUTEX_HASH_VALUE(object);
1645 entry = &mutexHashTable[hashValue];
1647 if (entry->object == object) {
1648 internal_unlock_mutex(&entry->mutex);
1651 while (entry->next != 0 && entry->next->object != object)
1652 entry = entry->next;
1654 assert(entry->next != 0);
1656 internal_unlock_mutex(&entry->next->mutex);
1658 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1659 mutexHashEntry *unlinked = entry->next;
1661 entry->next = unlinked->next;
1662 unlinked->next = firstFreeOverflowEntry;
1663 firstFreeOverflowEntry = unlinked;
1670 #if defined(USE_THREADS)
1671 void builtin_monitorenter(java_objectheader *o)
1673 #if !defined(NATIVE_THREADS)
1678 hashValue = MUTEX_HASH_VALUE(o);
1679 if (mutexHashTable[hashValue].object == o
1680 && mutexHashTable[hashValue].mutex.holder == currentThread)
1681 ++mutexHashTable[hashValue].mutex.count;
1683 internal_lock_mutex_for_object(o);
1687 monitorEnter((threadobject *) THREADOBJECT, o);
1693 #if defined(USE_THREADS)
1695 * Locks the class object - needed for static synchronized methods.
1696 * The use_class_as_object call is needed in order to circumvent a
1697 * possible deadlock with builtin_monitorenter called by another
1698 * thread calling use_class_as_object.
1700 void builtin_staticmonitorenter(classinfo *c)
1702 use_class_as_object(c);
1703 builtin_monitorenter(&c->header);
1708 #if defined(USE_THREADS)
1709 void builtin_monitorexit(java_objectheader *o)
1711 #if !defined(NATIVE_THREADS)
1716 hashValue = MUTEX_HASH_VALUE(o);
1717 if (mutexHashTable[hashValue].object == o) {
1718 if (mutexHashTable[hashValue].mutex.count == 1
1719 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1720 internal_unlock_mutex_for_object(o);
1722 --mutexHashTable[hashValue].mutex.count;
1725 internal_unlock_mutex_for_object(o);
1729 monitorExit((threadobject *) THREADOBJECT, o);
1735 /*****************************************************************************
1736 MISCELLANEOUS HELPER FUNCTIONS
1737 *****************************************************************************/
1741 /*********** Functions for integer divisions *****************************
1743 On some systems (eg. DEC ALPHA), integer division is not supported by the
1744 CPU. These helper functions implement the missing functionality.
1746 ******************************************************************************/
1748 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1749 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1752 /************** Functions for long arithmetics *******************************
1754 On systems where 64 bit Integers are not supported by the CPU, these
1755 functions are needed.
1757 ******************************************************************************/
1759 s8 builtin_ladd(s8 a, s8 b)
1772 s8 builtin_lsub(s8 a, s8 b)
1785 s8 builtin_lmul(s8 a, s8 b)
1798 s8 builtin_ldiv(s8 a, s8 b)
1811 s8 builtin_lrem(s8 a, s8 b)
1824 s8 builtin_lshl(s8 a, s4 b)
1837 s8 builtin_lshr(s8 a, s4 b)
1850 s8 builtin_lushr(s8 a, s4 b)
1855 c = ((u8) a) >> (b & 63);
1863 s8 builtin_land(s8 a, s8 b)
1876 s8 builtin_lor(s8 a, s8 b)
1889 s8 builtin_lxor(s8 a, s8 b)
1902 s8 builtin_lneg(s8 a)
1915 s4 builtin_lcmp(s8 a, s8 b)
1918 if (a < b) return -1;
1919 if (a > b) return 1;
1930 /*********** Functions for floating point operations *************************/
1932 /* used to convert FLT_xxx defines into float values */
1934 static inline float intBitsToFloat(s4 i)
1943 /* used to convert DBL_xxx defines into double values */
1945 static inline float longBitsToDouble(s8 l)
1954 float builtin_fadd(float a, float b)
1956 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1957 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1968 if (copysignf(1.0, a) == copysignf(1.0, b))
1971 return intBitsToFloat(FLT_NAN);
1977 float builtin_fsub(float a, float b)
1979 return builtin_fadd(a, builtin_fneg(b));
1983 float builtin_fmul(float a, float b)
1985 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1986 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1988 if (finitef(b)) return a * b;
1990 if (a == 0) return intBitsToFloat(FLT_NAN);
1991 else return copysignf(b, copysignf(1.0, b)*a);
1996 if (b == 0) return intBitsToFloat(FLT_NAN);
1997 else return copysignf(a, copysignf(1.0, a)*b);
2000 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2006 /* builtin_ddiv ****************************************************************
2008 Implementation as described in VM Spec.
2010 *******************************************************************************/
2012 float builtin_fdiv(float a, float b)
2016 /* If neither value1' nor value2' is NaN, the sign of the result */
2017 /* is positive if both values have the same sign, negative if the */
2018 /* values have different signs. */
2024 /* If either value1' or value2' is NaN, the result is NaN. */
2026 return intBitsToFloat(FLT_NAN);
2029 /* Division of a finite value by an infinity results in a */
2030 /* signed zero, with the sign-producing rule just given. */
2032 /* is sign equal? */
2034 if (copysignf(1.0, a) == copysignf(1.0, b))
2043 /* If either value1' or value2' is NaN, the result is NaN. */
2045 return intBitsToFloat(FLT_NAN);
2047 } else if (finitef(b)) {
2048 /* Division of an infinity by a finite value results in a signed */
2049 /* infinity, with the sign-producing rule just given. */
2051 /* is sign equal? */
2053 if (copysignf(1.0, a) == copysignf(1.0, b))
2054 return intBitsToFloat(FLT_POSINF);
2056 return intBitsToFloat(FLT_NEGINF);
2059 /* Division of an infinity by an infinity results in NaN. */
2061 return intBitsToFloat(FLT_NAN);
2067 float builtin_frem(float a, float b)
2073 float builtin_fneg(float a)
2075 if (isnanf(a)) return a;
2077 if (finitef(a)) return -a;
2078 else return copysignf(a, -copysignf(1.0, a));
2083 s4 builtin_fcmpl(float a, float b)
2085 if (isnanf(a)) return -1;
2086 if (isnanf(b)) return -1;
2087 if (!finitef(a) || !finitef(b)) {
2088 a = finitef(a) ? 0 : copysignf(1.0, a);
2089 b = finitef(b) ? 0 : copysignf(1.0, b);
2091 if (a > b) return 1;
2092 if (a == b) return 0;
2097 s4 builtin_fcmpg(float a, float b)
2099 if (isnanf(a)) return 1;
2100 if (isnanf(b)) return 1;
2101 if (!finitef(a) || !finitef(b)) {
2102 a = finitef(a) ? 0 : copysignf(1.0, a);
2103 b = finitef(b) ? 0 : copysignf(1.0, b);
2105 if (a > b) return 1;
2106 if (a == b) return 0;
2112 /************************* Functions for doubles ****************************/
2114 double builtin_dadd(double a, double b)
2116 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2117 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2119 if (finite(b)) return a + b;
2123 if (finite(b)) return a;
2125 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2126 else return longBitsToDouble(DBL_NAN);
2132 double builtin_dsub(double a, double b)
2134 return builtin_dadd(a, builtin_dneg(b));
2138 double builtin_dmul(double a, double b)
2140 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2141 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2143 if (finite(b)) return a * b;
2145 if (a == 0) return longBitsToDouble(DBL_NAN);
2146 else return copysign(b, copysign(1.0, b) * a);
2151 if (b == 0) return longBitsToDouble(DBL_NAN);
2152 else return copysign(a, copysign(1.0, a) * b);
2155 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2161 /* builtin_ddiv ****************************************************************
2163 Implementation as described in VM Spec.
2165 *******************************************************************************/
2167 double builtin_ddiv(double a, double b)
2171 /* If neither value1' nor value2' is NaN, the sign of the result */
2172 /* is positive if both values have the same sign, negative if the */
2173 /* values have different signs. */
2179 /* If either value1' or value2' is NaN, the result is NaN. */
2181 return longBitsToDouble(DBL_NAN);
2184 /* Division of a finite value by an infinity results in a */
2185 /* signed zero, with the sign-producing rule just given. */
2187 /* is sign equal? */
2189 if (copysign(1.0, a) == copysign(1.0, b))
2198 /* If either value1' or value2' is NaN, the result is NaN. */
2200 return longBitsToDouble(DBL_NAN);
2202 } else if (finite(b)) {
2203 /* Division of an infinity by a finite value results in a signed */
2204 /* infinity, with the sign-producing rule just given. */
2206 /* is sign equal? */
2208 if (copysign(1.0, a) == copysign(1.0, b))
2209 return longBitsToDouble(DBL_POSINF);
2211 return longBitsToDouble(DBL_NEGINF);
2214 /* Division of an infinity by an infinity results in NaN. */
2216 return longBitsToDouble(DBL_NAN);
2222 double builtin_drem(double a, double b)
2227 /* builtin_dneg ****************************************************************
2229 Implemented as described in VM Spec.
2231 *******************************************************************************/
2233 double builtin_dneg(double a)
2236 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2243 /* If the operand is a zero, the result is the zero of opposite */
2249 /* If the operand is an infinity, the result is the infinity of */
2250 /* opposite sign. */
2252 return copysign(a, -copysign(1.0, a));
2258 s4 builtin_dcmpl(double a, double b)
2260 if (isnan(a)) return -1;
2261 if (isnan(b)) return -1;
2262 if (!finite(a) || !finite(b)) {
2263 a = finite(a) ? 0 : copysign(1.0, a);
2264 b = finite(b) ? 0 : copysign(1.0, b);
2266 if (a > b) return 1;
2267 if (a == b) return 0;
2272 s4 builtin_dcmpg(double a, double b)
2274 if (isnan(a)) return 1;
2275 if (isnan(b)) return 1;
2276 if (!finite(a) || !finite(b)) {
2277 a = finite(a) ? 0 : copysign(1.0, a);
2278 b = finite(b) ? 0 : copysign(1.0, b);
2280 if (a > b) return 1;
2281 if (a == b) return 0;
2286 /*********************** Conversion operations ****************************/
2288 s8 builtin_i2l(s4 i)
2301 float builtin_i2f(s4 a)
2303 float f = (float) a;
2308 double builtin_i2d(s4 a)
2310 double d = (double) a;
2315 s4 builtin_l2i(s8 l)
2325 float builtin_l2f(s8 a)
2328 float f = (float) a;
2336 double builtin_l2d(s8 a)
2339 double d = (double) a;
2347 s4 builtin_f2i(float a)
2351 i = builtin_d2i((double) a);
2362 if (a < (-2147483648))
2363 return (-2147483648);
2366 f = copysignf((float) 1.0, a);
2369 return (-2147483648); */
2373 s8 builtin_f2l(float a)
2377 l = builtin_d2l((double) a);
2384 if (a > 9223372036854775807L)
2385 return 9223372036854775807L;
2386 if (a < (-9223372036854775808L))
2387 return (-9223372036854775808L);
2392 f = copysignf((float) 1.0, a);
2394 return 9223372036854775807L;
2395 return (-9223372036854775808L); */
2399 double builtin_f2d(float a)
2401 if (finitef(a)) return (double) a;
2404 return longBitsToDouble(DBL_NAN);
2406 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2411 s4 builtin_d2i(double a)
2416 if (a >= 2147483647)
2418 if (a <= (-2147483647-1))
2419 return (-2147483647-1);
2424 d = copysign(1.0, a);
2427 return (-2147483647-1);
2431 s8 builtin_d2l(double a)
2436 if (a >= 9223372036854775807LL)
2437 return 9223372036854775807LL;
2438 if (a <= (-9223372036854775807LL-1))
2439 return (-9223372036854775807LL-1);
2444 d = copysign(1.0, a);
2446 return 9223372036854775807LL;
2447 return (-9223372036854775807LL-1);
2451 float builtin_d2f(double a)
2457 return intBitsToFloat(FLT_NAN);
2459 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2464 /* builtin_clone_array *********************************************************
2466 Wrapper function for cloning arrays.
2468 *******************************************************************************/
2470 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2472 java_arrayheader *ah;
2473 java_lang_Cloneable *c;
2475 c = (java_lang_Cloneable *) o;
2477 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2483 /* builtin_asm_get_exceptionptrptr *********************************************
2485 this is a wrapper for calls from asmpart
2487 *******************************************************************************/
2489 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2490 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2492 return builtin_get_exceptionptrptr();
2498 * These are local overrides for various environment variables in Emacs.
2499 * Please do not remove this and leave it at the end of the file, where
2500 * Emacs will automagically detect them.
2501 * ---------------------------------------------------------------------
2504 * indent-tabs-mode: t