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 3582 2005-11-05 19:51:18Z 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"
62 #include "native/include/java_lang_Throwable.h"
63 #include "native/include/java_lang_VMThrowable.h"
65 #if defined(USE_THREADS)
66 # if defined(NATIVE_THREADS)
67 # include "threads/native/threads.h"
69 # include "threads/green/threads.h"
70 # include "threads/green/locks.h"
74 #include "toolbox/logging.h"
75 #include "toolbox/util.h"
76 #include "vm/builtin.h"
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/tables.h"
84 #include "vm/jit/asmpart.h"
85 #include "vm/jit/patcher.h"
88 /* include builtin tables *****************************************************/
90 #include "vm/builtintable.inc"
93 /* builtintable_init ***********************************************************
95 Parse the descriptors of builtin functions and create the parsed
98 *******************************************************************************/
100 static bool builtintable_init(void)
102 descriptor_pool *descpool;
106 s4 entries_automatic;
109 /* mark start of dump memory area */
111 dumpsize = dump_size();
113 /* create a new descriptor pool */
115 descpool = descriptor_pool_new(class_java_lang_Object);
117 /* add some entries we need */
119 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
122 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
125 /* calculate table entries statically */
128 sizeof(builtintable_internal) / sizeof(builtintable_entry);
131 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
132 - 1; /* last filler entry (comment see builtintable.inc) */
134 /* first add all descriptors to the pool */
136 for (i = 0; i < entries_internal; i++) {
137 /* create a utf8 string from descriptor */
139 descriptor = utf_new_char(builtintable_internal[i].descriptor);
141 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
142 /* release dump area */
144 dump_release(dumpsize);
150 for (i = 0; i < entries_automatic; i++) {
151 /* create a utf8 string from descriptor */
153 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
155 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
156 /* release dump area */
158 dump_release(dumpsize);
164 /* create the class reference table */
166 (void) descriptor_pool_create_classrefs(descpool, NULL);
168 /* allocate space for the parsed descriptors */
170 descriptor_pool_alloc_parsed_descriptors(descpool);
172 /* now parse all descriptors */
174 for (i = 0; i < entries_internal; i++) {
175 /* create a utf8 string from descriptor */
177 descriptor = utf_new_char(builtintable_internal[i].descriptor);
179 /* parse the descriptor, builtin is always static (no `this' pointer) */
181 builtintable_internal[i].md =
182 descriptor_pool_parse_method_descriptor(descpool, descriptor,
186 for (i = 0; i < entries_automatic; i++) {
187 /* create a utf8 string from descriptor */
189 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
191 /* parse the descriptor, builtin is always static (no `this' pointer) */
193 builtintable_automatic[i].md =
194 descriptor_pool_parse_method_descriptor(descpool, descriptor,
198 /* release dump area */
200 dump_release(dumpsize);
206 /* builtintable_comparator *****************************************************
208 qsort comparator for the automatic builtin table.
210 *******************************************************************************/
212 static int builtintable_comparator(const void *a, const void *b)
214 builtintable_entry *bte1;
215 builtintable_entry *bte2;
217 bte1 = (builtintable_entry *) a;
218 bte2 = (builtintable_entry *) b;
220 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
224 /* builtintable_sort_automatic *************************************************
226 Sorts the automatic builtin table.
228 *******************************************************************************/
230 static void builtintable_sort_automatic(void)
234 /* calculate table size statically (`- 1' comment see builtintable.inc) */
236 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
238 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
239 builtintable_comparator);
243 /* builtin_init ****************************************************************
247 *******************************************************************************/
249 bool builtin_init(void)
251 /* initialize the builtin tables */
253 if (!builtintable_init())
256 /* sort builtin tables */
258 builtintable_sort_automatic();
264 /* builtintable_get_internal ***************************************************
266 Finds an entry in the builtintable for internal functions and
267 returns the a pointer to the structure.
269 *******************************************************************************/
271 builtintable_entry *builtintable_get_internal(functionptr fp)
275 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
276 if (builtintable_internal[i].fp == fp)
277 return &builtintable_internal[i];
284 /* builtintable_get_automatic **************************************************
286 Finds an entry in the builtintable for functions which are replaced
287 automatically and returns the a pointer to the structure.
289 *******************************************************************************/
291 builtintable_entry *builtintable_get_automatic(s4 opcode)
293 builtintable_entry *first;
294 builtintable_entry *last;
295 builtintable_entry *middle;
299 /* calculate table size statically (`- 1' comment see builtintable.inc) */
301 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
303 first = builtintable_automatic;
304 last = builtintable_automatic + entries;
306 while (entries > 0) {
308 middle = first + half;
310 if (middle->opcode < opcode) {
317 return (first != last ? first : NULL);
321 /*****************************************************************************
323 *****************************************************************************/
327 /*************** internal function: builtin_isanysubclass *********************
329 Checks a subclass relation between two classes. Implemented interfaces
330 are interpreted as super classes.
331 Return value: 1 ... sub is subclass of super
334 *****************************************************************************/
335 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
338 castinfo classvalues;
343 if (super->flags & ACC_INTERFACE) {
344 res = (sub->vftbl->interfacetablelength > super->index) &&
345 (sub->vftbl->interfacetable[-super->index] != NULL);
348 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
350 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
351 (u4) classvalues.super_diffval;
358 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
362 castinfo classvalues;
367 asm_getclassvalues_atomic(super, sub, &classvalues);
369 if ((base = classvalues.super_baseval) <= 0) {
370 /* super is an interface */
371 res = (sub->interfacetablelength > -base) &&
372 (sub->interfacetable[base] != NULL);
374 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
375 <= (u4) classvalues.super_diffval;
382 /****************** function: builtin_instanceof *****************************
384 Checks if an object is an instance of some given class (or subclass of
385 that class). If class is an interface, checks if the interface is
387 Return value: 1 ... obj is an instance of class or implements the interface
388 0 ... otherwise or if obj == NULL
390 *****************************************************************************/
392 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
397 return builtin_isanysubclass(obj->vftbl->class, class);
402 /**************** function: builtin_checkcast *******************************
404 The same as builtin_instanceof except that 1 is returned when
407 ****************************************************************************/
409 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
414 if (builtin_isanysubclass(obj->vftbl->class, class))
421 /* builtin_descriptorscompatible ***********************************************
423 Checks if two array type descriptors are assignment compatible
425 Return value: 1 ... target = desc is possible
428 *******************************************************************************/
430 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
431 arraydescriptor *target)
436 if (desc->arraytype != target->arraytype)
439 if (desc->arraytype != ARRAYTYPE_OBJECT)
442 /* {both arrays are arrays of references} */
444 if (desc->dimension == target->dimension) {
445 /* an array which contains elements of interface types is
446 allowed to be casted to Object (JOWENN)*/
448 if ((desc->elementvftbl->baseval < 0) &&
449 (target->elementvftbl->baseval == 1))
452 return builtin_isanysubclass_vftbl(desc->elementvftbl,
453 target->elementvftbl);
456 if (desc->dimension < target->dimension)
459 /* {desc has higher dimension than target} */
461 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
462 target->elementvftbl);
466 /* builtin_arraycheckcast ******************************************************
468 Checks if an object is really a subtype of the requested array
469 type. The object has to be an array to begin with. For simple
470 arrays (int, short, double, etc.) the types have to match exactly.
471 For arrays of objects, the type of elements in the array has to be
472 a subtype (or the same type) of the requested element type. For
473 arrays of arrays (which in turn can again be arrays of arrays), the
474 types at the lowest level have to satisfy the corresponding sub
477 *******************************************************************************/
479 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
481 arraydescriptor *desc;
486 if ((desc = o->vftbl->arraydesc) == NULL)
489 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
493 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
498 return builtin_arraycheckcast(o, targetclass);
502 /************************** exception functions *******************************
504 ******************************************************************************/
506 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
508 java_lang_Throwable *t;
514 t = (java_lang_Throwable *) xptr;
516 /* calculate message length */
518 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
522 utf_strlen(xptr->vftbl->class->name) +
524 javastring_strlen((java_objectheader *) t->detailMessage);
527 logtextlen += strlen("(nil)");
529 /* allocate memory */
531 dumpsize = dump_size();
533 logtext = DMNEW(char, logtextlen);
535 strcpy(logtext, "Builtin exception thrown: ");
538 utf_sprint_classname(logtext + strlen(logtext),
539 xptr->vftbl->class->name);
541 if (t->detailMessage) {
544 buf = javastring_tochar((java_objectheader *) t->detailMessage);
545 strcat(logtext, ": ");
546 strcat(logtext, buf);
547 MFREE(buf, char, strlen(buf));
551 strcat(logtext, "(nil)");
558 dump_release(dumpsize);
561 *exceptionptr = xptr;
568 /* builtin_canstore ************************************************************
570 Checks, if an object can be stored in an array.
572 Return value: 1 ... possible
575 *******************************************************************************/
577 s4 builtin_canstore(java_objectarray *a, java_objectheader *o)
579 arraydescriptor *desc;
580 arraydescriptor *valuedesc;
581 vftbl_t *componentvftbl;
584 castinfo classvalues;
589 /* The following is guaranteed (by verifier checks):
591 * *) a->...vftbl->arraydesc != NULL
592 * *) a->...vftbl->arraydesc->componentvftbl != NULL
593 * *) o->vftbl is not an interface vftbl
596 desc = a->header.objheader.vftbl->arraydesc;
597 componentvftbl = desc->componentvftbl;
598 valuevftbl = o->vftbl;
600 if ((desc->dimension - 1) == 0) {
603 /* {a is a one-dimensional array} */
604 /* {a is an array of references} */
606 if (valuevftbl == componentvftbl)
609 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
611 if ((base = classvalues.super_baseval) <= 0)
612 /* an array of interface references */
613 return (valuevftbl->interfacetablelength > -base &&
614 valuevftbl->interfacetable[base] != NULL);
616 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
617 <= (unsigned) classvalues.super_diffval;
622 /* {a has dimension > 1} */
623 /* {componentvftbl->arraydesc != NULL} */
625 /* check if o is an array */
626 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 java_lang_Throwable *t;
1218 java_lang_VMThrowable *vmt;
1219 java_lang_Throwable *cause;
1221 stackTraceBuffer *stb;
1223 t = (java_lang_Throwable *) xptr;
1226 /* print the root exception */
1228 utf_display_classname(t->header.vftbl->class->name);
1230 if (t->detailMessage) {
1231 u = javastring_toutf(t->detailMessage, false);
1239 /* print the cause if available */
1241 if (cause && (cause != t)) {
1242 printf("Caused by: ");
1243 utf_display_classname(cause->header.vftbl->class->name);
1245 if (cause->detailMessage) {
1246 u = javastring_toutf(cause->detailMessage, false);
1255 /* now print the stacktrace */
1258 stb = (stackTraceBuffer *) vmt->vmData;
1260 stacktrace_print_trace(stb);
1268 /* builtin_trace_args **********************************************************
1272 *******************************************************************************/
1274 #ifdef TRACE_ARGS_NUM
1275 void builtin_trace_args(s8 a0, s8 a1,
1276 #if TRACE_ARGS_NUM >= 4
1278 #endif /* TRACE_ARGS_NUM >= 4 */
1279 #if TRACE_ARGS_NUM >= 6
1281 #endif /* TRACE_ARGS_NUM >= 6 */
1282 #if TRACE_ARGS_NUM == 8
1284 #endif /* TRACE_ARGS_NUM == 8 */
1296 /* calculate message length */
1299 6 + methodindent + strlen("called: ") +
1300 utf_strlen(m->class->name) +
1302 utf_strlen(m->name) +
1303 utf_strlen(m->descriptor) +
1304 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1306 /* add maximal argument length */
1308 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1310 /* allocate memory */
1312 dumpsize = dump_size();
1314 logtext = DMNEW(char, logtextlen);
1316 sprintf(logtext,"-%d-",methodindent);
1317 pos = strlen(logtext);
1319 for (i = 0; i < methodindent; i++)
1320 logtext[pos++] = '\t';
1322 strcpy(logtext + pos, "called: ");
1324 utf_strcat_classname(logtext, m->class->name);
1325 strcat(logtext, ".");
1326 utf_strcat(logtext, m->name);
1327 utf_strcat(logtext, m->descriptor);
1329 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1330 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1331 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1332 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1333 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1334 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1335 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1336 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1337 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1338 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1339 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1341 strcat(logtext, "(");
1343 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1344 /* Only Arguments in integer Registers are passed correctly here */
1345 /* long longs spilled on Stack have an wrong offset of +4 */
1346 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1347 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1348 switch (md->paramcount) {
1352 #if SIZEOF_VOID_P == 4
1354 sprintf(logtext + strlen(logtext),
1360 sprintf(logtext + strlen(logtext),
1365 #if TRACE_ARGS_NUM >= 4
1367 sprintf(logtext + strlen(logtext),
1368 "0x%llx, 0x%llx, 0x%llx",
1373 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1375 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1378 #endif /* TRACE_ARGS_NUM >= 4 */
1380 #if TRACE_ARGS_NUM >= 6
1382 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1384 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1389 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1391 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1394 #endif /* TRACE_ARGS_NUM >= 6 */
1396 #if TRACE_ARGS_NUM == 8
1398 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1400 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1402 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1406 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1408 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1410 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1412 #endif /* TRACE_ARGS_NUM == 8 */
1415 #if TRACE_ARGS_NUM == 2
1416 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1418 #elif TRACE_ARGS_NUM == 4
1419 sprintf(logtext + strlen(logtext),
1420 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1421 a0, a1, a2, a3, md->paramcount - 4);
1423 #elif TRACE_ARGS_NUM == 6
1424 sprintf(logtext + strlen(logtext),
1425 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1426 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1428 #elif TRACE_ARGS_NUM == 8
1429 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1431 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1433 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1434 , a6, a7, md->paramcount - 8);
1438 #else /* SIZEOF_VOID_P == 4 */
1441 sprintf(logtext + strlen(logtext),
1447 sprintf(logtext + strlen(logtext),
1453 sprintf(logtext + strlen(logtext),
1454 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1458 sprintf(logtext + strlen(logtext),
1459 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1463 #if TRACE_ARGS_NUM >= 6
1465 sprintf(logtext + strlen(logtext),
1466 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1467 a0, a1, a2, a3, a4);
1471 sprintf(logtext + strlen(logtext),
1472 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1473 a0, a1, a2, a3, a4, a5);
1475 #endif /* TRACE_ARGS_NUM >= 6 */
1477 #if TRACE_ARGS_NUM == 8
1479 sprintf(logtext + strlen(logtext),
1480 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1481 a0, a1, a2, a3, a4, a5, a6);
1485 sprintf(logtext + strlen(logtext),
1486 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1487 a0, a1, a2, a3, a4, a5, a6, a7);
1489 #endif /* TRACE_ARGS_NUM == 8 */
1492 #if TRACE_ARGS_NUM == 4
1493 sprintf(logtext + strlen(logtext),
1494 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1495 a0, a1, a2, a3, md->paramcount - 4);
1497 #elif TRACE_ARGS_NUM == 6
1498 sprintf(logtext + strlen(logtext),
1499 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1500 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1502 #elif TRACE_ARGS_NUM == 8
1503 sprintf(logtext + strlen(logtext),
1504 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1505 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1508 #endif /* SIZEOF_VOID_P == 4 */
1511 strcat(logtext, ")");
1515 /* release memory */
1517 dump_release(dumpsize);
1524 /* builtin_displaymethodstop ***************************************************
1528 *******************************************************************************/
1530 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1542 /* calculate message length */
1545 6 + methodindent + strlen("finished: ") +
1546 utf_strlen(m->class->name) +
1548 utf_strlen(m->name) +
1549 utf_strlen(m->descriptor) +
1550 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1552 /* add maximal argument length */
1554 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1556 /* allocate memory */
1558 dumpsize = dump_size();
1560 logtext = DMNEW(char, logtextlen);
1562 /* outdent the log message */
1567 log_text("WARNING: unmatched methodindent--");
1569 /* generate the message */
1571 sprintf(logtext,"-%d-",methodindent);
1572 pos = strlen(logtext);
1574 for (i = 0; i < methodindent; i++)
1575 logtext[pos++] = '\t';
1577 strcpy(logtext + pos, "finished: ");
1578 utf_strcat_classname(logtext, m->class->name);
1579 strcat(logtext, ".");
1580 utf_strcat(logtext, m->name);
1581 utf_strcat(logtext, m->descriptor);
1583 switch (md->returntype.type) {
1585 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1589 #if SIZEOF_VOID_P == 4
1590 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1592 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1597 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1602 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1607 #if SIZEOF_VOID_P == 4
1608 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1610 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1617 /* release memory */
1619 dump_release(dumpsize);
1623 /****************************************************************************
1624 SYNCHRONIZATION FUNCTIONS
1625 *****************************************************************************/
1627 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1629 * Lock the mutex of an object.
1631 void internal_lock_mutex_for_object(java_objectheader *object)
1633 mutexHashEntry *entry;
1636 assert(object != 0);
1638 hashValue = MUTEX_HASH_VALUE(object);
1639 entry = &mutexHashTable[hashValue];
1641 if (entry->object != 0) {
1642 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1644 entry->mutex.holder = 0;
1645 entry->mutex.count = 0;
1646 entry->mutex.muxWaiters = 0;
1649 while (entry->next != 0 && entry->object != object)
1650 entry = entry->next;
1652 if (entry->object != object) {
1653 entry->next = firstFreeOverflowEntry;
1654 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1656 entry = entry->next;
1659 assert(entry->conditionCount == 0);
1664 entry->mutex.holder = 0;
1665 entry->mutex.count = 0;
1666 entry->mutex.muxWaiters = 0;
1669 if (entry->object == 0)
1670 entry->object = object;
1672 internal_lock_mutex(&entry->mutex);
1677 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1679 * Unlocks the mutex of an object.
1681 void internal_unlock_mutex_for_object (java_objectheader *object)
1684 mutexHashEntry *entry;
1686 hashValue = MUTEX_HASH_VALUE(object);
1687 entry = &mutexHashTable[hashValue];
1689 if (entry->object == object) {
1690 internal_unlock_mutex(&entry->mutex);
1693 while (entry->next != 0 && entry->next->object != object)
1694 entry = entry->next;
1696 assert(entry->next != 0);
1698 internal_unlock_mutex(&entry->next->mutex);
1700 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1701 mutexHashEntry *unlinked = entry->next;
1703 entry->next = unlinked->next;
1704 unlinked->next = firstFreeOverflowEntry;
1705 firstFreeOverflowEntry = unlinked;
1712 #if defined(USE_THREADS)
1713 void builtin_monitorenter(java_objectheader *o)
1715 #if !defined(NATIVE_THREADS)
1720 hashValue = MUTEX_HASH_VALUE(o);
1721 if (mutexHashTable[hashValue].object == o
1722 && mutexHashTable[hashValue].mutex.holder == currentThread)
1723 ++mutexHashTable[hashValue].mutex.count;
1725 internal_lock_mutex_for_object(o);
1729 monitorEnter((threadobject *) THREADOBJECT, o);
1735 #if defined(USE_THREADS)
1737 * Locks the class object - needed for static synchronized methods.
1738 * The use_class_as_object call is needed in order to circumvent a
1739 * possible deadlock with builtin_monitorenter called by another
1740 * thread calling use_class_as_object.
1742 void builtin_staticmonitorenter(classinfo *c)
1744 use_class_as_object(c);
1745 builtin_monitorenter(&c->header);
1750 #if defined(USE_THREADS)
1751 void builtin_monitorexit(java_objectheader *o)
1753 #if !defined(NATIVE_THREADS)
1758 hashValue = MUTEX_HASH_VALUE(o);
1759 if (mutexHashTable[hashValue].object == o) {
1760 if (mutexHashTable[hashValue].mutex.count == 1
1761 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1762 internal_unlock_mutex_for_object(o);
1764 --mutexHashTable[hashValue].mutex.count;
1767 internal_unlock_mutex_for_object(o);
1771 monitorExit((threadobject *) THREADOBJECT, o);
1777 /*****************************************************************************
1778 MISCELLANEOUS HELPER FUNCTIONS
1779 *****************************************************************************/
1783 /*********** Functions for integer divisions *****************************
1785 On some systems (eg. DEC ALPHA), integer division is not supported by the
1786 CPU. These helper functions implement the missing functionality.
1788 ******************************************************************************/
1790 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1791 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1794 /************** Functions for long arithmetics *******************************
1796 On systems where 64 bit Integers are not supported by the CPU, these
1797 functions are needed.
1799 ******************************************************************************/
1801 s8 builtin_ladd(s8 a, s8 b)
1814 s8 builtin_lsub(s8 a, s8 b)
1827 s8 builtin_lmul(s8 a, s8 b)
1840 s8 builtin_ldiv(s8 a, s8 b)
1853 s8 builtin_lrem(s8 a, s8 b)
1866 s8 builtin_lshl(s8 a, s4 b)
1879 s8 builtin_lshr(s8 a, s4 b)
1892 s8 builtin_lushr(s8 a, s4 b)
1897 c = ((u8) a) >> (b & 63);
1905 s8 builtin_land(s8 a, s8 b)
1918 s8 builtin_lor(s8 a, s8 b)
1931 s8 builtin_lxor(s8 a, s8 b)
1944 s8 builtin_lneg(s8 a)
1957 s4 builtin_lcmp(s8 a, s8 b)
1960 if (a < b) return -1;
1961 if (a > b) return 1;
1972 /*********** Functions for floating point operations *************************/
1974 /* used to convert FLT_xxx defines into float values */
1976 static inline float intBitsToFloat(s4 i)
1985 /* used to convert DBL_xxx defines into double values */
1987 static inline float longBitsToDouble(s8 l)
1996 float builtin_fadd(float a, float b)
1998 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1999 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2010 if (copysignf(1.0, a) == copysignf(1.0, b))
2013 return intBitsToFloat(FLT_NAN);
2019 float builtin_fsub(float a, float b)
2021 return builtin_fadd(a, builtin_fneg(b));
2025 float builtin_fmul(float a, float b)
2027 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2028 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2030 if (finitef(b)) return a * b;
2032 if (a == 0) return intBitsToFloat(FLT_NAN);
2033 else return copysignf(b, copysignf(1.0, b)*a);
2038 if (b == 0) return intBitsToFloat(FLT_NAN);
2039 else return copysignf(a, copysignf(1.0, a)*b);
2042 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2048 /* builtin_ddiv ****************************************************************
2050 Implementation as described in VM Spec.
2052 *******************************************************************************/
2054 float builtin_fdiv(float a, float b)
2058 /* If neither value1' nor value2' is NaN, the sign of the result */
2059 /* is positive if both values have the same sign, negative if the */
2060 /* values have different signs. */
2066 /* If either value1' or value2' is NaN, the result is NaN. */
2068 return intBitsToFloat(FLT_NAN);
2071 /* Division of a finite value by an infinity results in a */
2072 /* signed zero, with the sign-producing rule just given. */
2074 /* is sign equal? */
2076 if (copysignf(1.0, a) == copysignf(1.0, b))
2085 /* If either value1' or value2' is NaN, the result is NaN. */
2087 return intBitsToFloat(FLT_NAN);
2089 } else if (finitef(b)) {
2090 /* Division of an infinity by a finite value results in a signed */
2091 /* infinity, with the sign-producing rule just given. */
2093 /* is sign equal? */
2095 if (copysignf(1.0, a) == copysignf(1.0, b))
2096 return intBitsToFloat(FLT_POSINF);
2098 return intBitsToFloat(FLT_NEGINF);
2101 /* Division of an infinity by an infinity results in NaN. */
2103 return intBitsToFloat(FLT_NAN);
2109 float builtin_frem(float a, float b)
2115 float builtin_fneg(float a)
2117 if (isnanf(a)) return a;
2119 if (finitef(a)) return -a;
2120 else return copysignf(a, -copysignf(1.0, a));
2125 s4 builtin_fcmpl(float a, float b)
2127 if (isnanf(a)) return -1;
2128 if (isnanf(b)) return -1;
2129 if (!finitef(a) || !finitef(b)) {
2130 a = finitef(a) ? 0 : copysignf(1.0, a);
2131 b = finitef(b) ? 0 : copysignf(1.0, b);
2133 if (a > b) return 1;
2134 if (a == b) return 0;
2139 s4 builtin_fcmpg(float a, float b)
2141 if (isnanf(a)) return 1;
2142 if (isnanf(b)) return 1;
2143 if (!finitef(a) || !finitef(b)) {
2144 a = finitef(a) ? 0 : copysignf(1.0, a);
2145 b = finitef(b) ? 0 : copysignf(1.0, b);
2147 if (a > b) return 1;
2148 if (a == b) return 0;
2154 /************************* Functions for doubles ****************************/
2156 double builtin_dadd(double a, double b)
2158 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2159 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2161 if (finite(b)) return a + b;
2165 if (finite(b)) return a;
2167 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2168 else return longBitsToDouble(DBL_NAN);
2174 double builtin_dsub(double a, double b)
2176 return builtin_dadd(a, builtin_dneg(b));
2180 double builtin_dmul(double a, double b)
2182 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2183 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2185 if (finite(b)) return a * b;
2187 if (a == 0) return longBitsToDouble(DBL_NAN);
2188 else return copysign(b, copysign(1.0, b) * a);
2193 if (b == 0) return longBitsToDouble(DBL_NAN);
2194 else return copysign(a, copysign(1.0, a) * b);
2197 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2203 /* builtin_ddiv ****************************************************************
2205 Implementation as described in VM Spec.
2207 *******************************************************************************/
2209 double builtin_ddiv(double a, double b)
2213 /* If neither value1' nor value2' is NaN, the sign of the result */
2214 /* is positive if both values have the same sign, negative if the */
2215 /* values have different signs. */
2221 /* If either value1' or value2' is NaN, the result is NaN. */
2223 return longBitsToDouble(DBL_NAN);
2226 /* Division of a finite value by an infinity results in a */
2227 /* signed zero, with the sign-producing rule just given. */
2229 /* is sign equal? */
2231 if (copysign(1.0, a) == copysign(1.0, b))
2240 /* If either value1' or value2' is NaN, the result is NaN. */
2242 return longBitsToDouble(DBL_NAN);
2244 } else if (finite(b)) {
2245 /* Division of an infinity by a finite value results in a signed */
2246 /* infinity, with the sign-producing rule just given. */
2248 /* is sign equal? */
2250 if (copysign(1.0, a) == copysign(1.0, b))
2251 return longBitsToDouble(DBL_POSINF);
2253 return longBitsToDouble(DBL_NEGINF);
2256 /* Division of an infinity by an infinity results in NaN. */
2258 return longBitsToDouble(DBL_NAN);
2264 double builtin_drem(double a, double b)
2269 /* builtin_dneg ****************************************************************
2271 Implemented as described in VM Spec.
2273 *******************************************************************************/
2275 double builtin_dneg(double a)
2278 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2285 /* If the operand is a zero, the result is the zero of opposite */
2291 /* If the operand is an infinity, the result is the infinity of */
2292 /* opposite sign. */
2294 return copysign(a, -copysign(1.0, a));
2300 s4 builtin_dcmpl(double a, double b)
2302 if (isnan(a)) return -1;
2303 if (isnan(b)) return -1;
2304 if (!finite(a) || !finite(b)) {
2305 a = finite(a) ? 0 : copysign(1.0, a);
2306 b = finite(b) ? 0 : copysign(1.0, b);
2308 if (a > b) return 1;
2309 if (a == b) return 0;
2314 s4 builtin_dcmpg(double a, double b)
2316 if (isnan(a)) return 1;
2317 if (isnan(b)) return 1;
2318 if (!finite(a) || !finite(b)) {
2319 a = finite(a) ? 0 : copysign(1.0, a);
2320 b = finite(b) ? 0 : copysign(1.0, b);
2322 if (a > b) return 1;
2323 if (a == b) return 0;
2328 /*********************** Conversion operations ****************************/
2330 s8 builtin_i2l(s4 i)
2343 float builtin_i2f(s4 a)
2345 float f = (float) a;
2350 double builtin_i2d(s4 a)
2352 double d = (double) a;
2357 s4 builtin_l2i(s8 l)
2367 float builtin_l2f(s8 a)
2370 float f = (float) a;
2378 double builtin_l2d(s8 a)
2381 double d = (double) a;
2389 s4 builtin_f2i(float a)
2393 i = builtin_d2i((double) a);
2404 if (a < (-2147483648))
2405 return (-2147483648);
2408 f = copysignf((float) 1.0, a);
2411 return (-2147483648); */
2415 s8 builtin_f2l(float a)
2419 l = builtin_d2l((double) a);
2426 if (a > 9223372036854775807L)
2427 return 9223372036854775807L;
2428 if (a < (-9223372036854775808L))
2429 return (-9223372036854775808L);
2434 f = copysignf((float) 1.0, a);
2436 return 9223372036854775807L;
2437 return (-9223372036854775808L); */
2441 double builtin_f2d(float a)
2443 if (finitef(a)) return (double) a;
2446 return longBitsToDouble(DBL_NAN);
2448 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2453 s4 builtin_d2i(double a)
2458 if (a >= 2147483647)
2460 if (a <= (-2147483647-1))
2461 return (-2147483647-1);
2466 d = copysign(1.0, a);
2469 return (-2147483647-1);
2473 s8 builtin_d2l(double a)
2478 if (a >= 9223372036854775807LL)
2479 return 9223372036854775807LL;
2480 if (a <= (-9223372036854775807LL-1))
2481 return (-9223372036854775807LL-1);
2486 d = copysign(1.0, a);
2488 return 9223372036854775807LL;
2489 return (-9223372036854775807LL-1);
2493 float builtin_d2f(double a)
2499 return intBitsToFloat(FLT_NAN);
2501 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2506 /* builtin_clone_array *********************************************************
2508 Wrapper function for cloning arrays.
2510 *******************************************************************************/
2512 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2514 java_arrayheader *ah;
2515 java_lang_Cloneable *c;
2517 c = (java_lang_Cloneable *) o;
2519 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2525 /* builtin_asm_get_exceptionptrptr *********************************************
2527 this is a wrapper for calls from asmpart
2529 *******************************************************************************/
2531 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2532 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2534 return builtin_get_exceptionptrptr();
2540 * These are local overrides for various environment variables in Emacs.
2541 * Please do not remove this and leave it at the end of the file, where
2542 * Emacs will automagically detect them.
2543 * ---------------------------------------------------------------------
2546 * indent-tabs-mode: t