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 3134 2005-08-23 14:45:29Z cacao $
53 #include "classpath/native/fdlibm/fdlibm.h"
56 #include "mm/memory.h"
57 #include "native/native.h"
58 #include "native/include/java_lang_Cloneable.h"
59 #include "native/include/java_lang_Object.h" /* required by VMObject */
60 #include "native/include/java_lang_VMObject.h"
62 #if defined(USE_THREADS)
63 # if defined(NATIVE_THREADS)
64 # include "threads/native/threads.h"
66 # include "threads/green/threads.h"
67 # include "threads/green/locks.h"
71 #include "toolbox/logging.h"
72 #include "toolbox/util.h"
73 #include "vm/builtin.h"
74 #include "vm/exceptions.h"
75 #include "vm/global.h"
76 #include "vm/initialize.h"
77 #include "vm/loader.h"
78 #include "vm/options.h"
79 #include "vm/stringlocal.h"
80 #include "vm/tables.h"
81 #include "vm/jit/asmpart.h"
82 #include "vm/jit/patcher.h"
85 #undef DEBUG /*define DEBUG 1*/
87 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
88 THREADSPECIFIC void *_thread_nativestackframeinfo = NULL;
91 /* include builtin tables *****************************************************/
93 #include "vm/builtintable.inc"
96 /* builtintable_init ***********************************************************
98 Parse the descriptors of builtin functions and create the parsed
101 *******************************************************************************/
103 static bool builtintable_init(void)
105 descriptor_pool *descpool;
109 s4 entries_automatic;
112 /* mark start of dump memory area */
114 dumpsize = dump_size();
116 /* create a new descriptor pool */
118 descpool = descriptor_pool_new(class_java_lang_Object);
120 /* add some entries we need */
122 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
125 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
128 /* calculate table entries statically */
131 sizeof(builtintable_internal) / sizeof(builtintable_entry);
134 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
135 - 1; /* last filler entry (comment see builtintable.inc) */
137 /* first add all descriptors to the pool */
139 for (i = 0; i < entries_internal; i++) {
140 /* create a utf8 string from descriptor */
142 descriptor = utf_new_char(builtintable_internal[i].descriptor);
144 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
145 /* release dump area */
147 dump_release(dumpsize);
153 for (i = 0; i < entries_automatic; i++) {
154 /* create a utf8 string from descriptor */
156 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
158 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
159 /* release dump area */
161 dump_release(dumpsize);
167 /* create the class reference table */
169 (void) descriptor_pool_create_classrefs(descpool, NULL);
171 /* allocate space for the parsed descriptors */
173 descriptor_pool_alloc_parsed_descriptors(descpool);
175 /* now parse all descriptors */
177 for (i = 0; i < entries_internal; i++) {
178 /* create a utf8 string from descriptor */
180 descriptor = utf_new_char(builtintable_internal[i].descriptor);
182 /* parse the descriptor, builtin is always static (no `this' pointer) */
184 builtintable_internal[i].md =
185 descriptor_pool_parse_method_descriptor(descpool, descriptor,
189 for (i = 0; i < entries_automatic; i++) {
190 /* create a utf8 string from descriptor */
192 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
194 /* parse the descriptor, builtin is always static (no `this' pointer) */
196 builtintable_automatic[i].md =
197 descriptor_pool_parse_method_descriptor(descpool, descriptor,
201 /* release dump area */
203 dump_release(dumpsize);
209 /* builtintable_comparator *****************************************************
211 qsort comparator for the automatic builtin table.
213 *******************************************************************************/
215 static int builtintable_comparator(const void *a, const void *b)
217 builtintable_entry *bte1;
218 builtintable_entry *bte2;
220 bte1 = (builtintable_entry *) a;
221 bte2 = (builtintable_entry *) b;
223 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
227 /* builtintable_sort_automatic *************************************************
229 Sorts the automatic builtin table.
231 *******************************************************************************/
233 static void builtintable_sort_automatic(void)
237 /* calculate table size statically (`- 1' comment see builtintable.inc) */
239 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
241 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
242 builtintable_comparator);
246 /* builtin_init ****************************************************************
250 *******************************************************************************/
252 bool builtin_init(void)
254 /* initialize the builtin tables */
256 if (!builtintable_init())
259 /* sort builtin tables */
261 builtintable_sort_automatic();
267 /* builtintable_get_internal ***************************************************
269 Finds an entry in the builtintable for internal functions and
270 returns the a pointer to the structure.
272 *******************************************************************************/
274 builtintable_entry *builtintable_get_internal(functionptr fp)
278 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
279 if (builtintable_internal[i].fp == fp)
280 return &builtintable_internal[i];
287 /* builtintable_get_automatic **************************************************
289 Finds an entry in the builtintable for functions which are replaced
290 automatically and returns the a pointer to the structure.
292 *******************************************************************************/
294 builtintable_entry *builtintable_get_automatic(s4 opcode)
296 builtintable_entry *first;
297 builtintable_entry *last;
298 builtintable_entry *middle;
302 /* calculate table size statically (`- 1' comment see builtintable.inc) */
304 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
306 first = builtintable_automatic;
307 last = builtintable_automatic + entries;
309 while (entries > 0) {
311 middle = first + half;
313 if (middle->opcode < opcode) {
320 return (first != last ? first : NULL);
324 /*****************************************************************************
326 *****************************************************************************/
330 /*************** internal function: builtin_isanysubclass *********************
332 Checks a subclass relation between two classes. Implemented interfaces
333 are interpreted as super classes.
334 Return value: 1 ... sub is subclass of super
337 *****************************************************************************/
338 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
341 castinfo classvalues;
346 if (super->flags & ACC_INTERFACE)
347 return (sub->vftbl->interfacetablelength > super->index) &&
348 (sub->vftbl->interfacetable[-super->index] != NULL);
350 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
352 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
353 (u4) classvalues.super_diffval;
359 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
363 castinfo classvalues;
368 asm_getclassvalues_atomic(super, sub, &classvalues);
370 if ((base = classvalues.super_baseval) <= 0)
371 /* super is an interface */
372 res = (sub->interfacetablelength > -base) &&
373 (sub->interfacetable[base] != NULL);
375 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
376 <= (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 /* XXX should use vftbl */
393 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
396 log_text ("builtin_instanceof called");
401 return builtin_isanysubclass(obj->vftbl->class, class);
406 /**************** function: builtin_checkcast *******************************
408 The same as builtin_instanceof except that 1 is returned when
411 ****************************************************************************/
413 /* XXX should use vftbl */
414 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
417 log_text("builtin_checkcast called");
422 if (builtin_isanysubclass(obj->vftbl->class, class))
426 printf("#### checkcast failed ");
427 utf_display(obj->vftbl->class->name);
429 utf_display(class->name);
437 /* builtin_descriptorscompatible ***********************************************
439 Checks if two array type descriptors are assignment compatible
441 Return value: 1 ... target = desc is possible
444 *******************************************************************************/
446 static s4 builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
451 if (desc->arraytype != target->arraytype)
454 if (desc->arraytype != ARRAYTYPE_OBJECT)
457 /* {both arrays are arrays of references} */
459 if (desc->dimension == target->dimension) {
460 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
461 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
462 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
464 if (desc->dimension < target->dimension) return 0;
466 /* {desc has higher dimension than target} */
467 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
471 /* builtin_arraycheckcast ******************************************************
473 Checks if an object is really a subtype of the requested array
474 type. The object has to be an array to begin with. For simple
475 arrays (int, short, double, etc.) the types have to match exactly.
476 For arrays of objects, the type of elements in the array has to be
477 a subtype (or the same type) of the requested element type. For
478 arrays of arrays (which in turn can again be arrays of arrays), the
479 types at the lowest level have to satisfy the corresponding sub
482 *******************************************************************************/
484 s4 builtin_arraycheckcast(java_objectheader *o, vftbl_t *target)
486 arraydescriptor *desc;
491 if ((desc = o->vftbl->arraydesc) == NULL)
494 return builtin_descriptorscompatible(desc, target->arraydesc);
498 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
503 return builtin_arraycheckcast(obj, target);
507 /************************** exception functions *******************************
509 ******************************************************************************/
511 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
513 java_lang_Throwable *t;
519 t = (java_lang_Throwable *) xptr;
521 /* calculate message length */
523 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
527 utf_strlen(xptr->vftbl->class->name) +
529 javastring_strlen((java_objectheader *) t->detailMessage);
532 logtextlen += strlen("(nil)");
534 /* allocate memory */
536 dumpsize = dump_size();
538 logtext = DMNEW(char, logtextlen);
540 strcpy(logtext, "Builtin exception thrown: ");
543 utf_sprint_classname(logtext + strlen(logtext),
544 xptr->vftbl->class->name);
546 if (t->detailMessage) {
549 buf = javastring_tochar((java_objectheader *) t->detailMessage);
550 strcat(logtext, ": ");
551 strcat(logtext, buf);
552 MFREE(buf, char, strlen(buf));
556 strcat(logtext, "(nil)");
563 dump_release(dumpsize);
566 *exceptionptr = xptr;
573 /* builtin_canstore ************************************************************
575 Checks, if an object can be stored in an array.
577 Return value: 1 ... possible
580 *******************************************************************************/
582 s4 builtin_canstore(java_objectarray *a, java_objectheader *o)
584 arraydescriptor *desc;
585 arraydescriptor *valuedesc;
586 vftbl_t *componentvftbl;
589 castinfo classvalues;
594 /* The following is guaranteed (by verifier checks):
596 * *) a->...vftbl->arraydesc != NULL
597 * *) a->...vftbl->arraydesc->componentvftbl != NULL
598 * *) o->vftbl is not an interface vftbl
601 desc = a->header.objheader.vftbl->arraydesc;
602 componentvftbl = desc->componentvftbl;
603 valuevftbl = o->vftbl;
605 if ((desc->dimension - 1) == 0) {
608 /* {a is a one-dimensional array} */
609 /* {a is an array of references} */
611 if (valuevftbl == componentvftbl)
614 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
616 if ((base = classvalues.super_baseval) <= 0)
617 /* an array of interface references */
618 return (valuevftbl->interfacetablelength > -base &&
619 valuevftbl->interfacetable[base] != NULL);
621 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
622 <= (unsigned) classvalues.super_diffval;
627 /* {a has dimension > 1} */
628 /* {componentvftbl->arraydesc != NULL} */
630 /* check if o is an array */
631 if ((valuedesc = valuevftbl->arraydesc) == NULL)
633 /* {o is an array} */
635 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
639 /* This is an optimized version where a is guaranteed to be one-dimensional */
640 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
642 arraydescriptor *desc;
643 vftbl_t *elementvftbl;
647 castinfo classvalues;
651 /* The following is guaranteed (by verifier checks):
653 * *) a->...vftbl->arraydesc != NULL
654 * *) a->...vftbl->arraydesc->elementvftbl != NULL
655 * *) a->...vftbl->arraydesc->dimension == 1
656 * *) o->vftbl is not an interface vftbl
659 desc = a->header.objheader.vftbl->arraydesc;
660 elementvftbl = desc->elementvftbl;
661 valuevftbl = o->vftbl;
663 /* {a is a one-dimensional array} */
665 if (valuevftbl == elementvftbl)
668 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
670 if ((base = classvalues.super_baseval) <= 0)
671 /* an array of interface references */
672 return (valuevftbl->interfacetablelength > -base &&
673 valuevftbl->interfacetable[base] != NULL);
675 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
676 <= (unsigned) classvalues.super_diffval;
682 /* This is an optimized version where a is guaranteed to be a
683 * one-dimensional array of a class type */
684 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
686 vftbl_t *elementvftbl;
689 castinfo classvalues;
693 /* The following is guaranteed (by verifier checks):
695 * *) a->...vftbl->arraydesc != NULL
696 * *) a->...vftbl->arraydesc->elementvftbl != NULL
697 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
698 * *) a->...vftbl->arraydesc->dimension == 1
699 * *) o->vftbl is not an interface vftbl
702 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
703 valuevftbl = o->vftbl;
705 /* {a is a one-dimensional array} */
707 if (valuevftbl == elementvftbl)
710 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
712 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
713 <= (unsigned) classvalues.super_diffval;
719 /* builtin_new *****************************************************************
721 Creates a new instance of class c on the heap.
723 Return value: pointer to the object or NULL if no memory is
726 *******************************************************************************/
728 java_objectheader *builtin_new(classinfo *c)
730 java_objectheader *o;
732 /* is the class loaded */
736 /* is the class linked */
741 if (!c->initialized) {
743 log_message_class("Initialize class (from builtin_new): ", c);
745 if (!initialize_class(c))
749 o = heap_allocate(c->instancesize, true, c->finalizer);
754 MSET(o, 0, u1, c->instancesize);
758 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
766 /* builtin_newarray ************************************************************
768 Creates an array with the given vftbl on the heap.
770 Return value: pointer to the array or NULL if no memory is available
772 CAUTION: The given vftbl must be the vftbl of the *array* class,
773 not of the element class.
775 *******************************************************************************/
777 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
780 arraydescriptor *desc;
785 desc = arrayvftbl->arraydesc;
786 dataoffset = desc->dataoffset;
787 componentsize = desc->componentsize;
790 *exceptionptr = new_negativearraysizeexception();
794 actualsize = dataoffset + size * componentsize;
796 if (((u4) actualsize) < ((u4) size)) { /* overflow */
797 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
801 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
806 MSET(a, 0, u1, actualsize);
808 a->objheader.vftbl = arrayvftbl;
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 *component)
833 /* is class loaded */
834 assert(component->loaded);
836 /* is class linked */
837 if (!component->linked)
838 if (!link_class(component))
841 c = class_array_of(component, true);
846 return (java_objectarray *) builtin_newarray(size, c->vftbl);
850 /* builtin_newarray_int ********************************************************
852 Creates an array of 32 bit Integers on the heap.
854 Return value: pointer to the array or NULL if no memory is
857 *******************************************************************************/
859 java_intarray *builtin_newarray_int(s4 size)
861 return (java_intarray *)
862 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
866 /* builtin_newarray_long *******************************************************
868 Creates an array of 64 bit Integers on the heap.
870 Return value: pointer to the array or NULL if no memory is
873 *******************************************************************************/
875 java_longarray *builtin_newarray_long(s4 size)
877 return (java_longarray *)
878 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
882 /* builtin_newarray_float ******************************************************
884 Creates an array of 32 bit IEEE floats on the heap.
886 Return value: pointer to the array or NULL if no memory is
889 *******************************************************************************/
891 java_floatarray *builtin_newarray_float(s4 size)
893 return (java_floatarray *)
894 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
898 /* builtin_newarray_double *****************************************************
900 Creates an array of 64 bit IEEE floats on the heap.
902 Return value: pointer to the array or NULL if no memory is
905 *******************************************************************************/
907 java_doublearray *builtin_newarray_double(s4 size)
909 return (java_doublearray *)
910 builtin_newarray(size,
911 primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
915 /* builtin_newarray_byte *******************************************************
917 Creates an array of 8 bit Integers on the heap.
919 Return value: pointer to the array or NULL if no memory is
922 *******************************************************************************/
924 java_bytearray *builtin_newarray_byte(s4 size)
926 return (java_bytearray *)
927 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
931 /* builtin_newarray_char *******************************************************
933 Creates an array of characters on the heap.
935 Return value: pointer to the array or NULL if no memory is
938 *******************************************************************************/
940 java_chararray *builtin_newarray_char(s4 size)
942 return (java_chararray *)
943 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
947 /* builtin_newarray_short ******************************************************
949 Creates an array of 16 bit Integers on the heap.
951 Return value: pointer to the array or NULL if no memory is
954 *******************************************************************************/
956 java_shortarray *builtin_newarray_short(s4 size)
958 return (java_shortarray *)
959 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
963 /* builtin_newarray_boolean ****************************************************
965 Creates an array of bytes on the heap. The array is designated as
966 an array of booleans (important for casts)
968 Return value: pointer to the array or NULL if no memory is
971 *******************************************************************************/
973 java_booleanarray *builtin_newarray_boolean(s4 size)
975 return (java_booleanarray *)
976 builtin_newarray(size,
977 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
981 /* builtin_multianewarray ******************************************************
983 Creates a multi-dimensional array on the heap. The dimensions are
984 passed in an array of longs.
987 n............number of dimensions to create
988 arrayvftbl...vftbl of the array class
989 dims.........array containing the size of each dimension to create
991 Return value: pointer to the array or NULL if no memory is
994 ******************************************************************************/
996 java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims)
1000 vftbl_t *componentvftbl;
1002 /* create this dimension */
1004 size = (s4) dims[0];
1005 a = builtin_newarray(size, arrayvftbl);
1010 /* if this is the last dimension return */
1015 /* get the vftbl of the components to create */
1017 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
1019 /* The verifier guarantees that the dimension count is in the range. */
1021 /* create the component arrays */
1023 for (i = 0; i < size; i++) {
1024 java_arrayheader *ea =
1025 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1026 /* we save an s4 to a s8 slot, 8-byte aligned */
1028 builtin_multianewarray(n, componentvftbl, dims + 2);
1030 builtin_multianewarray(n, componentvftbl, dims + 1);
1036 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1043 /*****************************************************************************
1046 Various functions for printing a message at method entry or exit (for
1049 *****************************************************************************/
1051 u4 methodindent = 0;
1053 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1063 if (opt_verbose || runverbose || verboseexception) {
1064 /* calculate message length */
1068 strlen("Exception ") +
1069 utf_strlen(xptr->vftbl->class->name);
1072 logtextlen = strlen("Some Throwable");
1074 logtextlen += strlen(" thrown in ");
1078 utf_strlen(m->class->name) +
1080 utf_strlen(m->name) +
1081 utf_strlen(m->descriptor) +
1082 strlen("(NOSYNC,NATIVE");
1084 #if SIZEOF_VOID_P == 8
1086 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1088 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1091 if (m->class->sourcefile == NULL)
1092 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1094 logtextlen += utf_strlen(m->class->sourcefile);
1096 logtextlen += strlen(":65536)");
1099 logtextlen += strlen("call_java_method");
1101 logtextlen += strlen("0");
1103 /* allocate memory */
1105 dumpsize = dump_size();
1107 logtext = DMNEW(char, logtextlen);
1110 strcpy(logtext, "Exception ");
1111 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1114 strcpy(logtext, "Some Throwable");
1117 strcat(logtext, " thrown in ");
1120 utf_strcat_classname(logtext, m->class->name);
1121 strcat(logtext, ".");
1122 utf_strcat(logtext, m->name);
1123 utf_strcat(logtext, m->descriptor);
1125 if (m->flags & ACC_SYNCHRONIZED)
1126 strcat(logtext, "(SYNC");
1128 strcat(logtext, "(NOSYNC");
1130 if (m->flags & ACC_NATIVE) {
1131 strcat(logtext, ",NATIVE");
1133 #if SIZEOF_VOID_P == 8
1134 sprintf(logtext + strlen(logtext),
1135 ")(0x%016lx) at position 0x%016lx",
1136 (ptrint) m->entrypoint, (ptrint) pos);
1138 sprintf(logtext + strlen(logtext),
1139 ")(0x%08x) at position 0x%08x",
1140 (ptrint) m->entrypoint, (ptrint) pos);
1144 #if SIZEOF_VOID_P == 8
1145 sprintf(logtext + strlen(logtext),
1146 ")(0x%016lx) at position 0x%016lx (",
1147 (ptrint) m->entrypoint, (ptrint) pos);
1149 sprintf(logtext + strlen(logtext),
1150 ")(0x%08x) at position 0x%08x (",
1151 (ptrint) m->entrypoint, (ptrint) pos);
1154 if (m->class->sourcefile == NULL)
1155 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1157 utf_strcat(logtext, m->class->sourcefile);
1159 sprintf(logtext + strlen(logtext), ":%d)", line);
1163 strcat(logtext, "call_java_method");
1167 /* release memory */
1169 dump_release(dumpsize);
1176 /* builtin_trace_args **********************************************************
1180 *******************************************************************************/
1182 #ifdef TRACE_ARGS_NUM
1183 void builtin_trace_args(s8 a0, s8 a1,
1184 #if TRACE_ARGS_NUM >= 4
1186 #endif /* TRACE_ARGS_NUM >= 4 */
1187 #if TRACE_ARGS_NUM >= 6
1189 #endif /* TRACE_ARGS_NUM >= 6 */
1190 #if TRACE_ARGS_NUM == 8
1192 #endif /* TRACE_ARGS_NUM == 8 */
1203 /* calculate message length */
1206 methodindent + strlen("called: ") +
1207 utf_strlen(m->class->name) +
1209 utf_strlen(m->name) +
1210 utf_strlen(m->descriptor) +
1211 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1213 /* add maximal argument length */
1215 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1217 /* allocate memory */
1219 dumpsize = dump_size();
1221 logtext = DMNEW(char, logtextlen);
1223 for (i = 0; i < methodindent; i++)
1226 strcpy(logtext + methodindent, "called: ");
1228 utf_strcat_classname(logtext, m->class->name);
1229 strcat(logtext, ".");
1230 utf_strcat(logtext, m->name);
1231 utf_strcat(logtext, m->descriptor);
1233 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1234 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1235 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1236 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1237 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1238 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1239 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1240 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1241 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1242 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1243 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1245 strcat(logtext, "(");
1247 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1248 /* Only Arguments in integer Registers are passed correctly here */
1249 /* long longs spilled on Stack have an wrong offset of +4 */
1250 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1251 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1252 switch (md->paramcount) {
1256 #if SIZEOF_VOID_P == 4
1258 sprintf(logtext + strlen(logtext),
1264 sprintf(logtext + strlen(logtext),
1269 #if TRACE_ARGS_NUM >= 4
1271 sprintf(logtext + strlen(logtext),
1272 "0x%llx, 0x%llx, 0x%llx",
1277 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1279 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1282 #endif /* TRACE_ARGS_NUM >= 4 */
1284 #if TRACE_ARGS_NUM >= 6
1286 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1288 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1293 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1295 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1298 #endif /* TRACE_ARGS_NUM >= 6 */
1300 #if TRACE_ARGS_NUM == 8
1302 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1304 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1306 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1310 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1312 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1314 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1316 #endif /* TRACE_ARGS_NUM == 8 */
1319 #if TRACE_ARGS_NUM == 2
1320 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1322 #elif TRACE_ARGS_NUM == 4
1323 sprintf(logtext + strlen(logtext),
1324 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1325 a0, a1, a2, a3, md->paramcount - 4);
1327 #elif TRACE_ARGS_NUM == 6
1328 sprintf(logtext + strlen(logtext),
1329 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1330 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1332 #elif TRACE_ARGS_NUM == 8
1333 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1335 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1337 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1338 , a6, a7, md->paramcount - 8);
1342 #else /* SIZEOF_VOID_P == 4 */
1345 sprintf(logtext + strlen(logtext),
1351 sprintf(logtext + strlen(logtext),
1357 sprintf(logtext + strlen(logtext),
1358 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1362 sprintf(logtext + strlen(logtext),
1363 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1367 #if TRACE_ARGS_NUM >= 6
1369 sprintf(logtext + strlen(logtext),
1370 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1371 a0, a1, a2, a3, a4);
1375 sprintf(logtext + strlen(logtext),
1376 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1377 a0, a1, a2, a3, a4, a5);
1379 #endif /* TRACE_ARGS_NUM >= 6 */
1381 #if TRACE_ARGS_NUM == 8
1383 sprintf(logtext + strlen(logtext),
1384 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1385 a0, a1, a2, a3, a4, a5, a6);
1389 sprintf(logtext + strlen(logtext),
1390 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1391 a0, a1, a2, a3, a4, a5, a6, a7);
1393 #endif /* TRACE_ARGS_NUM == 8 */
1396 #if TRACE_ARGS_NUM == 4
1397 sprintf(logtext + strlen(logtext),
1398 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1399 a0, a1, a2, a3, md->paramcount - 4);
1401 #elif TRACE_ARGS_NUM == 6
1402 sprintf(logtext + strlen(logtext),
1403 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1404 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1406 #elif TRACE_ARGS_NUM == 8
1407 sprintf(logtext + strlen(logtext),
1408 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1409 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1412 #endif /* SIZEOF_VOID_P == 4 */
1415 strcat(logtext, ")");
1419 /* release memory */
1421 dump_release(dumpsize);
1428 /* builtin_displaymethodstop ***************************************************
1432 *******************************************************************************/
1434 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1445 /* calculate message length */
1448 methodindent + strlen("finished: ") +
1449 utf_strlen(m->class->name) +
1451 utf_strlen(m->name) +
1452 utf_strlen(m->descriptor) +
1453 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1455 /* add maximal argument length */
1457 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1459 /* allocate memory */
1461 dumpsize = dump_size();
1463 logtext = DMNEW(char, logtextlen);
1465 /* generate the message */
1467 for (i = 0; i < methodindent; i++)
1473 log_text("WARNING: unmatched methodindent--");
1475 strcpy(logtext + methodindent, "finished: ");
1476 utf_strcat_classname(logtext, m->class->name);
1477 strcat(logtext, ".");
1478 utf_strcat(logtext, m->name);
1479 utf_strcat(logtext, m->descriptor);
1481 switch (md->returntype.type) {
1483 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1487 #if SIZEOF_VOID_P == 4
1488 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1490 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1495 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1500 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1505 #if SIZEOF_VOID_P == 4
1506 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1508 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1515 /* release memory */
1517 dump_release(dumpsize);
1521 /****************************************************************************
1522 SYNCHRONIZATION FUNCTIONS
1523 *****************************************************************************/
1525 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1527 * Lock the mutex of an object.
1529 void internal_lock_mutex_for_object(java_objectheader *object)
1531 mutexHashEntry *entry;
1534 assert(object != 0);
1536 hashValue = MUTEX_HASH_VALUE(object);
1537 entry = &mutexHashTable[hashValue];
1539 if (entry->object != 0) {
1540 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1542 entry->mutex.holder = 0;
1543 entry->mutex.count = 0;
1544 entry->mutex.muxWaiters = 0;
1547 while (entry->next != 0 && entry->object != object)
1548 entry = entry->next;
1550 if (entry->object != object) {
1551 entry->next = firstFreeOverflowEntry;
1552 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1554 entry = entry->next;
1557 assert(entry->conditionCount == 0);
1562 entry->mutex.holder = 0;
1563 entry->mutex.count = 0;
1564 entry->mutex.muxWaiters = 0;
1567 if (entry->object == 0)
1568 entry->object = object;
1570 internal_lock_mutex(&entry->mutex);
1575 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1577 * Unlocks the mutex of an object.
1579 void internal_unlock_mutex_for_object (java_objectheader *object)
1582 mutexHashEntry *entry;
1584 hashValue = MUTEX_HASH_VALUE(object);
1585 entry = &mutexHashTable[hashValue];
1587 if (entry->object == object) {
1588 internal_unlock_mutex(&entry->mutex);
1591 while (entry->next != 0 && entry->next->object != object)
1592 entry = entry->next;
1594 assert(entry->next != 0);
1596 internal_unlock_mutex(&entry->next->mutex);
1598 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1599 mutexHashEntry *unlinked = entry->next;
1601 entry->next = unlinked->next;
1602 unlinked->next = firstFreeOverflowEntry;
1603 firstFreeOverflowEntry = unlinked;
1610 #if defined(USE_THREADS)
1611 void builtin_monitorenter(java_objectheader *o)
1613 #if !defined(NATIVE_THREADS)
1618 hashValue = MUTEX_HASH_VALUE(o);
1619 if (mutexHashTable[hashValue].object == o
1620 && mutexHashTable[hashValue].mutex.holder == currentThread)
1621 ++mutexHashTable[hashValue].mutex.count;
1623 internal_lock_mutex_for_object(o);
1627 monitorEnter((threadobject *) THREADOBJECT, o);
1633 #if defined(USE_THREADS)
1635 * Locks the class object - needed for static synchronized methods.
1636 * The use_class_as_object call is needed in order to circumvent a
1637 * possible deadlock with builtin_monitorenter called by another
1638 * thread calling use_class_as_object.
1640 void builtin_staticmonitorenter(classinfo *c)
1642 use_class_as_object(c);
1643 builtin_monitorenter(&c->header);
1648 #if defined(USE_THREADS)
1649 void builtin_monitorexit(java_objectheader *o)
1651 #if !defined(NATIVE_THREADS)
1656 hashValue = MUTEX_HASH_VALUE(o);
1657 if (mutexHashTable[hashValue].object == o) {
1658 if (mutexHashTable[hashValue].mutex.count == 1
1659 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1660 internal_unlock_mutex_for_object(o);
1662 --mutexHashTable[hashValue].mutex.count;
1665 internal_unlock_mutex_for_object(o);
1669 monitorExit((threadobject *) THREADOBJECT, o);
1675 /*****************************************************************************
1676 MISCELLANEOUS HELPER FUNCTIONS
1677 *****************************************************************************/
1681 /*********** Functions for integer divisions *****************************
1683 On some systems (eg. DEC ALPHA), integer division is not supported by the
1684 CPU. These helper functions implement the missing functionality.
1686 ******************************************************************************/
1688 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1689 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1692 /************** Functions for long arithmetics *******************************
1694 On systems where 64 bit Integers are not supported by the CPU, these
1695 functions are needed.
1697 ******************************************************************************/
1699 s8 builtin_ladd(s8 a, s8 b)
1712 s8 builtin_lsub(s8 a, s8 b)
1725 s8 builtin_lmul(s8 a, s8 b)
1738 s8 builtin_ldiv(s8 a, s8 b)
1751 s8 builtin_lrem(s8 a, s8 b)
1764 s8 builtin_lshl(s8 a, s4 b)
1777 s8 builtin_lshr(s8 a, s4 b)
1790 s8 builtin_lushr(s8 a, s4 b)
1795 c = ((u8) a) >> (b & 63);
1803 s8 builtin_land(s8 a, s8 b)
1816 s8 builtin_lor(s8 a, s8 b)
1829 s8 builtin_lxor(s8 a, s8 b)
1842 s8 builtin_lneg(s8 a)
1855 s4 builtin_lcmp(s8 a, s8 b)
1858 if (a < b) return -1;
1859 if (a > b) return 1;
1870 /*********** Functions for floating point operations *************************/
1872 float builtin_fadd(float a, float b)
1874 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1875 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1886 if (copysignf(1.0, a) == copysignf(1.0, b))
1889 return intBitsToFloat(FLT_NAN);
1895 float builtin_fsub(float a, float b)
1897 return builtin_fadd(a, builtin_fneg(b));
1901 float builtin_fmul(float a, float b)
1903 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1904 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1906 if (finitef(b)) return a * b;
1908 if (a == 0) return intBitsToFloat(FLT_NAN);
1909 else return copysignf(b, copysignf(1.0, b)*a);
1914 if (b == 0) return intBitsToFloat(FLT_NAN);
1915 else return copysignf(a, copysignf(1.0, a)*b);
1918 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1924 /* builtin_ddiv ****************************************************************
1926 Implementation as described in VM Spec.
1928 *******************************************************************************/
1930 float builtin_fdiv(float a, float b)
1934 /* If neither value1' nor value2' is NaN, the sign of the result */
1935 /* is positive if both values have the same sign, negative if the */
1936 /* values have different signs. */
1942 /* If either value1' or value2' is NaN, the result is NaN. */
1944 return intBitsToFloat(FLT_NAN);
1947 /* Division of a finite value by an infinity results in a */
1948 /* signed zero, with the sign-producing rule just given. */
1950 /* is sign equal? */
1952 if (copysignf(1.0, a) == copysignf(1.0, b))
1961 /* If either value1' or value2' is NaN, the result is NaN. */
1963 return intBitsToFloat(FLT_NAN);
1965 } else if (finitef(b)) {
1966 /* Division of an infinity by a finite value results in a signed */
1967 /* infinity, with the sign-producing rule just given. */
1969 /* is sign equal? */
1971 if (copysignf(1.0, a) == copysignf(1.0, b))
1972 return intBitsToFloat(FLT_POSINF);
1974 return intBitsToFloat(FLT_NEGINF);
1977 /* Division of an infinity by an infinity results in NaN. */
1979 return intBitsToFloat(FLT_NAN);
1985 float builtin_frem(float a, float b)
1991 float builtin_fneg(float a)
1993 if (isnanf(a)) return a;
1995 if (finitef(a)) return -a;
1996 else return copysignf(a, -copysignf(1.0, a));
2001 s4 builtin_fcmpl(float a, float b)
2003 if (isnanf(a)) return -1;
2004 if (isnanf(b)) return -1;
2005 if (!finitef(a) || !finitef(b)) {
2006 a = finitef(a) ? 0 : copysignf(1.0, a);
2007 b = finitef(b) ? 0 : copysignf(1.0, b);
2009 if (a > b) return 1;
2010 if (a == b) return 0;
2015 s4 builtin_fcmpg(float a, float b)
2017 if (isnanf(a)) return 1;
2018 if (isnanf(b)) return 1;
2019 if (!finitef(a) || !finitef(b)) {
2020 a = finitef(a) ? 0 : copysignf(1.0, a);
2021 b = finitef(b) ? 0 : copysignf(1.0, b);
2023 if (a > b) return 1;
2024 if (a == b) return 0;
2030 /************************* Functions for doubles ****************************/
2032 double builtin_dadd(double a, double b)
2034 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2035 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2037 if (finite(b)) return a + b;
2041 if (finite(b)) return a;
2043 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2044 else return longBitsToDouble(DBL_NAN);
2050 double builtin_dsub(double a, double b)
2052 return builtin_dadd(a, builtin_dneg(b));
2056 double builtin_dmul(double a, double b)
2058 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2059 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2061 if (finite(b)) return a * b;
2063 if (a == 0) return longBitsToDouble(DBL_NAN);
2064 else return copysign(b, copysign(1.0, b) * a);
2069 if (b == 0) return longBitsToDouble(DBL_NAN);
2070 else return copysign(a, copysign(1.0, a) * b);
2073 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2079 /* builtin_ddiv ****************************************************************
2081 Implementation as described in VM Spec.
2083 *******************************************************************************/
2085 double builtin_ddiv(double a, double b)
2089 /* If neither value1' nor value2' is NaN, the sign of the result */
2090 /* is positive if both values have the same sign, negative if the */
2091 /* values have different signs. */
2097 /* If either value1' or value2' is NaN, the result is NaN. */
2099 return longBitsToDouble(DBL_NAN);
2102 /* Division of a finite value by an infinity results in a */
2103 /* signed zero, with the sign-producing rule just given. */
2105 /* is sign equal? */
2107 if (copysign(1.0, a) == copysign(1.0, b))
2116 /* If either value1' or value2' is NaN, the result is NaN. */
2118 return longBitsToDouble(DBL_NAN);
2120 } else if (finite(b)) {
2121 /* Division of an infinity by a finite value results in a signed */
2122 /* infinity, with the sign-producing rule just given. */
2124 /* is sign equal? */
2126 if (copysign(1.0, a) == copysign(1.0, b))
2127 return longBitsToDouble(DBL_POSINF);
2129 return longBitsToDouble(DBL_NEGINF);
2132 /* Division of an infinity by an infinity results in NaN. */
2134 return longBitsToDouble(DBL_NAN);
2140 double builtin_drem(double a, double b)
2145 /* builtin_dneg ****************************************************************
2147 Implemented as described in VM Spec.
2149 *******************************************************************************/
2151 double builtin_dneg(double a)
2154 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2161 /* If the operand is a zero, the result is the zero of opposite */
2167 /* If the operand is an infinity, the result is the infinity of */
2168 /* opposite sign. */
2170 return copysign(a, -copysign(1.0, a));
2176 s4 builtin_dcmpl(double a, double b)
2178 if (isnan(a)) return -1;
2179 if (isnan(b)) return -1;
2180 if (!finite(a) || !finite(b)) {
2181 a = finite(a) ? 0 : copysign(1.0, a);
2182 b = finite(b) ? 0 : copysign(1.0, b);
2184 if (a > b) return 1;
2185 if (a == b) return 0;
2190 s4 builtin_dcmpg(double a, double b)
2192 if (isnan(a)) return 1;
2193 if (isnan(b)) return 1;
2194 if (!finite(a) || !finite(b)) {
2195 a = finite(a) ? 0 : copysign(1.0, a);
2196 b = finite(b) ? 0 : copysign(1.0, b);
2198 if (a > b) return 1;
2199 if (a == b) return 0;
2204 /*********************** Conversion operations ****************************/
2206 s8 builtin_i2l(s4 i)
2219 float builtin_i2f(s4 a)
2221 float f = (float) a;
2226 double builtin_i2d(s4 a)
2228 double d = (double) a;
2233 s4 builtin_l2i(s8 l)
2243 float builtin_l2f(s8 a)
2246 float f = (float) a;
2254 double builtin_l2d(s8 a)
2257 double d = (double) a;
2265 s4 builtin_f2i(float a)
2269 i = builtin_d2i((double) a);
2280 if (a < (-2147483648))
2281 return (-2147483648);
2284 f = copysignf((float) 1.0, a);
2287 return (-2147483648); */
2291 s8 builtin_f2l(float a)
2295 l = builtin_d2l((double) a);
2302 if (a > 9223372036854775807L)
2303 return 9223372036854775807L;
2304 if (a < (-9223372036854775808L))
2305 return (-9223372036854775808L);
2310 f = copysignf((float) 1.0, a);
2312 return 9223372036854775807L;
2313 return (-9223372036854775808L); */
2317 double builtin_f2d(float a)
2319 if (finitef(a)) return (double) a;
2322 return longBitsToDouble(DBL_NAN);
2324 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2329 s4 builtin_d2i(double a)
2334 if (a >= 2147483647)
2336 if (a <= (-2147483647-1))
2337 return (-2147483647-1);
2342 d = copysign(1.0, a);
2345 return (-2147483647-1);
2349 s8 builtin_d2l(double a)
2354 if (a >= 9223372036854775807LL)
2355 return 9223372036854775807LL;
2356 if (a <= (-9223372036854775807LL-1))
2357 return (-9223372036854775807LL-1);
2362 d = copysign(1.0, a);
2364 return 9223372036854775807LL;
2365 return (-9223372036854775807LL-1);
2369 float builtin_d2f(double a)
2375 return intBitsToFloat(FLT_NAN);
2377 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2382 /* used to convert FLT_xxx defines into float values */
2384 inline float intBitsToFloat(s4 i)
2393 /* used to convert DBL_xxx defines into double values */
2395 inline float longBitsToDouble(s8 l)
2404 /* builtin_clone_array *********************************************************
2406 Wrapper function for cloning arrays.
2408 *******************************************************************************/
2410 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2412 java_arrayheader *ah;
2413 java_lang_Cloneable *c;
2415 c = (java_lang_Object *) o;
2417 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2423 /* builtin_asm_get_exceptionptrptr *********************************************
2425 this is a wrapper for calls from asmpart
2427 *******************************************************************************/
2429 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2430 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2432 return builtin_get_exceptionptrptr();
2437 methodinfo *builtin_asm_get_threadrootmethod(void)
2439 return *threadrootmethod;
2443 void *builtin_asm_get_stackframeinfo(void)
2445 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2446 return &THREADINFO->_stackframeinfo;
2448 /* XXX FIXME FOR OLD THREAD IMPL (jowenn) */
2450 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2455 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,
2456 stacktraceelement *begin,
2457 stacktraceelement *end)
2459 /* stacktraceelement *el;*/
2462 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2463 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2465 *el=MNEW(stacktraceelement,s+1); /*GC*/
2467 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2470 /* XXX change this if line numbers bigger than u2 are allowed, the */
2471 /* currently supported class file format does no allow that */
2473 (*el)[s].linenumber=-1; /* -1 can never be reched otherwise, since line numbers are only u2, so it is save to use that as flag */
2479 * These are local overrides for various environment variables in Emacs.
2480 * Please do not remove this and leave it at the end of the file, where
2481 * Emacs will automagically detect them.
2482 * ---------------------------------------------------------------------
2485 * indent-tabs-mode: t