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 3613 2005-11-07 17:57:56Z 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 *oa, java_objectheader *o)
579 arraydescriptor *desc;
580 arraydescriptor *valuedesc;
581 vftbl_t *componentvftbl;
584 castinfo classvalues;
589 /* The following is guaranteed (by verifier checks):
591 * *) a->...vftbl->arraydesc != NULL
592 * *) a->...vftbl->arraydesc->componentvftbl != NULL
593 * *) o->vftbl is not an interface vftbl
596 desc = oa->header.objheader.vftbl->arraydesc;
597 componentvftbl = desc->componentvftbl;
598 valuevftbl = o->vftbl;
600 if ((desc->dimension - 1) == 0) {
603 /* {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 */
627 if ((valuedesc = valuevftbl->arraydesc) == NULL)
630 /* {o is an array} */
632 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
636 /* This is an optimized version where a is guaranteed to be one-dimensional */
637 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
639 arraydescriptor *desc;
640 vftbl_t *elementvftbl;
644 castinfo classvalues;
648 /* The following is guaranteed (by verifier checks):
650 * *) a->...vftbl->arraydesc != NULL
651 * *) a->...vftbl->arraydesc->elementvftbl != NULL
652 * *) a->...vftbl->arraydesc->dimension == 1
653 * *) o->vftbl is not an interface vftbl
656 desc = a->header.objheader.vftbl->arraydesc;
657 elementvftbl = desc->elementvftbl;
658 valuevftbl = o->vftbl;
660 /* {a is a one-dimensional array} */
662 if (valuevftbl == elementvftbl)
665 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
667 if ((base = classvalues.super_baseval) <= 0)
668 /* an array of interface references */
669 return (valuevftbl->interfacetablelength > -base &&
670 valuevftbl->interfacetable[base] != NULL);
672 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
673 <= (unsigned) classvalues.super_diffval;
679 /* This is an optimized version where a is guaranteed to be a
680 * one-dimensional array of a class type */
681 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
683 vftbl_t *elementvftbl;
686 castinfo classvalues;
690 /* The following is guaranteed (by verifier checks):
692 * *) a->...vftbl->arraydesc != NULL
693 * *) a->...vftbl->arraydesc->elementvftbl != NULL
694 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
695 * *) a->...vftbl->arraydesc->dimension == 1
696 * *) o->vftbl is not an interface vftbl
699 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
700 valuevftbl = o->vftbl;
702 /* {a is a one-dimensional array} */
704 if (valuevftbl == elementvftbl)
707 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
709 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
710 <= (unsigned) classvalues.super_diffval;
716 /* builtin_new *****************************************************************
718 Creates a new instance of class c on the heap.
720 Return value: pointer to the object or NULL if no memory is
723 *******************************************************************************/
725 java_objectheader *builtin_new(classinfo *c)
727 java_objectheader *o;
729 /* is the class loaded */
733 /* check if we can instantiate this class */
735 if (c->flags & ACC_ABSTRACT) {
737 new_exception_utfmessage(string_java_lang_InstantiationError,
742 /* is the class linked */
747 if (!c->initialized) {
749 log_message_class("Initialize class (from builtin_new): ", c);
751 if (!initialize_class(c))
755 o = heap_allocate(c->instancesize, true, c->finalizer);
762 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
770 /* builtin_newarray ************************************************************
772 Creates an array with the given vftbl on the heap. This function
773 takes as class argument an array class.
775 Return value: pointer to the array or NULL if no memory is available
777 *******************************************************************************/
779 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
781 arraydescriptor *desc;
787 desc = arrayclass->vftbl->arraydesc;
788 dataoffset = desc->dataoffset;
789 componentsize = desc->componentsize;
792 *exceptionptr = new_negativearraysizeexception();
796 actualsize = dataoffset + size * componentsize;
798 if (((u4) actualsize) < ((u4) size)) { /* overflow */
799 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
803 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
808 a->objheader.vftbl = arrayclass->vftbl;
810 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
811 initObjectLock(&a->objheader);
820 /* builtin_anewarray ***********************************************************
822 Creates an array of references to the given class type on the heap.
824 Return value: pointer to the array or NULL if no memory is
827 *******************************************************************************/
829 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
831 classinfo *arrayclass;
833 /* is class loaded */
835 assert(componentclass->loaded);
837 /* is class linked */
839 if (!componentclass->linked)
840 if (!link_class(componentclass))
843 arrayclass = class_array_of(componentclass, true);
848 return (java_objectarray *) builtin_newarray(size, arrayclass);
852 /* builtin_newarray_boolean ****************************************************
854 Creates an array of bytes on the heap. The array is designated as
855 an array of booleans (important for casts)
857 Return value: pointer to the array or NULL if no memory is
860 *******************************************************************************/
862 java_booleanarray *builtin_newarray_boolean(s4 size)
864 return (java_booleanarray *)
865 builtin_newarray(size,
866 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
870 /* builtin_newarray_byte *******************************************************
872 Creates an array of 8 bit Integers on the heap.
874 Return value: pointer to the array or NULL if no memory is
877 *******************************************************************************/
879 java_bytearray *builtin_newarray_byte(s4 size)
881 return (java_bytearray *)
882 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
886 /* builtin_newarray_char *******************************************************
888 Creates an array of characters on the heap.
890 Return value: pointer to the array or NULL if no memory is
893 *******************************************************************************/
895 java_chararray *builtin_newarray_char(s4 size)
897 return (java_chararray *)
898 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
902 /* builtin_newarray_short ******************************************************
904 Creates an array of 16 bit Integers on the heap.
906 Return value: pointer to the array or NULL if no memory is
909 *******************************************************************************/
911 java_shortarray *builtin_newarray_short(s4 size)
913 return (java_shortarray *)
914 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
918 /* builtin_newarray_int ********************************************************
920 Creates an array of 32 bit Integers on the heap.
922 Return value: pointer to the array or NULL if no memory is
925 *******************************************************************************/
927 java_intarray *builtin_newarray_int(s4 size)
929 return (java_intarray *)
930 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
934 /* builtin_newarray_long *******************************************************
936 Creates an array of 64 bit Integers on the heap.
938 Return value: pointer to the array or NULL if no memory is
941 *******************************************************************************/
943 java_longarray *builtin_newarray_long(s4 size)
945 return (java_longarray *)
946 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
950 /* builtin_newarray_float ******************************************************
952 Creates an array of 32 bit IEEE floats on the heap.
954 Return value: pointer to the array or NULL if no memory is
957 *******************************************************************************/
959 java_floatarray *builtin_newarray_float(s4 size)
961 return (java_floatarray *)
962 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
966 /* builtin_newarray_double *****************************************************
968 Creates an array of 64 bit IEEE floats on the heap.
970 Return value: pointer to the array or NULL if no memory is
973 *******************************************************************************/
975 java_doublearray *builtin_newarray_double(s4 size)
977 return (java_doublearray *)
978 builtin_newarray(size,
979 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
983 /* builtin_multianewarray_intern ***********************************************
985 Creates a multi-dimensional array on the heap. The dimensions are
986 passed in an array of longs.
989 n............number of dimensions to create
990 arrayvftbl...vftbl of the array class
991 dims.........array containing the size of each dimension to create
993 Return value: pointer to the array or NULL if no memory is
996 ******************************************************************************/
998 static java_arrayheader *builtin_multianewarray_intern(int n,
999 classinfo *arrayclass,
1003 java_arrayheader *a;
1004 classinfo *componentclass;
1007 /* create this dimension */
1009 size = (s4) dims[0];
1010 a = builtin_newarray(size, arrayclass);
1015 /* if this is the last dimension return */
1020 /* get the class of the components to create */
1022 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1024 /* The verifier guarantees that the dimension count is in the range. */
1026 /* create the component arrays */
1028 for (i = 0; i < size; i++) {
1029 java_arrayheader *ea =
1030 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1031 /* we save an s4 to a s8 slot, 8-byte aligned */
1033 builtin_multianewarray_intern(n, componentclass, dims + 2);
1035 builtin_multianewarray_intern(n, componentclass, dims + 1);
1041 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1048 /* builtin_multianewarray ******************************************************
1050 Wrapper for builtin_multianewarray_intern which checks all
1051 dimensions before we start allocating.
1053 ******************************************************************************/
1055 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1061 /* check all dimensions before doing anything */
1063 for (i = 0; i < n; i++) {
1064 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1065 /* we save an s4 to a s8 slot, 8-byte aligned */
1066 size = (s4) dims[i * 2];
1068 size = (s4) dims[i];
1072 *exceptionptr = new_negativearraysizeexception();
1077 /* now call the real function */
1079 return builtin_multianewarray_intern(n, arrayclass, dims);
1083 /*****************************************************************************
1086 Various functions for printing a message at method entry or exit (for
1089 *****************************************************************************/
1091 s4 methodindent = 0;
1093 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1102 if (opt_verbose || runverbose || opt_verboseexception) {
1103 /* when running with verbosecall we remove one indent level */
1105 if (runverbose && indent)
1108 /* calculate message length */
1112 strlen("Exception ") +
1113 utf_strlen(xptr->vftbl->class->name);
1116 logtextlen = strlen("Some Throwable");
1119 logtextlen += strlen(" thrown in ");
1123 utf_strlen(m->class->name) +
1125 utf_strlen(m->name) +
1126 utf_strlen(m->descriptor) +
1127 strlen("(NOSYNC,NATIVE");
1129 #if SIZEOF_VOID_P == 8
1131 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1133 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1136 if (m->class->sourcefile == NULL)
1137 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1139 logtextlen += utf_strlen(m->class->sourcefile);
1141 logtextlen += strlen(":65536)");
1144 logtextlen += strlen("call_java_method");
1146 logtextlen += strlen("0");
1148 /* allocate memory */
1150 dumpsize = dump_size();
1152 logtext = DMNEW(char, logtextlen);
1155 strcpy(logtext, "Exception ");
1156 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1159 strcpy(logtext, "Some Throwable");
1162 strcat(logtext, " thrown in ");
1165 utf_strcat_classname(logtext, m->class->name);
1166 strcat(logtext, ".");
1167 utf_strcat(logtext, m->name);
1168 utf_strcat(logtext, m->descriptor);
1170 if (m->flags & ACC_SYNCHRONIZED)
1171 strcat(logtext, "(SYNC");
1173 strcat(logtext, "(NOSYNC");
1175 if (m->flags & ACC_NATIVE) {
1176 strcat(logtext, ",NATIVE");
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);
1189 #if SIZEOF_VOID_P == 8
1190 sprintf(logtext + strlen(logtext),
1191 ")(0x%016lx) at position 0x%016lx (",
1192 (ptrint) m->entrypoint, (ptrint) pos);
1194 sprintf(logtext + strlen(logtext),
1195 ")(0x%08x) at position 0x%08x (",
1196 (ptrint) m->entrypoint, (ptrint) pos);
1199 if (m->class->sourcefile == NULL)
1200 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1202 utf_strcat(logtext, m->class->sourcefile);
1204 sprintf(logtext + strlen(logtext), ":%d)", 0);
1208 strcat(logtext, "call_java_method");
1212 /* release memory */
1214 dump_release(dumpsize);
1216 /* print stacktrace for exception */
1218 if (opt_verboseexception) {
1219 java_lang_Throwable *t;
1220 java_lang_VMThrowable *vmt;
1221 java_lang_Throwable *cause;
1223 stackTraceBuffer *stb;
1225 t = (java_lang_Throwable *) xptr;
1228 /* print the root exception */
1230 utf_display_classname(t->header.vftbl->class->name);
1232 if (t->detailMessage) {
1233 u = javastring_toutf(t->detailMessage, false);
1241 /* print the cause if available */
1243 if (cause && (cause != t)) {
1244 printf("Caused by: ");
1245 utf_display_classname(cause->header.vftbl->class->name);
1247 if (cause->detailMessage) {
1248 u = javastring_toutf(cause->detailMessage, false);
1257 /* now print the stacktrace */
1260 stb = (stackTraceBuffer *) vmt->vmData;
1262 stacktrace_print_trace(stb);
1270 /* builtin_trace_args **********************************************************
1274 *******************************************************************************/
1276 #ifdef TRACE_ARGS_NUM
1277 void builtin_trace_args(s8 a0, s8 a1,
1278 #if TRACE_ARGS_NUM >= 4
1280 #endif /* TRACE_ARGS_NUM >= 4 */
1281 #if TRACE_ARGS_NUM >= 6
1283 #endif /* TRACE_ARGS_NUM >= 6 */
1284 #if TRACE_ARGS_NUM == 8
1286 #endif /* TRACE_ARGS_NUM == 8 */
1298 /* calculate message length */
1301 6 + methodindent + strlen("called: ") +
1302 utf_strlen(m->class->name) +
1304 utf_strlen(m->name) +
1305 utf_strlen(m->descriptor) +
1306 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1308 /* add maximal argument length */
1310 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1312 /* allocate memory */
1314 dumpsize = dump_size();
1316 logtext = DMNEW(char, logtextlen);
1318 sprintf(logtext,"-%d-",methodindent);
1319 pos = strlen(logtext);
1321 for (i = 0; i < methodindent; i++)
1322 logtext[pos++] = '\t';
1324 strcpy(logtext + pos, "called: ");
1326 utf_strcat_classname(logtext, m->class->name);
1327 strcat(logtext, ".");
1328 utf_strcat(logtext, m->name);
1329 utf_strcat(logtext, m->descriptor);
1331 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1332 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1333 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1334 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1335 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1336 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1337 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1338 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1339 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1340 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1341 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1343 strcat(logtext, "(");
1345 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1346 /* Only Arguments in integer Registers are passed correctly here */
1347 /* long longs spilled on Stack have an wrong offset of +4 */
1348 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1349 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1350 switch (md->paramcount) {
1354 #if SIZEOF_VOID_P == 4
1356 sprintf(logtext + strlen(logtext),
1362 sprintf(logtext + strlen(logtext),
1367 #if TRACE_ARGS_NUM >= 4
1369 sprintf(logtext + strlen(logtext),
1370 "0x%llx, 0x%llx, 0x%llx",
1375 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1377 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1380 #endif /* TRACE_ARGS_NUM >= 4 */
1382 #if TRACE_ARGS_NUM >= 6
1384 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1386 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1391 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1393 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1396 #endif /* TRACE_ARGS_NUM >= 6 */
1398 #if TRACE_ARGS_NUM == 8
1400 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1402 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1404 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1408 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1410 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1412 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1414 #endif /* TRACE_ARGS_NUM == 8 */
1417 #if TRACE_ARGS_NUM == 2
1418 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1420 #elif TRACE_ARGS_NUM == 4
1421 sprintf(logtext + strlen(logtext),
1422 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1423 a0, a1, a2, a3, md->paramcount - 4);
1425 #elif TRACE_ARGS_NUM == 6
1426 sprintf(logtext + strlen(logtext),
1427 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1428 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1430 #elif TRACE_ARGS_NUM == 8
1431 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1433 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1435 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1436 , a6, a7, md->paramcount - 8);
1440 #else /* SIZEOF_VOID_P == 4 */
1443 sprintf(logtext + strlen(logtext),
1449 sprintf(logtext + strlen(logtext),
1455 sprintf(logtext + strlen(logtext),
1456 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1460 sprintf(logtext + strlen(logtext),
1461 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1465 #if TRACE_ARGS_NUM >= 6
1467 sprintf(logtext + strlen(logtext),
1468 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1469 a0, a1, a2, a3, a4);
1473 sprintf(logtext + strlen(logtext),
1474 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1475 a0, a1, a2, a3, a4, a5);
1477 #endif /* TRACE_ARGS_NUM >= 6 */
1479 #if TRACE_ARGS_NUM == 8
1481 sprintf(logtext + strlen(logtext),
1482 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1483 a0, a1, a2, a3, a4, a5, a6);
1487 sprintf(logtext + strlen(logtext),
1488 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1489 a0, a1, a2, a3, a4, a5, a6, a7);
1491 #endif /* TRACE_ARGS_NUM == 8 */
1494 #if TRACE_ARGS_NUM == 4
1495 sprintf(logtext + strlen(logtext),
1496 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1497 a0, a1, a2, a3, md->paramcount - 4);
1499 #elif TRACE_ARGS_NUM == 6
1500 sprintf(logtext + strlen(logtext),
1501 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1502 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1504 #elif TRACE_ARGS_NUM == 8
1505 sprintf(logtext + strlen(logtext),
1506 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1507 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1510 #endif /* SIZEOF_VOID_P == 4 */
1513 strcat(logtext, ")");
1517 /* release memory */
1519 dump_release(dumpsize);
1526 /* builtin_displaymethodstop ***************************************************
1530 *******************************************************************************/
1532 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1544 /* calculate message length */
1547 6 + methodindent + strlen("finished: ") +
1548 utf_strlen(m->class->name) +
1550 utf_strlen(m->name) +
1551 utf_strlen(m->descriptor) +
1552 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1554 /* add maximal argument length */
1556 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1558 /* allocate memory */
1560 dumpsize = dump_size();
1562 logtext = DMNEW(char, logtextlen);
1564 /* outdent the log message */
1569 log_text("WARNING: unmatched methodindent--");
1571 /* generate the message */
1573 sprintf(logtext,"-%d-",methodindent);
1574 pos = strlen(logtext);
1576 for (i = 0; i < methodindent; i++)
1577 logtext[pos++] = '\t';
1579 strcpy(logtext + pos, "finished: ");
1580 utf_strcat_classname(logtext, m->class->name);
1581 strcat(logtext, ".");
1582 utf_strcat(logtext, m->name);
1583 utf_strcat(logtext, m->descriptor);
1585 switch (md->returntype.type) {
1587 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1591 #if SIZEOF_VOID_P == 4
1592 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1594 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1599 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1604 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1609 #if SIZEOF_VOID_P == 4
1610 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1612 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1619 /* release memory */
1621 dump_release(dumpsize);
1625 /****************************************************************************
1626 SYNCHRONIZATION FUNCTIONS
1627 *****************************************************************************/
1629 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1631 * Lock the mutex of an object.
1633 void internal_lock_mutex_for_object(java_objectheader *object)
1635 mutexHashEntry *entry;
1638 assert(object != 0);
1640 hashValue = MUTEX_HASH_VALUE(object);
1641 entry = &mutexHashTable[hashValue];
1643 if (entry->object != 0) {
1644 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1646 entry->mutex.holder = 0;
1647 entry->mutex.count = 0;
1648 entry->mutex.muxWaiters = 0;
1651 while (entry->next != 0 && entry->object != object)
1652 entry = entry->next;
1654 if (entry->object != object) {
1655 entry->next = firstFreeOverflowEntry;
1656 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1658 entry = entry->next;
1661 assert(entry->conditionCount == 0);
1666 entry->mutex.holder = 0;
1667 entry->mutex.count = 0;
1668 entry->mutex.muxWaiters = 0;
1671 if (entry->object == 0)
1672 entry->object = object;
1674 internal_lock_mutex(&entry->mutex);
1679 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1681 * Unlocks the mutex of an object.
1683 void internal_unlock_mutex_for_object (java_objectheader *object)
1686 mutexHashEntry *entry;
1688 hashValue = MUTEX_HASH_VALUE(object);
1689 entry = &mutexHashTable[hashValue];
1691 if (entry->object == object) {
1692 internal_unlock_mutex(&entry->mutex);
1695 while (entry->next != 0 && entry->next->object != object)
1696 entry = entry->next;
1698 assert(entry->next != 0);
1700 internal_unlock_mutex(&entry->next->mutex);
1702 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1703 mutexHashEntry *unlinked = entry->next;
1705 entry->next = unlinked->next;
1706 unlinked->next = firstFreeOverflowEntry;
1707 firstFreeOverflowEntry = unlinked;
1714 #if defined(USE_THREADS)
1715 void builtin_monitorenter(java_objectheader *o)
1717 #if !defined(NATIVE_THREADS)
1722 hashValue = MUTEX_HASH_VALUE(o);
1723 if (mutexHashTable[hashValue].object == o
1724 && mutexHashTable[hashValue].mutex.holder == currentThread)
1725 ++mutexHashTable[hashValue].mutex.count;
1727 internal_lock_mutex_for_object(o);
1731 monitorEnter((threadobject *) THREADOBJECT, o);
1737 #if defined(USE_THREADS)
1739 * Locks the class object - needed for static synchronized methods.
1740 * The use_class_as_object call is needed in order to circumvent a
1741 * possible deadlock with builtin_monitorenter called by another
1742 * thread calling use_class_as_object.
1744 void builtin_staticmonitorenter(classinfo *c)
1746 use_class_as_object(c);
1747 builtin_monitorenter(&c->header);
1752 #if defined(USE_THREADS)
1753 void builtin_monitorexit(java_objectheader *o)
1755 #if !defined(NATIVE_THREADS)
1760 hashValue = MUTEX_HASH_VALUE(o);
1761 if (mutexHashTable[hashValue].object == o) {
1762 if (mutexHashTable[hashValue].mutex.count == 1
1763 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1764 internal_unlock_mutex_for_object(o);
1766 --mutexHashTable[hashValue].mutex.count;
1769 internal_unlock_mutex_for_object(o);
1773 monitorExit((threadobject *) THREADOBJECT, o);
1779 /*****************************************************************************
1780 MISCELLANEOUS HELPER FUNCTIONS
1781 *****************************************************************************/
1785 /*********** Functions for integer divisions *****************************
1787 On some systems (eg. DEC ALPHA), integer division is not supported by the
1788 CPU. These helper functions implement the missing functionality.
1790 ******************************************************************************/
1792 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1793 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1796 /************** Functions for long arithmetics *******************************
1798 On systems where 64 bit Integers are not supported by the CPU, these
1799 functions are needed.
1801 ******************************************************************************/
1803 s8 builtin_ladd(s8 a, s8 b)
1816 s8 builtin_lsub(s8 a, s8 b)
1829 s8 builtin_lmul(s8 a, s8 b)
1842 s8 builtin_ldiv(s8 a, s8 b)
1855 s8 builtin_lrem(s8 a, s8 b)
1868 s8 builtin_lshl(s8 a, s4 b)
1881 s8 builtin_lshr(s8 a, s4 b)
1894 s8 builtin_lushr(s8 a, s4 b)
1899 c = ((u8) a) >> (b & 63);
1907 s8 builtin_land(s8 a, s8 b)
1920 s8 builtin_lor(s8 a, s8 b)
1933 s8 builtin_lxor(s8 a, s8 b)
1946 s8 builtin_lneg(s8 a)
1959 s4 builtin_lcmp(s8 a, s8 b)
1962 if (a < b) return -1;
1963 if (a > b) return 1;
1974 /*********** Functions for floating point operations *************************/
1976 /* used to convert FLT_xxx defines into float values */
1978 static inline float intBitsToFloat(s4 i)
1987 /* used to convert DBL_xxx defines into double values */
1989 static inline float longBitsToDouble(s8 l)
1998 float builtin_fadd(float a, float b)
2000 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2001 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2012 if (copysignf(1.0, a) == copysignf(1.0, b))
2015 return intBitsToFloat(FLT_NAN);
2021 float builtin_fsub(float a, float b)
2023 return builtin_fadd(a, builtin_fneg(b));
2027 float builtin_fmul(float a, float b)
2029 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2030 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2032 if (finitef(b)) return a * b;
2034 if (a == 0) return intBitsToFloat(FLT_NAN);
2035 else return copysignf(b, copysignf(1.0, b)*a);
2040 if (b == 0) return intBitsToFloat(FLT_NAN);
2041 else return copysignf(a, copysignf(1.0, a)*b);
2044 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2050 /* builtin_ddiv ****************************************************************
2052 Implementation as described in VM Spec.
2054 *******************************************************************************/
2056 float builtin_fdiv(float a, float b)
2060 /* If neither value1' nor value2' is NaN, the sign of the result */
2061 /* is positive if both values have the same sign, negative if the */
2062 /* values have different signs. */
2068 /* If either value1' or value2' is NaN, the result is NaN. */
2070 return intBitsToFloat(FLT_NAN);
2073 /* Division of a finite value by an infinity results in a */
2074 /* signed zero, with the sign-producing rule just given. */
2076 /* is sign equal? */
2078 if (copysignf(1.0, a) == copysignf(1.0, b))
2087 /* If either value1' or value2' is NaN, the result is NaN. */
2089 return intBitsToFloat(FLT_NAN);
2091 } else if (finitef(b)) {
2092 /* Division of an infinity by a finite value results in a signed */
2093 /* infinity, with the sign-producing rule just given. */
2095 /* is sign equal? */
2097 if (copysignf(1.0, a) == copysignf(1.0, b))
2098 return intBitsToFloat(FLT_POSINF);
2100 return intBitsToFloat(FLT_NEGINF);
2103 /* Division of an infinity by an infinity results in NaN. */
2105 return intBitsToFloat(FLT_NAN);
2111 float builtin_frem(float a, float b)
2117 float builtin_fneg(float a)
2119 if (isnanf(a)) return a;
2121 if (finitef(a)) return -a;
2122 else return copysignf(a, -copysignf(1.0, a));
2127 s4 builtin_fcmpl(float a, float b)
2129 if (isnanf(a)) return -1;
2130 if (isnanf(b)) return -1;
2131 if (!finitef(a) || !finitef(b)) {
2132 a = finitef(a) ? 0 : copysignf(1.0, a);
2133 b = finitef(b) ? 0 : copysignf(1.0, b);
2135 if (a > b) return 1;
2136 if (a == b) return 0;
2141 s4 builtin_fcmpg(float a, float b)
2143 if (isnanf(a)) return 1;
2144 if (isnanf(b)) return 1;
2145 if (!finitef(a) || !finitef(b)) {
2146 a = finitef(a) ? 0 : copysignf(1.0, a);
2147 b = finitef(b) ? 0 : copysignf(1.0, b);
2149 if (a > b) return 1;
2150 if (a == b) return 0;
2156 /************************* Functions for doubles ****************************/
2158 double builtin_dadd(double a, double b)
2160 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2161 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2163 if (finite(b)) return a + b;
2167 if (finite(b)) return a;
2169 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2170 else return longBitsToDouble(DBL_NAN);
2176 double builtin_dsub(double a, double b)
2178 return builtin_dadd(a, builtin_dneg(b));
2182 double builtin_dmul(double a, double b)
2184 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2185 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2187 if (finite(b)) return a * b;
2189 if (a == 0) return longBitsToDouble(DBL_NAN);
2190 else return copysign(b, copysign(1.0, b) * a);
2195 if (b == 0) return longBitsToDouble(DBL_NAN);
2196 else return copysign(a, copysign(1.0, a) * b);
2199 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2205 /* builtin_ddiv ****************************************************************
2207 Implementation as described in VM Spec.
2209 *******************************************************************************/
2211 double builtin_ddiv(double a, double b)
2215 /* If neither value1' nor value2' is NaN, the sign of the result */
2216 /* is positive if both values have the same sign, negative if the */
2217 /* values have different signs. */
2223 /* If either value1' or value2' is NaN, the result is NaN. */
2225 return longBitsToDouble(DBL_NAN);
2228 /* Division of a finite value by an infinity results in a */
2229 /* signed zero, with the sign-producing rule just given. */
2231 /* is sign equal? */
2233 if (copysign(1.0, a) == copysign(1.0, b))
2242 /* If either value1' or value2' is NaN, the result is NaN. */
2244 return longBitsToDouble(DBL_NAN);
2246 } else if (finite(b)) {
2247 /* Division of an infinity by a finite value results in a signed */
2248 /* infinity, with the sign-producing rule just given. */
2250 /* is sign equal? */
2252 if (copysign(1.0, a) == copysign(1.0, b))
2253 return longBitsToDouble(DBL_POSINF);
2255 return longBitsToDouble(DBL_NEGINF);
2258 /* Division of an infinity by an infinity results in NaN. */
2260 return longBitsToDouble(DBL_NAN);
2266 double builtin_drem(double a, double b)
2271 /* builtin_dneg ****************************************************************
2273 Implemented as described in VM Spec.
2275 *******************************************************************************/
2277 double builtin_dneg(double a)
2280 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2287 /* If the operand is a zero, the result is the zero of opposite */
2293 /* If the operand is an infinity, the result is the infinity of */
2294 /* opposite sign. */
2296 return copysign(a, -copysign(1.0, a));
2302 s4 builtin_dcmpl(double a, double b)
2304 if (isnan(a)) return -1;
2305 if (isnan(b)) return -1;
2306 if (!finite(a) || !finite(b)) {
2307 a = finite(a) ? 0 : copysign(1.0, a);
2308 b = finite(b) ? 0 : copysign(1.0, b);
2310 if (a > b) return 1;
2311 if (a == b) return 0;
2316 s4 builtin_dcmpg(double a, double b)
2318 if (isnan(a)) return 1;
2319 if (isnan(b)) return 1;
2320 if (!finite(a) || !finite(b)) {
2321 a = finite(a) ? 0 : copysign(1.0, a);
2322 b = finite(b) ? 0 : copysign(1.0, b);
2324 if (a > b) return 1;
2325 if (a == b) return 0;
2330 /*********************** Conversion operations ****************************/
2332 s8 builtin_i2l(s4 i)
2345 float builtin_i2f(s4 a)
2347 float f = (float) a;
2352 double builtin_i2d(s4 a)
2354 double d = (double) a;
2359 s4 builtin_l2i(s8 l)
2369 float builtin_l2f(s8 a)
2372 float f = (float) a;
2380 double builtin_l2d(s8 a)
2383 double d = (double) a;
2391 s4 builtin_f2i(float a)
2395 i = builtin_d2i((double) a);
2406 if (a < (-2147483648))
2407 return (-2147483648);
2410 f = copysignf((float) 1.0, a);
2413 return (-2147483648); */
2417 s8 builtin_f2l(float a)
2421 l = builtin_d2l((double) a);
2428 if (a > 9223372036854775807L)
2429 return 9223372036854775807L;
2430 if (a < (-9223372036854775808L))
2431 return (-9223372036854775808L);
2436 f = copysignf((float) 1.0, a);
2438 return 9223372036854775807L;
2439 return (-9223372036854775808L); */
2443 double builtin_f2d(float a)
2445 if (finitef(a)) return (double) a;
2448 return longBitsToDouble(DBL_NAN);
2450 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2455 s4 builtin_d2i(double a)
2460 if (a >= 2147483647)
2462 if (a <= (-2147483647-1))
2463 return (-2147483647-1);
2468 d = copysign(1.0, a);
2471 return (-2147483647-1);
2475 s8 builtin_d2l(double a)
2480 if (a >= 9223372036854775807LL)
2481 return 9223372036854775807LL;
2482 if (a <= (-9223372036854775807LL-1))
2483 return (-9223372036854775807LL-1);
2488 d = copysign(1.0, a);
2490 return 9223372036854775807LL;
2491 return (-9223372036854775807LL-1);
2495 float builtin_d2f(double a)
2501 return intBitsToFloat(FLT_NAN);
2503 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2508 /* builtin_clone_array *********************************************************
2510 Wrapper function for cloning arrays.
2512 *******************************************************************************/
2514 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2516 java_arrayheader *ah;
2517 java_lang_Cloneable *c;
2519 c = (java_lang_Cloneable *) o;
2521 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2527 /* builtin_asm_get_exceptionptrptr *********************************************
2529 this is a wrapper for calls from asmpart
2531 *******************************************************************************/
2533 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2534 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2536 return builtin_get_exceptionptrptr();
2542 * These are local overrides for various environment variables in Emacs.
2543 * Please do not remove this and leave it at the end of the file, where
2544 * Emacs will automagically detect them.
2545 * ---------------------------------------------------------------------
2548 * indent-tabs-mode: t