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 3562 2005-11-04 16:20:54Z 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 /* is the class linked */
736 if (!c->initialized) {
738 log_message_class("Initialize class (from builtin_new): ", c);
740 if (!initialize_class(c))
744 o = heap_allocate(c->instancesize, true, c->finalizer);
751 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
759 /* builtin_newarray ************************************************************
761 Creates an array with the given vftbl on the heap. This function
762 takes as class argument an array class.
764 Return value: pointer to the array or NULL if no memory is available
766 *******************************************************************************/
768 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
770 arraydescriptor *desc;
776 desc = arrayclass->vftbl->arraydesc;
777 dataoffset = desc->dataoffset;
778 componentsize = desc->componentsize;
781 *exceptionptr = new_negativearraysizeexception();
785 actualsize = dataoffset + size * componentsize;
787 if (((u4) actualsize) < ((u4) size)) { /* overflow */
788 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
792 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
797 a->objheader.vftbl = arrayclass->vftbl;
799 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
800 initObjectLock(&a->objheader);
809 /* builtin_anewarray ***********************************************************
811 Creates an array of references to the given class type on the heap.
813 Return value: pointer to the array or NULL if no memory is
816 *******************************************************************************/
818 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
820 classinfo *arrayclass;
822 /* is class loaded */
824 assert(componentclass->loaded);
826 /* is class linked */
828 if (!componentclass->linked)
829 if (!link_class(componentclass))
832 arrayclass = class_array_of(componentclass, true);
837 return (java_objectarray *) builtin_newarray(size, arrayclass);
841 /* builtin_newarray_boolean ****************************************************
843 Creates an array of bytes on the heap. The array is designated as
844 an array of booleans (important for casts)
846 Return value: pointer to the array or NULL if no memory is
849 *******************************************************************************/
851 java_booleanarray *builtin_newarray_boolean(s4 size)
853 return (java_booleanarray *)
854 builtin_newarray(size,
855 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
859 /* builtin_newarray_byte *******************************************************
861 Creates an array of 8 bit Integers on the heap.
863 Return value: pointer to the array or NULL if no memory is
866 *******************************************************************************/
868 java_bytearray *builtin_newarray_byte(s4 size)
870 return (java_bytearray *)
871 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
875 /* builtin_newarray_char *******************************************************
877 Creates an array of characters on the heap.
879 Return value: pointer to the array or NULL if no memory is
882 *******************************************************************************/
884 java_chararray *builtin_newarray_char(s4 size)
886 return (java_chararray *)
887 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
891 /* builtin_newarray_short ******************************************************
893 Creates an array of 16 bit Integers on the heap.
895 Return value: pointer to the array or NULL if no memory is
898 *******************************************************************************/
900 java_shortarray *builtin_newarray_short(s4 size)
902 return (java_shortarray *)
903 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
907 /* builtin_newarray_int ********************************************************
909 Creates an array of 32 bit Integers on the heap.
911 Return value: pointer to the array or NULL if no memory is
914 *******************************************************************************/
916 java_intarray *builtin_newarray_int(s4 size)
918 return (java_intarray *)
919 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
923 /* builtin_newarray_long *******************************************************
925 Creates an array of 64 bit Integers on the heap.
927 Return value: pointer to the array or NULL if no memory is
930 *******************************************************************************/
932 java_longarray *builtin_newarray_long(s4 size)
934 return (java_longarray *)
935 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
939 /* builtin_newarray_float ******************************************************
941 Creates an array of 32 bit IEEE floats on the heap.
943 Return value: pointer to the array or NULL if no memory is
946 *******************************************************************************/
948 java_floatarray *builtin_newarray_float(s4 size)
950 return (java_floatarray *)
951 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
955 /* builtin_newarray_double *****************************************************
957 Creates an array of 64 bit IEEE floats on the heap.
959 Return value: pointer to the array or NULL if no memory is
962 *******************************************************************************/
964 java_doublearray *builtin_newarray_double(s4 size)
966 return (java_doublearray *)
967 builtin_newarray(size,
968 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
972 /* builtin_multianewarray_intern ***********************************************
974 Creates a multi-dimensional array on the heap. The dimensions are
975 passed in an array of longs.
978 n............number of dimensions to create
979 arrayvftbl...vftbl of the array class
980 dims.........array containing the size of each dimension to create
982 Return value: pointer to the array or NULL if no memory is
985 ******************************************************************************/
987 static java_arrayheader *builtin_multianewarray_intern(int n,
988 classinfo *arrayclass,
993 classinfo *componentclass;
996 /* create this dimension */
999 a = builtin_newarray(size, arrayclass);
1004 /* if this is the last dimension return */
1009 /* get the class of the components to create */
1011 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1013 /* The verifier guarantees that the dimension count is in the range. */
1015 /* create the component arrays */
1017 for (i = 0; i < size; i++) {
1018 java_arrayheader *ea =
1019 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1020 /* we save an s4 to a s8 slot, 8-byte aligned */
1022 builtin_multianewarray_intern(n, componentclass, dims + 2);
1024 builtin_multianewarray_intern(n, componentclass, dims + 1);
1030 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1037 /* builtin_multianewarray ******************************************************
1039 Wrapper for builtin_multianewarray_intern which checks all
1040 dimensions before we start allocating.
1042 ******************************************************************************/
1044 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1050 /* check all dimensions before doing anything */
1052 for (i = 0; i < n; i++) {
1053 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1054 /* we save an s4 to a s8 slot, 8-byte aligned */
1055 size = (s4) dims[i * 2];
1057 size = (s4) dims[i];
1061 *exceptionptr = new_negativearraysizeexception();
1066 /* now call the real function */
1068 return builtin_multianewarray_intern(n, arrayclass, dims);
1072 /*****************************************************************************
1075 Various functions for printing a message at method entry or exit (for
1078 *****************************************************************************/
1080 s4 methodindent = 0;
1082 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1091 if (opt_verbose || runverbose || opt_verboseexception) {
1092 /* when running with verbosecall we remove one indent level */
1094 if (runverbose && indent)
1097 /* calculate message length */
1101 strlen("Exception ") +
1102 utf_strlen(xptr->vftbl->class->name);
1105 logtextlen = strlen("Some Throwable");
1108 logtextlen += strlen(" thrown in ");
1112 utf_strlen(m->class->name) +
1114 utf_strlen(m->name) +
1115 utf_strlen(m->descriptor) +
1116 strlen("(NOSYNC,NATIVE");
1118 #if SIZEOF_VOID_P == 8
1120 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1122 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1125 if (m->class->sourcefile == NULL)
1126 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1128 logtextlen += utf_strlen(m->class->sourcefile);
1130 logtextlen += strlen(":65536)");
1133 logtextlen += strlen("call_java_method");
1135 logtextlen += strlen("0");
1137 /* allocate memory */
1139 dumpsize = dump_size();
1141 logtext = DMNEW(char, logtextlen);
1144 strcpy(logtext, "Exception ");
1145 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1148 strcpy(logtext, "Some Throwable");
1151 strcat(logtext, " thrown in ");
1154 utf_strcat_classname(logtext, m->class->name);
1155 strcat(logtext, ".");
1156 utf_strcat(logtext, m->name);
1157 utf_strcat(logtext, m->descriptor);
1159 if (m->flags & ACC_SYNCHRONIZED)
1160 strcat(logtext, "(SYNC");
1162 strcat(logtext, "(NOSYNC");
1164 if (m->flags & ACC_NATIVE) {
1165 strcat(logtext, ",NATIVE");
1167 #if SIZEOF_VOID_P == 8
1168 sprintf(logtext + strlen(logtext),
1169 ")(0x%016lx) at position 0x%016lx",
1170 (ptrint) m->entrypoint, (ptrint) pos);
1172 sprintf(logtext + strlen(logtext),
1173 ")(0x%08x) at position 0x%08x",
1174 (ptrint) m->entrypoint, (ptrint) pos);
1178 #if SIZEOF_VOID_P == 8
1179 sprintf(logtext + strlen(logtext),
1180 ")(0x%016lx) at position 0x%016lx (",
1181 (ptrint) m->entrypoint, (ptrint) pos);
1183 sprintf(logtext + strlen(logtext),
1184 ")(0x%08x) at position 0x%08x (",
1185 (ptrint) m->entrypoint, (ptrint) pos);
1188 if (m->class->sourcefile == NULL)
1189 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1191 utf_strcat(logtext, m->class->sourcefile);
1193 sprintf(logtext + strlen(logtext), ":%d)", 0);
1197 strcat(logtext, "call_java_method");
1201 /* release memory */
1203 dump_release(dumpsize);
1205 /* print stacktrace for exception */
1207 if (opt_verboseexception) {
1208 java_lang_Throwable *t;
1209 java_lang_VMThrowable *vmt;
1210 java_lang_Throwable *cause;
1212 stackTraceBuffer *stb;
1214 t = (java_lang_Throwable *) xptr;
1217 /* print the root exception */
1219 utf_display_classname(t->header.vftbl->class->name);
1221 if (t->detailMessage) {
1222 u = javastring_toutf(t->detailMessage, false);
1230 /* print the cause if available */
1232 if (cause && (cause != t)) {
1233 printf("Caused by: ");
1234 utf_display_classname(cause->header.vftbl->class->name);
1236 if (cause->detailMessage) {
1237 u = javastring_toutf(cause->detailMessage, false);
1246 /* now print the stacktrace */
1249 stb = (stackTraceBuffer *) vmt->vmData;
1251 stacktrace_print_trace(stb);
1259 /* builtin_trace_args **********************************************************
1263 *******************************************************************************/
1265 #ifdef TRACE_ARGS_NUM
1266 void builtin_trace_args(s8 a0, s8 a1,
1267 #if TRACE_ARGS_NUM >= 4
1269 #endif /* TRACE_ARGS_NUM >= 4 */
1270 #if TRACE_ARGS_NUM >= 6
1272 #endif /* TRACE_ARGS_NUM >= 6 */
1273 #if TRACE_ARGS_NUM == 8
1275 #endif /* TRACE_ARGS_NUM == 8 */
1287 /* calculate message length */
1290 6 + methodindent + strlen("called: ") +
1291 utf_strlen(m->class->name) +
1293 utf_strlen(m->name) +
1294 utf_strlen(m->descriptor) +
1295 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1297 /* add maximal argument length */
1299 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1301 /* allocate memory */
1303 dumpsize = dump_size();
1305 logtext = DMNEW(char, logtextlen);
1307 sprintf(logtext,"-%d-",methodindent);
1308 pos = strlen(logtext);
1310 for (i = 0; i < methodindent; i++)
1311 logtext[pos++] = '\t';
1313 strcpy(logtext + pos, "called: ");
1315 utf_strcat_classname(logtext, m->class->name);
1316 strcat(logtext, ".");
1317 utf_strcat(logtext, m->name);
1318 utf_strcat(logtext, m->descriptor);
1320 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1321 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1322 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1323 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1324 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1325 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1326 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1327 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1328 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1329 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1330 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1332 strcat(logtext, "(");
1334 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1335 /* Only Arguments in integer Registers are passed correctly here */
1336 /* long longs spilled on Stack have an wrong offset of +4 */
1337 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1338 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1339 switch (md->paramcount) {
1343 #if SIZEOF_VOID_P == 4
1345 sprintf(logtext + strlen(logtext),
1351 sprintf(logtext + strlen(logtext),
1356 #if TRACE_ARGS_NUM >= 4
1358 sprintf(logtext + strlen(logtext),
1359 "0x%llx, 0x%llx, 0x%llx",
1364 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1366 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1369 #endif /* TRACE_ARGS_NUM >= 4 */
1371 #if TRACE_ARGS_NUM >= 6
1373 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1375 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1380 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1382 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1385 #endif /* TRACE_ARGS_NUM >= 6 */
1387 #if TRACE_ARGS_NUM == 8
1389 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1391 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1393 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1397 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1399 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1401 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1403 #endif /* TRACE_ARGS_NUM == 8 */
1406 #if TRACE_ARGS_NUM == 2
1407 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1409 #elif TRACE_ARGS_NUM == 4
1410 sprintf(logtext + strlen(logtext),
1411 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1412 a0, a1, a2, a3, md->paramcount - 4);
1414 #elif TRACE_ARGS_NUM == 6
1415 sprintf(logtext + strlen(logtext),
1416 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1417 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1419 #elif TRACE_ARGS_NUM == 8
1420 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1422 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1424 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1425 , a6, a7, md->paramcount - 8);
1429 #else /* SIZEOF_VOID_P == 4 */
1432 sprintf(logtext + strlen(logtext),
1438 sprintf(logtext + strlen(logtext),
1444 sprintf(logtext + strlen(logtext),
1445 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1449 sprintf(logtext + strlen(logtext),
1450 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1454 #if TRACE_ARGS_NUM >= 6
1456 sprintf(logtext + strlen(logtext),
1457 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1458 a0, a1, a2, a3, a4);
1462 sprintf(logtext + strlen(logtext),
1463 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1464 a0, a1, a2, a3, a4, a5);
1466 #endif /* TRACE_ARGS_NUM >= 6 */
1468 #if TRACE_ARGS_NUM == 8
1470 sprintf(logtext + strlen(logtext),
1471 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1472 a0, a1, a2, a3, a4, a5, a6);
1476 sprintf(logtext + strlen(logtext),
1477 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1478 a0, a1, a2, a3, a4, a5, a6, a7);
1480 #endif /* TRACE_ARGS_NUM == 8 */
1483 #if TRACE_ARGS_NUM == 4
1484 sprintf(logtext + strlen(logtext),
1485 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1486 a0, a1, a2, a3, md->paramcount - 4);
1488 #elif TRACE_ARGS_NUM == 6
1489 sprintf(logtext + strlen(logtext),
1490 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1491 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1493 #elif TRACE_ARGS_NUM == 8
1494 sprintf(logtext + strlen(logtext),
1495 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1496 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1499 #endif /* SIZEOF_VOID_P == 4 */
1502 strcat(logtext, ")");
1506 /* release memory */
1508 dump_release(dumpsize);
1515 /* builtin_displaymethodstop ***************************************************
1519 *******************************************************************************/
1521 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1533 /* calculate message length */
1536 6 + methodindent + strlen("finished: ") +
1537 utf_strlen(m->class->name) +
1539 utf_strlen(m->name) +
1540 utf_strlen(m->descriptor) +
1541 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1543 /* add maximal argument length */
1545 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1547 /* allocate memory */
1549 dumpsize = dump_size();
1551 logtext = DMNEW(char, logtextlen);
1553 /* outdent the log message */
1558 log_text("WARNING: unmatched methodindent--");
1560 /* generate the message */
1562 sprintf(logtext,"-%d-",methodindent);
1563 pos = strlen(logtext);
1565 for (i = 0; i < methodindent; i++)
1566 logtext[pos++] = '\t';
1568 strcpy(logtext + pos, "finished: ");
1569 utf_strcat_classname(logtext, m->class->name);
1570 strcat(logtext, ".");
1571 utf_strcat(logtext, m->name);
1572 utf_strcat(logtext, m->descriptor);
1574 switch (md->returntype.type) {
1576 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1580 #if SIZEOF_VOID_P == 4
1581 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1583 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1588 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1593 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1598 #if SIZEOF_VOID_P == 4
1599 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1601 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1608 /* release memory */
1610 dump_release(dumpsize);
1614 /****************************************************************************
1615 SYNCHRONIZATION FUNCTIONS
1616 *****************************************************************************/
1618 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1620 * Lock the mutex of an object.
1622 void internal_lock_mutex_for_object(java_objectheader *object)
1624 mutexHashEntry *entry;
1627 assert(object != 0);
1629 hashValue = MUTEX_HASH_VALUE(object);
1630 entry = &mutexHashTable[hashValue];
1632 if (entry->object != 0) {
1633 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1635 entry->mutex.holder = 0;
1636 entry->mutex.count = 0;
1637 entry->mutex.muxWaiters = 0;
1640 while (entry->next != 0 && entry->object != object)
1641 entry = entry->next;
1643 if (entry->object != object) {
1644 entry->next = firstFreeOverflowEntry;
1645 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1647 entry = entry->next;
1650 assert(entry->conditionCount == 0);
1655 entry->mutex.holder = 0;
1656 entry->mutex.count = 0;
1657 entry->mutex.muxWaiters = 0;
1660 if (entry->object == 0)
1661 entry->object = object;
1663 internal_lock_mutex(&entry->mutex);
1668 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1670 * Unlocks the mutex of an object.
1672 void internal_unlock_mutex_for_object (java_objectheader *object)
1675 mutexHashEntry *entry;
1677 hashValue = MUTEX_HASH_VALUE(object);
1678 entry = &mutexHashTable[hashValue];
1680 if (entry->object == object) {
1681 internal_unlock_mutex(&entry->mutex);
1684 while (entry->next != 0 && entry->next->object != object)
1685 entry = entry->next;
1687 assert(entry->next != 0);
1689 internal_unlock_mutex(&entry->next->mutex);
1691 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1692 mutexHashEntry *unlinked = entry->next;
1694 entry->next = unlinked->next;
1695 unlinked->next = firstFreeOverflowEntry;
1696 firstFreeOverflowEntry = unlinked;
1703 #if defined(USE_THREADS)
1704 void builtin_monitorenter(java_objectheader *o)
1706 #if !defined(NATIVE_THREADS)
1711 hashValue = MUTEX_HASH_VALUE(o);
1712 if (mutexHashTable[hashValue].object == o
1713 && mutexHashTable[hashValue].mutex.holder == currentThread)
1714 ++mutexHashTable[hashValue].mutex.count;
1716 internal_lock_mutex_for_object(o);
1720 monitorEnter((threadobject *) THREADOBJECT, o);
1726 #if defined(USE_THREADS)
1728 * Locks the class object - needed for static synchronized methods.
1729 * The use_class_as_object call is needed in order to circumvent a
1730 * possible deadlock with builtin_monitorenter called by another
1731 * thread calling use_class_as_object.
1733 void builtin_staticmonitorenter(classinfo *c)
1735 use_class_as_object(c);
1736 builtin_monitorenter(&c->header);
1741 #if defined(USE_THREADS)
1742 void builtin_monitorexit(java_objectheader *o)
1744 #if !defined(NATIVE_THREADS)
1749 hashValue = MUTEX_HASH_VALUE(o);
1750 if (mutexHashTable[hashValue].object == o) {
1751 if (mutexHashTable[hashValue].mutex.count == 1
1752 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1753 internal_unlock_mutex_for_object(o);
1755 --mutexHashTable[hashValue].mutex.count;
1758 internal_unlock_mutex_for_object(o);
1762 monitorExit((threadobject *) THREADOBJECT, o);
1768 /*****************************************************************************
1769 MISCELLANEOUS HELPER FUNCTIONS
1770 *****************************************************************************/
1774 /*********** Functions for integer divisions *****************************
1776 On some systems (eg. DEC ALPHA), integer division is not supported by the
1777 CPU. These helper functions implement the missing functionality.
1779 ******************************************************************************/
1781 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1782 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1785 /************** Functions for long arithmetics *******************************
1787 On systems where 64 bit Integers are not supported by the CPU, these
1788 functions are needed.
1790 ******************************************************************************/
1792 s8 builtin_ladd(s8 a, s8 b)
1805 s8 builtin_lsub(s8 a, s8 b)
1818 s8 builtin_lmul(s8 a, s8 b)
1831 s8 builtin_ldiv(s8 a, s8 b)
1844 s8 builtin_lrem(s8 a, s8 b)
1857 s8 builtin_lshl(s8 a, s4 b)
1870 s8 builtin_lshr(s8 a, s4 b)
1883 s8 builtin_lushr(s8 a, s4 b)
1888 c = ((u8) a) >> (b & 63);
1896 s8 builtin_land(s8 a, s8 b)
1909 s8 builtin_lor(s8 a, s8 b)
1922 s8 builtin_lxor(s8 a, s8 b)
1935 s8 builtin_lneg(s8 a)
1948 s4 builtin_lcmp(s8 a, s8 b)
1951 if (a < b) return -1;
1952 if (a > b) return 1;
1963 /*********** Functions for floating point operations *************************/
1965 /* used to convert FLT_xxx defines into float values */
1967 static inline float intBitsToFloat(s4 i)
1976 /* used to convert DBL_xxx defines into double values */
1978 static inline float longBitsToDouble(s8 l)
1987 float builtin_fadd(float a, float b)
1989 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1990 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2001 if (copysignf(1.0, a) == copysignf(1.0, b))
2004 return intBitsToFloat(FLT_NAN);
2010 float builtin_fsub(float a, float b)
2012 return builtin_fadd(a, builtin_fneg(b));
2016 float builtin_fmul(float a, float b)
2018 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2019 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2021 if (finitef(b)) return a * b;
2023 if (a == 0) return intBitsToFloat(FLT_NAN);
2024 else return copysignf(b, copysignf(1.0, b)*a);
2029 if (b == 0) return intBitsToFloat(FLT_NAN);
2030 else return copysignf(a, copysignf(1.0, a)*b);
2033 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2039 /* builtin_ddiv ****************************************************************
2041 Implementation as described in VM Spec.
2043 *******************************************************************************/
2045 float builtin_fdiv(float a, float b)
2049 /* If neither value1' nor value2' is NaN, the sign of the result */
2050 /* is positive if both values have the same sign, negative if the */
2051 /* values have different signs. */
2057 /* If either value1' or value2' is NaN, the result is NaN. */
2059 return intBitsToFloat(FLT_NAN);
2062 /* Division of a finite value by an infinity results in a */
2063 /* signed zero, with the sign-producing rule just given. */
2065 /* is sign equal? */
2067 if (copysignf(1.0, a) == copysignf(1.0, b))
2076 /* If either value1' or value2' is NaN, the result is NaN. */
2078 return intBitsToFloat(FLT_NAN);
2080 } else if (finitef(b)) {
2081 /* Division of an infinity by a finite value results in a signed */
2082 /* infinity, with the sign-producing rule just given. */
2084 /* is sign equal? */
2086 if (copysignf(1.0, a) == copysignf(1.0, b))
2087 return intBitsToFloat(FLT_POSINF);
2089 return intBitsToFloat(FLT_NEGINF);
2092 /* Division of an infinity by an infinity results in NaN. */
2094 return intBitsToFloat(FLT_NAN);
2100 float builtin_frem(float a, float b)
2106 float builtin_fneg(float a)
2108 if (isnanf(a)) return a;
2110 if (finitef(a)) return -a;
2111 else return copysignf(a, -copysignf(1.0, a));
2116 s4 builtin_fcmpl(float a, float b)
2118 if (isnanf(a)) return -1;
2119 if (isnanf(b)) return -1;
2120 if (!finitef(a) || !finitef(b)) {
2121 a = finitef(a) ? 0 : copysignf(1.0, a);
2122 b = finitef(b) ? 0 : copysignf(1.0, b);
2124 if (a > b) return 1;
2125 if (a == b) return 0;
2130 s4 builtin_fcmpg(float a, float b)
2132 if (isnanf(a)) return 1;
2133 if (isnanf(b)) return 1;
2134 if (!finitef(a) || !finitef(b)) {
2135 a = finitef(a) ? 0 : copysignf(1.0, a);
2136 b = finitef(b) ? 0 : copysignf(1.0, b);
2138 if (a > b) return 1;
2139 if (a == b) return 0;
2145 /************************* Functions for doubles ****************************/
2147 double builtin_dadd(double a, double b)
2149 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2150 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2152 if (finite(b)) return a + b;
2156 if (finite(b)) return a;
2158 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2159 else return longBitsToDouble(DBL_NAN);
2165 double builtin_dsub(double a, double b)
2167 return builtin_dadd(a, builtin_dneg(b));
2171 double builtin_dmul(double a, double b)
2173 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2174 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2176 if (finite(b)) return a * b;
2178 if (a == 0) return longBitsToDouble(DBL_NAN);
2179 else return copysign(b, copysign(1.0, b) * a);
2184 if (b == 0) return longBitsToDouble(DBL_NAN);
2185 else return copysign(a, copysign(1.0, a) * b);
2188 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2194 /* builtin_ddiv ****************************************************************
2196 Implementation as described in VM Spec.
2198 *******************************************************************************/
2200 double builtin_ddiv(double a, double b)
2204 /* If neither value1' nor value2' is NaN, the sign of the result */
2205 /* is positive if both values have the same sign, negative if the */
2206 /* values have different signs. */
2212 /* If either value1' or value2' is NaN, the result is NaN. */
2214 return longBitsToDouble(DBL_NAN);
2217 /* Division of a finite value by an infinity results in a */
2218 /* signed zero, with the sign-producing rule just given. */
2220 /* is sign equal? */
2222 if (copysign(1.0, a) == copysign(1.0, b))
2231 /* If either value1' or value2' is NaN, the result is NaN. */
2233 return longBitsToDouble(DBL_NAN);
2235 } else if (finite(b)) {
2236 /* Division of an infinity by a finite value results in a signed */
2237 /* infinity, with the sign-producing rule just given. */
2239 /* is sign equal? */
2241 if (copysign(1.0, a) == copysign(1.0, b))
2242 return longBitsToDouble(DBL_POSINF);
2244 return longBitsToDouble(DBL_NEGINF);
2247 /* Division of an infinity by an infinity results in NaN. */
2249 return longBitsToDouble(DBL_NAN);
2255 double builtin_drem(double a, double b)
2260 /* builtin_dneg ****************************************************************
2262 Implemented as described in VM Spec.
2264 *******************************************************************************/
2266 double builtin_dneg(double a)
2269 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2276 /* If the operand is a zero, the result is the zero of opposite */
2282 /* If the operand is an infinity, the result is the infinity of */
2283 /* opposite sign. */
2285 return copysign(a, -copysign(1.0, a));
2291 s4 builtin_dcmpl(double a, double b)
2293 if (isnan(a)) return -1;
2294 if (isnan(b)) return -1;
2295 if (!finite(a) || !finite(b)) {
2296 a = finite(a) ? 0 : copysign(1.0, a);
2297 b = finite(b) ? 0 : copysign(1.0, b);
2299 if (a > b) return 1;
2300 if (a == b) return 0;
2305 s4 builtin_dcmpg(double a, double b)
2307 if (isnan(a)) return 1;
2308 if (isnan(b)) return 1;
2309 if (!finite(a) || !finite(b)) {
2310 a = finite(a) ? 0 : copysign(1.0, a);
2311 b = finite(b) ? 0 : copysign(1.0, b);
2313 if (a > b) return 1;
2314 if (a == b) return 0;
2319 /*********************** Conversion operations ****************************/
2321 s8 builtin_i2l(s4 i)
2334 float builtin_i2f(s4 a)
2336 float f = (float) a;
2341 double builtin_i2d(s4 a)
2343 double d = (double) a;
2348 s4 builtin_l2i(s8 l)
2358 float builtin_l2f(s8 a)
2361 float f = (float) a;
2369 double builtin_l2d(s8 a)
2372 double d = (double) a;
2380 s4 builtin_f2i(float a)
2384 i = builtin_d2i((double) a);
2395 if (a < (-2147483648))
2396 return (-2147483648);
2399 f = copysignf((float) 1.0, a);
2402 return (-2147483648); */
2406 s8 builtin_f2l(float a)
2410 l = builtin_d2l((double) a);
2417 if (a > 9223372036854775807L)
2418 return 9223372036854775807L;
2419 if (a < (-9223372036854775808L))
2420 return (-9223372036854775808L);
2425 f = copysignf((float) 1.0, a);
2427 return 9223372036854775807L;
2428 return (-9223372036854775808L); */
2432 double builtin_f2d(float a)
2434 if (finitef(a)) return (double) a;
2437 return longBitsToDouble(DBL_NAN);
2439 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2444 s4 builtin_d2i(double a)
2449 if (a >= 2147483647)
2451 if (a <= (-2147483647-1))
2452 return (-2147483647-1);
2457 d = copysign(1.0, a);
2460 return (-2147483647-1);
2464 s8 builtin_d2l(double a)
2469 if (a >= 9223372036854775807LL)
2470 return 9223372036854775807LL;
2471 if (a <= (-9223372036854775807LL-1))
2472 return (-9223372036854775807LL-1);
2477 d = copysign(1.0, a);
2479 return 9223372036854775807LL;
2480 return (-9223372036854775807LL-1);
2484 float builtin_d2f(double a)
2490 return intBitsToFloat(FLT_NAN);
2492 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2497 /* builtin_clone_array *********************************************************
2499 Wrapper function for cloning arrays.
2501 *******************************************************************************/
2503 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2505 java_arrayheader *ah;
2506 java_lang_Cloneable *c;
2508 c = (java_lang_Cloneable *) o;
2510 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2516 /* builtin_asm_get_exceptionptrptr *********************************************
2518 this is a wrapper for calls from asmpart
2520 *******************************************************************************/
2522 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2523 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2525 return builtin_get_exceptionptrptr();
2531 * These are local overrides for various environment variables in Emacs.
2532 * Please do not remove this and leave it at the end of the file, where
2533 * Emacs will automagically detect them.
2534 * ---------------------------------------------------------------------
2537 * indent-tabs-mode: t