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 3239 2005-09-21 14:09:22Z twisti $
54 #include "classpath/native/fdlibm/fdlibm.h"
57 #include "mm/memory.h"
58 #include "native/native.h"
59 #include "native/include/java_lang_Cloneable.h"
60 #include "native/include/java_lang_Object.h" /* required by VMObject */
61 #include "native/include/java_lang_VMObject.h"
63 #if defined(USE_THREADS)
64 # if defined(NATIVE_THREADS)
65 # include "threads/native/threads.h"
67 # include "threads/green/threads.h"
68 # include "threads/green/locks.h"
72 #include "toolbox/logging.h"
73 #include "toolbox/util.h"
74 #include "vm/builtin.h"
75 #include "vm/exceptions.h"
76 #include "vm/global.h"
77 #include "vm/initialize.h"
78 #include "vm/loader.h"
79 #include "vm/options.h"
80 #include "vm/stringlocal.h"
81 #include "vm/tables.h"
82 #include "vm/jit/asmpart.h"
83 #include "vm/jit/patcher.h"
86 /* include builtin tables *****************************************************/
88 #include "vm/builtintable.inc"
91 /* builtintable_init ***********************************************************
93 Parse the descriptors of builtin functions and create the parsed
96 *******************************************************************************/
98 static bool builtintable_init(void)
100 descriptor_pool *descpool;
104 s4 entries_automatic;
107 /* mark start of dump memory area */
109 dumpsize = dump_size();
111 /* create a new descriptor pool */
113 descpool = descriptor_pool_new(class_java_lang_Object);
115 /* add some entries we need */
117 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
120 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
123 /* calculate table entries statically */
126 sizeof(builtintable_internal) / sizeof(builtintable_entry);
129 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
130 - 1; /* last filler entry (comment see builtintable.inc) */
132 /* first add all descriptors to the pool */
134 for (i = 0; i < entries_internal; i++) {
135 /* create a utf8 string from descriptor */
137 descriptor = utf_new_char(builtintable_internal[i].descriptor);
139 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
140 /* release dump area */
142 dump_release(dumpsize);
148 for (i = 0; i < entries_automatic; i++) {
149 /* create a utf8 string from descriptor */
151 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
153 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
154 /* release dump area */
156 dump_release(dumpsize);
162 /* create the class reference table */
164 (void) descriptor_pool_create_classrefs(descpool, NULL);
166 /* allocate space for the parsed descriptors */
168 descriptor_pool_alloc_parsed_descriptors(descpool);
170 /* now parse all descriptors */
172 for (i = 0; i < entries_internal; i++) {
173 /* create a utf8 string from descriptor */
175 descriptor = utf_new_char(builtintable_internal[i].descriptor);
177 /* parse the descriptor, builtin is always static (no `this' pointer) */
179 builtintable_internal[i].md =
180 descriptor_pool_parse_method_descriptor(descpool, descriptor,
184 for (i = 0; i < entries_automatic; i++) {
185 /* create a utf8 string from descriptor */
187 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
189 /* parse the descriptor, builtin is always static (no `this' pointer) */
191 builtintable_automatic[i].md =
192 descriptor_pool_parse_method_descriptor(descpool, descriptor,
196 /* release dump area */
198 dump_release(dumpsize);
204 /* builtintable_comparator *****************************************************
206 qsort comparator for the automatic builtin table.
208 *******************************************************************************/
210 static int builtintable_comparator(const void *a, const void *b)
212 builtintable_entry *bte1;
213 builtintable_entry *bte2;
215 bte1 = (builtintable_entry *) a;
216 bte2 = (builtintable_entry *) b;
218 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
222 /* builtintable_sort_automatic *************************************************
224 Sorts the automatic builtin table.
226 *******************************************************************************/
228 static void builtintable_sort_automatic(void)
232 /* calculate table size statically (`- 1' comment see builtintable.inc) */
234 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
236 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
237 builtintable_comparator);
241 /* builtin_init ****************************************************************
245 *******************************************************************************/
247 bool builtin_init(void)
249 /* initialize the builtin tables */
251 if (!builtintable_init())
254 /* sort builtin tables */
256 builtintable_sort_automatic();
262 /* builtintable_get_internal ***************************************************
264 Finds an entry in the builtintable for internal functions and
265 returns the a pointer to the structure.
267 *******************************************************************************/
269 builtintable_entry *builtintable_get_internal(functionptr fp)
273 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
274 if (builtintable_internal[i].fp == fp)
275 return &builtintable_internal[i];
282 /* builtintable_get_automatic **************************************************
284 Finds an entry in the builtintable for functions which are replaced
285 automatically and returns the a pointer to the structure.
287 *******************************************************************************/
289 builtintable_entry *builtintable_get_automatic(s4 opcode)
291 builtintable_entry *first;
292 builtintable_entry *last;
293 builtintable_entry *middle;
297 /* calculate table size statically (`- 1' comment see builtintable.inc) */
299 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
301 first = builtintable_automatic;
302 last = builtintable_automatic + entries;
304 while (entries > 0) {
306 middle = first + half;
308 if (middle->opcode < opcode) {
315 return (first != last ? first : NULL);
319 /*****************************************************************************
321 *****************************************************************************/
325 /*************** internal function: builtin_isanysubclass *********************
327 Checks a subclass relation between two classes. Implemented interfaces
328 are interpreted as super classes.
329 Return value: 1 ... sub is subclass of super
332 *****************************************************************************/
333 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
336 castinfo classvalues;
341 if (super->flags & ACC_INTERFACE) {
342 res = (sub->vftbl->interfacetablelength > super->index) &&
343 (sub->vftbl->interfacetable[-super->index] != NULL);
346 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
348 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
349 (u4) classvalues.super_diffval;
356 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
360 castinfo classvalues;
365 asm_getclassvalues_atomic(super, sub, &classvalues);
367 if ((base = classvalues.super_baseval) <= 0) {
368 /* super is an interface */
369 res = (sub->interfacetablelength > -base) &&
370 (sub->interfacetable[base] != NULL);
372 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
373 <= (u4) classvalues.super_diffval;
380 /****************** function: builtin_instanceof *****************************
382 Checks if an object is an instance of some given class (or subclass of
383 that class). If class is an interface, checks if the interface is
385 Return value: 1 ... obj is an instance of class or implements the interface
386 0 ... otherwise or if obj == NULL
388 *****************************************************************************/
390 /* XXX should use vftbl */
391 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
396 return builtin_isanysubclass(obj->vftbl->class, class);
401 /**************** function: builtin_checkcast *******************************
403 The same as builtin_instanceof except that 1 is returned when
406 ****************************************************************************/
408 /* XXX should use vftbl */
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, arraydescriptor *target)
435 if (desc->arraytype != target->arraytype)
438 if (desc->arraytype != ARRAYTYPE_OBJECT)
441 /* {both arrays are arrays of references} */
443 if (desc->dimension == target->dimension) {
444 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
445 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
446 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
448 if (desc->dimension < target->dimension) return 0;
450 /* {desc has higher dimension than target} */
451 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
455 /* builtin_arraycheckcast ******************************************************
457 Checks if an object is really a subtype of the requested array
458 type. The object has to be an array to begin with. For simple
459 arrays (int, short, double, etc.) the types have to match exactly.
460 For arrays of objects, the type of elements in the array has to be
461 a subtype (or the same type) of the requested element type. For
462 arrays of arrays (which in turn can again be arrays of arrays), the
463 types at the lowest level have to satisfy the corresponding sub
466 *******************************************************************************/
468 s4 builtin_arraycheckcast(java_objectheader *o, vftbl_t *target)
470 arraydescriptor *desc;
475 if ((desc = o->vftbl->arraydesc) == NULL)
478 return builtin_descriptorscompatible(desc, target->arraydesc);
482 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
487 return builtin_arraycheckcast(obj, target);
491 /************************** exception functions *******************************
493 ******************************************************************************/
495 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
497 java_lang_Throwable *t;
503 t = (java_lang_Throwable *) xptr;
505 /* calculate message length */
507 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
511 utf_strlen(xptr->vftbl->class->name) +
513 javastring_strlen((java_objectheader *) t->detailMessage);
516 logtextlen += strlen("(nil)");
518 /* allocate memory */
520 dumpsize = dump_size();
522 logtext = DMNEW(char, logtextlen);
524 strcpy(logtext, "Builtin exception thrown: ");
527 utf_sprint_classname(logtext + strlen(logtext),
528 xptr->vftbl->class->name);
530 if (t->detailMessage) {
533 buf = javastring_tochar((java_objectheader *) t->detailMessage);
534 strcat(logtext, ": ");
535 strcat(logtext, buf);
536 MFREE(buf, char, strlen(buf));
540 strcat(logtext, "(nil)");
547 dump_release(dumpsize);
550 *exceptionptr = xptr;
557 /* builtin_canstore ************************************************************
559 Checks, if an object can be stored in an array.
561 Return value: 1 ... possible
564 *******************************************************************************/
566 s4 builtin_canstore(java_objectarray *a, java_objectheader *o)
568 arraydescriptor *desc;
569 arraydescriptor *valuedesc;
570 vftbl_t *componentvftbl;
573 castinfo classvalues;
578 /* The following is guaranteed (by verifier checks):
580 * *) a->...vftbl->arraydesc != NULL
581 * *) a->...vftbl->arraydesc->componentvftbl != NULL
582 * *) o->vftbl is not an interface vftbl
585 desc = a->header.objheader.vftbl->arraydesc;
586 componentvftbl = desc->componentvftbl;
587 valuevftbl = o->vftbl;
589 if ((desc->dimension - 1) == 0) {
592 /* {a is a one-dimensional array} */
593 /* {a is an array of references} */
595 if (valuevftbl == componentvftbl)
598 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
600 if ((base = classvalues.super_baseval) <= 0)
601 /* an array of interface references */
602 return (valuevftbl->interfacetablelength > -base &&
603 valuevftbl->interfacetable[base] != NULL);
605 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
606 <= (unsigned) classvalues.super_diffval;
611 /* {a has dimension > 1} */
612 /* {componentvftbl->arraydesc != NULL} */
614 /* check if o is an array */
615 if ((valuedesc = valuevftbl->arraydesc) == NULL)
617 /* {o is an array} */
619 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
623 /* This is an optimized version where a is guaranteed to be one-dimensional */
624 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
626 arraydescriptor *desc;
627 vftbl_t *elementvftbl;
631 castinfo classvalues;
635 /* The following is guaranteed (by verifier checks):
637 * *) a->...vftbl->arraydesc != NULL
638 * *) a->...vftbl->arraydesc->elementvftbl != NULL
639 * *) a->...vftbl->arraydesc->dimension == 1
640 * *) o->vftbl is not an interface vftbl
643 desc = a->header.objheader.vftbl->arraydesc;
644 elementvftbl = desc->elementvftbl;
645 valuevftbl = o->vftbl;
647 /* {a is a one-dimensional array} */
649 if (valuevftbl == elementvftbl)
652 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
654 if ((base = classvalues.super_baseval) <= 0)
655 /* an array of interface references */
656 return (valuevftbl->interfacetablelength > -base &&
657 valuevftbl->interfacetable[base] != NULL);
659 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
660 <= (unsigned) classvalues.super_diffval;
666 /* This is an optimized version where a is guaranteed to be a
667 * one-dimensional array of a class type */
668 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
670 vftbl_t *elementvftbl;
673 castinfo classvalues;
677 /* The following is guaranteed (by verifier checks):
679 * *) a->...vftbl->arraydesc != NULL
680 * *) a->...vftbl->arraydesc->elementvftbl != NULL
681 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
682 * *) a->...vftbl->arraydesc->dimension == 1
683 * *) o->vftbl is not an interface vftbl
686 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
687 valuevftbl = o->vftbl;
689 /* {a is a one-dimensional array} */
691 if (valuevftbl == elementvftbl)
694 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
696 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
697 <= (unsigned) classvalues.super_diffval;
703 /* builtin_new *****************************************************************
705 Creates a new instance of class c on the heap.
707 Return value: pointer to the object or NULL if no memory is
710 *******************************************************************************/
712 java_objectheader *builtin_new(classinfo *c)
714 java_objectheader *o;
716 /* is the class loaded */
720 /* is the class linked */
725 if (!c->initialized) {
727 log_message_class("Initialize class (from builtin_new): ", c);
729 if (!initialize_class(c))
733 o = heap_allocate(c->instancesize, true, c->finalizer);
738 MSET(o, 0, u1, c->instancesize);
742 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
750 /* builtin_newarray ************************************************************
752 Creates an array with the given vftbl on the heap.
754 Return value: pointer to the array or NULL if no memory is available
756 CAUTION: The given vftbl must be the vftbl of the *array* class,
757 not of the element class.
759 *******************************************************************************/
761 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
764 arraydescriptor *desc;
769 desc = arrayvftbl->arraydesc;
770 dataoffset = desc->dataoffset;
771 componentsize = desc->componentsize;
774 *exceptionptr = new_negativearraysizeexception();
778 actualsize = dataoffset + size * componentsize;
780 if (((u4) actualsize) < ((u4) size)) { /* overflow */
781 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
785 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
790 MSET(a, 0, u1, actualsize);
792 a->objheader.vftbl = arrayvftbl;
794 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
795 initObjectLock(&a->objheader);
804 /* builtin_anewarray ***********************************************************
806 Creates an array of references to the given class type on the heap.
808 Return value: pointer to the array or NULL if no memory is
811 *******************************************************************************/
813 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
817 /* is class loaded */
818 assert(component->loaded);
820 /* is class linked */
821 if (!component->linked)
822 if (!link_class(component))
825 c = class_array_of(component, true);
830 return (java_objectarray *) builtin_newarray(size, c->vftbl);
834 /* builtin_newarray_int ********************************************************
836 Creates an array of 32 bit Integers on the heap.
838 Return value: pointer to the array or NULL if no memory is
841 *******************************************************************************/
843 java_intarray *builtin_newarray_int(s4 size)
845 return (java_intarray *)
846 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
850 /* builtin_newarray_long *******************************************************
852 Creates an array of 64 bit Integers on the heap.
854 Return value: pointer to the array or NULL if no memory is
857 *******************************************************************************/
859 java_longarray *builtin_newarray_long(s4 size)
861 return (java_longarray *)
862 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
866 /* builtin_newarray_float ******************************************************
868 Creates an array of 32 bit IEEE floats on the heap.
870 Return value: pointer to the array or NULL if no memory is
873 *******************************************************************************/
875 java_floatarray *builtin_newarray_float(s4 size)
877 return (java_floatarray *)
878 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
882 /* builtin_newarray_double *****************************************************
884 Creates an array of 64 bit IEEE floats on the heap.
886 Return value: pointer to the array or NULL if no memory is
889 *******************************************************************************/
891 java_doublearray *builtin_newarray_double(s4 size)
893 return (java_doublearray *)
894 builtin_newarray(size,
895 primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
899 /* builtin_newarray_byte *******************************************************
901 Creates an array of 8 bit Integers on the heap.
903 Return value: pointer to the array or NULL if no memory is
906 *******************************************************************************/
908 java_bytearray *builtin_newarray_byte(s4 size)
910 return (java_bytearray *)
911 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
915 /* builtin_newarray_char *******************************************************
917 Creates an array of characters on the heap.
919 Return value: pointer to the array or NULL if no memory is
922 *******************************************************************************/
924 java_chararray *builtin_newarray_char(s4 size)
926 return (java_chararray *)
927 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
931 /* builtin_newarray_short ******************************************************
933 Creates an array of 16 bit Integers on the heap.
935 Return value: pointer to the array or NULL if no memory is
938 *******************************************************************************/
940 java_shortarray *builtin_newarray_short(s4 size)
942 return (java_shortarray *)
943 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
947 /* builtin_newarray_boolean ****************************************************
949 Creates an array of bytes on the heap. The array is designated as
950 an array of booleans (important for casts)
952 Return value: pointer to the array or NULL if no memory is
955 *******************************************************************************/
957 java_booleanarray *builtin_newarray_boolean(s4 size)
959 return (java_booleanarray *)
960 builtin_newarray(size,
961 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
965 /* builtin_multianewarray ******************************************************
967 Creates a multi-dimensional array on the heap. The dimensions are
968 passed in an array of longs.
971 n............number of dimensions to create
972 arrayvftbl...vftbl of the array class
973 dims.........array containing the size of each dimension to create
975 Return value: pointer to the array or NULL if no memory is
978 ******************************************************************************/
980 java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims)
984 vftbl_t *componentvftbl;
986 /* create this dimension */
989 a = builtin_newarray(size, arrayvftbl);
994 /* if this is the last dimension return */
999 /* get the vftbl of the components to create */
1001 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
1003 /* The verifier guarantees that the dimension count is in the range. */
1005 /* create the component arrays */
1007 for (i = 0; i < size; i++) {
1008 java_arrayheader *ea =
1009 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1010 /* we save an s4 to a s8 slot, 8-byte aligned */
1012 builtin_multianewarray(n, componentvftbl, dims + 2);
1014 builtin_multianewarray(n, componentvftbl, dims + 1);
1020 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1027 /*****************************************************************************
1030 Various functions for printing a message at method entry or exit (for
1033 *****************************************************************************/
1035 u4 methodindent = 0;
1037 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1047 if (opt_verbose || runverbose || verboseexception) {
1048 /* calculate message length */
1052 strlen("Exception ") +
1053 utf_strlen(xptr->vftbl->class->name);
1056 logtextlen = strlen("Some Throwable");
1058 logtextlen += strlen(" thrown in ");
1062 utf_strlen(m->class->name) +
1064 utf_strlen(m->name) +
1065 utf_strlen(m->descriptor) +
1066 strlen("(NOSYNC,NATIVE");
1068 #if SIZEOF_VOID_P == 8
1070 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1072 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1075 if (m->class->sourcefile == NULL)
1076 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1078 logtextlen += utf_strlen(m->class->sourcefile);
1080 logtextlen += strlen(":65536)");
1083 logtextlen += strlen("call_java_method");
1085 logtextlen += strlen("0");
1087 /* allocate memory */
1089 dumpsize = dump_size();
1091 logtext = DMNEW(char, logtextlen);
1094 strcpy(logtext, "Exception ");
1095 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1098 strcpy(logtext, "Some Throwable");
1101 strcat(logtext, " thrown in ");
1104 utf_strcat_classname(logtext, m->class->name);
1105 strcat(logtext, ".");
1106 utf_strcat(logtext, m->name);
1107 utf_strcat(logtext, m->descriptor);
1109 if (m->flags & ACC_SYNCHRONIZED)
1110 strcat(logtext, "(SYNC");
1112 strcat(logtext, "(NOSYNC");
1114 if (m->flags & ACC_NATIVE) {
1115 strcat(logtext, ",NATIVE");
1117 #if SIZEOF_VOID_P == 8
1118 sprintf(logtext + strlen(logtext),
1119 ")(0x%016lx) at position 0x%016lx",
1120 (ptrint) m->entrypoint, (ptrint) pos);
1122 sprintf(logtext + strlen(logtext),
1123 ")(0x%08x) at position 0x%08x",
1124 (ptrint) m->entrypoint, (ptrint) pos);
1128 #if SIZEOF_VOID_P == 8
1129 sprintf(logtext + strlen(logtext),
1130 ")(0x%016lx) at position 0x%016lx (",
1131 (ptrint) m->entrypoint, (ptrint) pos);
1133 sprintf(logtext + strlen(logtext),
1134 ")(0x%08x) at position 0x%08x (",
1135 (ptrint) m->entrypoint, (ptrint) pos);
1138 if (m->class->sourcefile == NULL)
1139 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1141 utf_strcat(logtext, m->class->sourcefile);
1143 sprintf(logtext + strlen(logtext), ":%d)", line);
1147 strcat(logtext, "call_java_method");
1151 /* release memory */
1153 dump_release(dumpsize);
1160 /* builtin_trace_args **********************************************************
1164 *******************************************************************************/
1166 #ifdef TRACE_ARGS_NUM
1167 void builtin_trace_args(s8 a0, s8 a1,
1168 #if TRACE_ARGS_NUM >= 4
1170 #endif /* TRACE_ARGS_NUM >= 4 */
1171 #if TRACE_ARGS_NUM >= 6
1173 #endif /* TRACE_ARGS_NUM >= 6 */
1174 #if TRACE_ARGS_NUM == 8
1176 #endif /* TRACE_ARGS_NUM == 8 */
1187 /* calculate message length */
1190 methodindent + strlen("called: ") +
1191 utf_strlen(m->class->name) +
1193 utf_strlen(m->name) +
1194 utf_strlen(m->descriptor) +
1195 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1197 /* add maximal argument length */
1199 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1201 /* allocate memory */
1203 dumpsize = dump_size();
1205 logtext = DMNEW(char, logtextlen);
1207 for (i = 0; i < methodindent; i++)
1210 strcpy(logtext + methodindent, "called: ");
1212 utf_strcat_classname(logtext, m->class->name);
1213 strcat(logtext, ".");
1214 utf_strcat(logtext, m->name);
1215 utf_strcat(logtext, m->descriptor);
1217 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1218 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1219 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1220 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1221 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1222 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1223 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1224 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1225 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1226 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1227 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1229 strcat(logtext, "(");
1231 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1232 /* Only Arguments in integer Registers are passed correctly here */
1233 /* long longs spilled on Stack have an wrong offset of +4 */
1234 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1235 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1236 switch (md->paramcount) {
1240 #if SIZEOF_VOID_P == 4
1242 sprintf(logtext + strlen(logtext),
1248 sprintf(logtext + strlen(logtext),
1253 #if TRACE_ARGS_NUM >= 4
1255 sprintf(logtext + strlen(logtext),
1256 "0x%llx, 0x%llx, 0x%llx",
1261 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1263 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1266 #endif /* TRACE_ARGS_NUM >= 4 */
1268 #if TRACE_ARGS_NUM >= 6
1270 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1272 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1277 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1279 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1282 #endif /* TRACE_ARGS_NUM >= 6 */
1284 #if TRACE_ARGS_NUM == 8
1286 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1288 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1290 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1294 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1296 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1298 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1300 #endif /* TRACE_ARGS_NUM == 8 */
1303 #if TRACE_ARGS_NUM == 2
1304 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1306 #elif TRACE_ARGS_NUM == 4
1307 sprintf(logtext + strlen(logtext),
1308 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1309 a0, a1, a2, a3, md->paramcount - 4);
1311 #elif TRACE_ARGS_NUM == 6
1312 sprintf(logtext + strlen(logtext),
1313 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1314 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1316 #elif TRACE_ARGS_NUM == 8
1317 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1319 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1321 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1322 , a6, a7, md->paramcount - 8);
1326 #else /* SIZEOF_VOID_P == 4 */
1329 sprintf(logtext + strlen(logtext),
1335 sprintf(logtext + strlen(logtext),
1341 sprintf(logtext + strlen(logtext),
1342 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1346 sprintf(logtext + strlen(logtext),
1347 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1351 #if TRACE_ARGS_NUM >= 6
1353 sprintf(logtext + strlen(logtext),
1354 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1355 a0, a1, a2, a3, a4);
1359 sprintf(logtext + strlen(logtext),
1360 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1361 a0, a1, a2, a3, a4, a5);
1363 #endif /* TRACE_ARGS_NUM >= 6 */
1365 #if TRACE_ARGS_NUM == 8
1367 sprintf(logtext + strlen(logtext),
1368 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1369 a0, a1, a2, a3, a4, a5, a6);
1373 sprintf(logtext + strlen(logtext),
1374 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1375 a0, a1, a2, a3, a4, a5, a6, a7);
1377 #endif /* TRACE_ARGS_NUM == 8 */
1380 #if TRACE_ARGS_NUM == 4
1381 sprintf(logtext + strlen(logtext),
1382 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1383 a0, a1, a2, a3, md->paramcount - 4);
1385 #elif TRACE_ARGS_NUM == 6
1386 sprintf(logtext + strlen(logtext),
1387 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1388 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1390 #elif TRACE_ARGS_NUM == 8
1391 sprintf(logtext + strlen(logtext),
1392 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1393 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1396 #endif /* SIZEOF_VOID_P == 4 */
1399 strcat(logtext, ")");
1403 /* release memory */
1405 dump_release(dumpsize);
1412 /* builtin_displaymethodstop ***************************************************
1416 *******************************************************************************/
1418 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1429 /* calculate message length */
1432 methodindent + strlen("finished: ") +
1433 utf_strlen(m->class->name) +
1435 utf_strlen(m->name) +
1436 utf_strlen(m->descriptor) +
1437 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1439 /* add maximal argument length */
1441 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1443 /* allocate memory */
1445 dumpsize = dump_size();
1447 logtext = DMNEW(char, logtextlen);
1449 /* generate the message */
1451 for (i = 0; i < methodindent; i++)
1457 log_text("WARNING: unmatched methodindent--");
1459 strcpy(logtext + methodindent, "finished: ");
1460 utf_strcat_classname(logtext, m->class->name);
1461 strcat(logtext, ".");
1462 utf_strcat(logtext, m->name);
1463 utf_strcat(logtext, m->descriptor);
1465 switch (md->returntype.type) {
1467 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1471 #if SIZEOF_VOID_P == 4
1472 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1474 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1479 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1484 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1489 #if SIZEOF_VOID_P == 4
1490 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1492 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1499 /* release memory */
1501 dump_release(dumpsize);
1505 /****************************************************************************
1506 SYNCHRONIZATION FUNCTIONS
1507 *****************************************************************************/
1509 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1511 * Lock the mutex of an object.
1513 void internal_lock_mutex_for_object(java_objectheader *object)
1515 mutexHashEntry *entry;
1518 assert(object != 0);
1520 hashValue = MUTEX_HASH_VALUE(object);
1521 entry = &mutexHashTable[hashValue];
1523 if (entry->object != 0) {
1524 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1526 entry->mutex.holder = 0;
1527 entry->mutex.count = 0;
1528 entry->mutex.muxWaiters = 0;
1531 while (entry->next != 0 && entry->object != object)
1532 entry = entry->next;
1534 if (entry->object != object) {
1535 entry->next = firstFreeOverflowEntry;
1536 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1538 entry = entry->next;
1541 assert(entry->conditionCount == 0);
1546 entry->mutex.holder = 0;
1547 entry->mutex.count = 0;
1548 entry->mutex.muxWaiters = 0;
1551 if (entry->object == 0)
1552 entry->object = object;
1554 internal_lock_mutex(&entry->mutex);
1559 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1561 * Unlocks the mutex of an object.
1563 void internal_unlock_mutex_for_object (java_objectheader *object)
1566 mutexHashEntry *entry;
1568 hashValue = MUTEX_HASH_VALUE(object);
1569 entry = &mutexHashTable[hashValue];
1571 if (entry->object == object) {
1572 internal_unlock_mutex(&entry->mutex);
1575 while (entry->next != 0 && entry->next->object != object)
1576 entry = entry->next;
1578 assert(entry->next != 0);
1580 internal_unlock_mutex(&entry->next->mutex);
1582 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1583 mutexHashEntry *unlinked = entry->next;
1585 entry->next = unlinked->next;
1586 unlinked->next = firstFreeOverflowEntry;
1587 firstFreeOverflowEntry = unlinked;
1594 #if defined(USE_THREADS)
1595 void builtin_monitorenter(java_objectheader *o)
1597 #if !defined(NATIVE_THREADS)
1602 hashValue = MUTEX_HASH_VALUE(o);
1603 if (mutexHashTable[hashValue].object == o
1604 && mutexHashTable[hashValue].mutex.holder == currentThread)
1605 ++mutexHashTable[hashValue].mutex.count;
1607 internal_lock_mutex_for_object(o);
1611 monitorEnter((threadobject *) THREADOBJECT, o);
1617 #if defined(USE_THREADS)
1619 * Locks the class object - needed for static synchronized methods.
1620 * The use_class_as_object call is needed in order to circumvent a
1621 * possible deadlock with builtin_monitorenter called by another
1622 * thread calling use_class_as_object.
1624 void builtin_staticmonitorenter(classinfo *c)
1626 use_class_as_object(c);
1627 builtin_monitorenter(&c->header);
1632 #if defined(USE_THREADS)
1633 void builtin_monitorexit(java_objectheader *o)
1635 #if !defined(NATIVE_THREADS)
1640 hashValue = MUTEX_HASH_VALUE(o);
1641 if (mutexHashTable[hashValue].object == o) {
1642 if (mutexHashTable[hashValue].mutex.count == 1
1643 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1644 internal_unlock_mutex_for_object(o);
1646 --mutexHashTable[hashValue].mutex.count;
1649 internal_unlock_mutex_for_object(o);
1653 monitorExit((threadobject *) THREADOBJECT, o);
1659 /*****************************************************************************
1660 MISCELLANEOUS HELPER FUNCTIONS
1661 *****************************************************************************/
1665 /*********** Functions for integer divisions *****************************
1667 On some systems (eg. DEC ALPHA), integer division is not supported by the
1668 CPU. These helper functions implement the missing functionality.
1670 ******************************************************************************/
1672 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1673 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1676 /************** Functions for long arithmetics *******************************
1678 On systems where 64 bit Integers are not supported by the CPU, these
1679 functions are needed.
1681 ******************************************************************************/
1683 s8 builtin_ladd(s8 a, s8 b)
1696 s8 builtin_lsub(s8 a, s8 b)
1709 s8 builtin_lmul(s8 a, s8 b)
1722 s8 builtin_ldiv(s8 a, s8 b)
1735 s8 builtin_lrem(s8 a, s8 b)
1748 s8 builtin_lshl(s8 a, s4 b)
1761 s8 builtin_lshr(s8 a, s4 b)
1774 s8 builtin_lushr(s8 a, s4 b)
1779 c = ((u8) a) >> (b & 63);
1787 s8 builtin_land(s8 a, s8 b)
1800 s8 builtin_lor(s8 a, s8 b)
1813 s8 builtin_lxor(s8 a, s8 b)
1826 s8 builtin_lneg(s8 a)
1839 s4 builtin_lcmp(s8 a, s8 b)
1842 if (a < b) return -1;
1843 if (a > b) return 1;
1854 /*********** Functions for floating point operations *************************/
1856 /* used to convert FLT_xxx defines into float values */
1858 static inline float intBitsToFloat(s4 i)
1867 /* used to convert DBL_xxx defines into double values */
1869 static inline float longBitsToDouble(s8 l)
1878 float builtin_fadd(float a, float b)
1880 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1881 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1892 if (copysignf(1.0, a) == copysignf(1.0, b))
1895 return intBitsToFloat(FLT_NAN);
1901 float builtin_fsub(float a, float b)
1903 return builtin_fadd(a, builtin_fneg(b));
1907 float builtin_fmul(float a, float b)
1909 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1910 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1912 if (finitef(b)) return a * b;
1914 if (a == 0) return intBitsToFloat(FLT_NAN);
1915 else return copysignf(b, copysignf(1.0, b)*a);
1920 if (b == 0) return intBitsToFloat(FLT_NAN);
1921 else return copysignf(a, copysignf(1.0, a)*b);
1924 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1930 /* builtin_ddiv ****************************************************************
1932 Implementation as described in VM Spec.
1934 *******************************************************************************/
1936 float builtin_fdiv(float a, float b)
1940 /* If neither value1' nor value2' is NaN, the sign of the result */
1941 /* is positive if both values have the same sign, negative if the */
1942 /* values have different signs. */
1948 /* If either value1' or value2' is NaN, the result is NaN. */
1950 return intBitsToFloat(FLT_NAN);
1953 /* Division of a finite value by an infinity results in a */
1954 /* signed zero, with the sign-producing rule just given. */
1956 /* is sign equal? */
1958 if (copysignf(1.0, a) == copysignf(1.0, b))
1967 /* If either value1' or value2' is NaN, the result is NaN. */
1969 return intBitsToFloat(FLT_NAN);
1971 } else if (finitef(b)) {
1972 /* Division of an infinity by a finite value results in a signed */
1973 /* infinity, with the sign-producing rule just given. */
1975 /* is sign equal? */
1977 if (copysignf(1.0, a) == copysignf(1.0, b))
1978 return intBitsToFloat(FLT_POSINF);
1980 return intBitsToFloat(FLT_NEGINF);
1983 /* Division of an infinity by an infinity results in NaN. */
1985 return intBitsToFloat(FLT_NAN);
1991 float builtin_frem(float a, float b)
1997 float builtin_fneg(float a)
1999 if (isnanf(a)) return a;
2001 if (finitef(a)) return -a;
2002 else return copysignf(a, -copysignf(1.0, a));
2007 s4 builtin_fcmpl(float a, float b)
2009 if (isnanf(a)) return -1;
2010 if (isnanf(b)) return -1;
2011 if (!finitef(a) || !finitef(b)) {
2012 a = finitef(a) ? 0 : copysignf(1.0, a);
2013 b = finitef(b) ? 0 : copysignf(1.0, b);
2015 if (a > b) return 1;
2016 if (a == b) return 0;
2021 s4 builtin_fcmpg(float a, float b)
2023 if (isnanf(a)) return 1;
2024 if (isnanf(b)) return 1;
2025 if (!finitef(a) || !finitef(b)) {
2026 a = finitef(a) ? 0 : copysignf(1.0, a);
2027 b = finitef(b) ? 0 : copysignf(1.0, b);
2029 if (a > b) return 1;
2030 if (a == b) return 0;
2036 /************************* Functions for doubles ****************************/
2038 double builtin_dadd(double a, double b)
2040 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2041 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2043 if (finite(b)) return a + b;
2047 if (finite(b)) return a;
2049 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2050 else return longBitsToDouble(DBL_NAN);
2056 double builtin_dsub(double a, double b)
2058 return builtin_dadd(a, builtin_dneg(b));
2062 double builtin_dmul(double a, double b)
2064 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2065 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2067 if (finite(b)) return a * b;
2069 if (a == 0) return longBitsToDouble(DBL_NAN);
2070 else return copysign(b, copysign(1.0, b) * a);
2075 if (b == 0) return longBitsToDouble(DBL_NAN);
2076 else return copysign(a, copysign(1.0, a) * b);
2079 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2085 /* builtin_ddiv ****************************************************************
2087 Implementation as described in VM Spec.
2089 *******************************************************************************/
2091 double builtin_ddiv(double a, double b)
2095 /* If neither value1' nor value2' is NaN, the sign of the result */
2096 /* is positive if both values have the same sign, negative if the */
2097 /* values have different signs. */
2103 /* If either value1' or value2' is NaN, the result is NaN. */
2105 return longBitsToDouble(DBL_NAN);
2108 /* Division of a finite value by an infinity results in a */
2109 /* signed zero, with the sign-producing rule just given. */
2111 /* is sign equal? */
2113 if (copysign(1.0, a) == copysign(1.0, b))
2122 /* If either value1' or value2' is NaN, the result is NaN. */
2124 return longBitsToDouble(DBL_NAN);
2126 } else if (finite(b)) {
2127 /* Division of an infinity by a finite value results in a signed */
2128 /* infinity, with the sign-producing rule just given. */
2130 /* is sign equal? */
2132 if (copysign(1.0, a) == copysign(1.0, b))
2133 return longBitsToDouble(DBL_POSINF);
2135 return longBitsToDouble(DBL_NEGINF);
2138 /* Division of an infinity by an infinity results in NaN. */
2140 return longBitsToDouble(DBL_NAN);
2146 double builtin_drem(double a, double b)
2151 /* builtin_dneg ****************************************************************
2153 Implemented as described in VM Spec.
2155 *******************************************************************************/
2157 double builtin_dneg(double a)
2160 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2167 /* If the operand is a zero, the result is the zero of opposite */
2173 /* If the operand is an infinity, the result is the infinity of */
2174 /* opposite sign. */
2176 return copysign(a, -copysign(1.0, a));
2182 s4 builtin_dcmpl(double a, double b)
2184 if (isnan(a)) return -1;
2185 if (isnan(b)) return -1;
2186 if (!finite(a) || !finite(b)) {
2187 a = finite(a) ? 0 : copysign(1.0, a);
2188 b = finite(b) ? 0 : copysign(1.0, b);
2190 if (a > b) return 1;
2191 if (a == b) return 0;
2196 s4 builtin_dcmpg(double a, double b)
2198 if (isnan(a)) return 1;
2199 if (isnan(b)) return 1;
2200 if (!finite(a) || !finite(b)) {
2201 a = finite(a) ? 0 : copysign(1.0, a);
2202 b = finite(b) ? 0 : copysign(1.0, b);
2204 if (a > b) return 1;
2205 if (a == b) return 0;
2210 /*********************** Conversion operations ****************************/
2212 s8 builtin_i2l(s4 i)
2225 float builtin_i2f(s4 a)
2227 float f = (float) a;
2232 double builtin_i2d(s4 a)
2234 double d = (double) a;
2239 s4 builtin_l2i(s8 l)
2249 float builtin_l2f(s8 a)
2252 float f = (float) a;
2260 double builtin_l2d(s8 a)
2263 double d = (double) a;
2271 s4 builtin_f2i(float a)
2275 i = builtin_d2i((double) a);
2286 if (a < (-2147483648))
2287 return (-2147483648);
2290 f = copysignf((float) 1.0, a);
2293 return (-2147483648); */
2297 s8 builtin_f2l(float a)
2301 l = builtin_d2l((double) a);
2308 if (a > 9223372036854775807L)
2309 return 9223372036854775807L;
2310 if (a < (-9223372036854775808L))
2311 return (-9223372036854775808L);
2316 f = copysignf((float) 1.0, a);
2318 return 9223372036854775807L;
2319 return (-9223372036854775808L); */
2323 double builtin_f2d(float a)
2325 if (finitef(a)) return (double) a;
2328 return longBitsToDouble(DBL_NAN);
2330 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2335 s4 builtin_d2i(double a)
2340 if (a >= 2147483647)
2342 if (a <= (-2147483647-1))
2343 return (-2147483647-1);
2348 d = copysign(1.0, a);
2351 return (-2147483647-1);
2355 s8 builtin_d2l(double a)
2360 if (a >= 9223372036854775807LL)
2361 return 9223372036854775807LL;
2362 if (a <= (-9223372036854775807LL-1))
2363 return (-9223372036854775807LL-1);
2368 d = copysign(1.0, a);
2370 return 9223372036854775807LL;
2371 return (-9223372036854775807LL-1);
2375 float builtin_d2f(double a)
2381 return intBitsToFloat(FLT_NAN);
2383 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2388 /* builtin_clone_array *********************************************************
2390 Wrapper function for cloning arrays.
2392 *******************************************************************************/
2394 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2396 java_arrayheader *ah;
2397 java_lang_Cloneable *c;
2399 c = (java_lang_Cloneable *) o;
2401 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2407 /* builtin_asm_get_exceptionptrptr *********************************************
2409 this is a wrapper for calls from asmpart
2411 *******************************************************************************/
2413 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2414 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2416 return builtin_get_exceptionptrptr();
2422 * These are local overrides for various environment variables in Emacs.
2423 * Please do not remove this and leave it at the end of the file, where
2424 * Emacs will automagically detect them.
2425 * ---------------------------------------------------------------------
2428 * indent-tabs-mode: t