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 3174 2005-09-12 08:59:06Z twisti $
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 res = (sub->vftbl->interfacetablelength > super->index) &&
348 (sub->vftbl->interfacetable[-super->index] != NULL);
351 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
353 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
354 (u4) classvalues.super_diffval;
361 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
365 castinfo classvalues;
370 asm_getclassvalues_atomic(super, sub, &classvalues);
372 if ((base = classvalues.super_baseval) <= 0) {
373 /* super is an interface */
374 res = (sub->interfacetablelength > -base) &&
375 (sub->interfacetable[base] != NULL);
377 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
378 <= (u4) classvalues.super_diffval;
385 /****************** function: builtin_instanceof *****************************
387 Checks if an object is an instance of some given class (or subclass of
388 that class). If class is an interface, checks if the interface is
390 Return value: 1 ... obj is an instance of class or implements the interface
391 0 ... otherwise or if obj == NULL
393 *****************************************************************************/
395 /* XXX should use vftbl */
396 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
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)
419 if (builtin_isanysubclass(obj->vftbl->class, class))
426 /* builtin_descriptorscompatible ***********************************************
428 Checks if two array type descriptors are assignment compatible
430 Return value: 1 ... target = desc is possible
433 *******************************************************************************/
435 static s4 builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
440 if (desc->arraytype != target->arraytype)
443 if (desc->arraytype != ARRAYTYPE_OBJECT)
446 /* {both arrays are arrays of references} */
448 if (desc->dimension == target->dimension) {
449 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
450 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
451 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
453 if (desc->dimension < target->dimension) return 0;
455 /* {desc has higher dimension than target} */
456 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
460 /* builtin_arraycheckcast ******************************************************
462 Checks if an object is really a subtype of the requested array
463 type. The object has to be an array to begin with. For simple
464 arrays (int, short, double, etc.) the types have to match exactly.
465 For arrays of objects, the type of elements in the array has to be
466 a subtype (or the same type) of the requested element type. For
467 arrays of arrays (which in turn can again be arrays of arrays), the
468 types at the lowest level have to satisfy the corresponding sub
471 *******************************************************************************/
473 s4 builtin_arraycheckcast(java_objectheader *o, vftbl_t *target)
475 arraydescriptor *desc;
480 if ((desc = o->vftbl->arraydesc) == NULL)
483 return builtin_descriptorscompatible(desc, target->arraydesc);
487 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
492 return builtin_arraycheckcast(obj, target);
496 /************************** exception functions *******************************
498 ******************************************************************************/
500 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
502 java_lang_Throwable *t;
508 t = (java_lang_Throwable *) xptr;
510 /* calculate message length */
512 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
516 utf_strlen(xptr->vftbl->class->name) +
518 javastring_strlen((java_objectheader *) t->detailMessage);
521 logtextlen += strlen("(nil)");
523 /* allocate memory */
525 dumpsize = dump_size();
527 logtext = DMNEW(char, logtextlen);
529 strcpy(logtext, "Builtin exception thrown: ");
532 utf_sprint_classname(logtext + strlen(logtext),
533 xptr->vftbl->class->name);
535 if (t->detailMessage) {
538 buf = javastring_tochar((java_objectheader *) t->detailMessage);
539 strcat(logtext, ": ");
540 strcat(logtext, buf);
541 MFREE(buf, char, strlen(buf));
545 strcat(logtext, "(nil)");
552 dump_release(dumpsize);
555 *exceptionptr = xptr;
562 /* builtin_canstore ************************************************************
564 Checks, if an object can be stored in an array.
566 Return value: 1 ... possible
569 *******************************************************************************/
571 s4 builtin_canstore(java_objectarray *a, java_objectheader *o)
573 arraydescriptor *desc;
574 arraydescriptor *valuedesc;
575 vftbl_t *componentvftbl;
578 castinfo classvalues;
583 /* The following is guaranteed (by verifier checks):
585 * *) a->...vftbl->arraydesc != NULL
586 * *) a->...vftbl->arraydesc->componentvftbl != NULL
587 * *) o->vftbl is not an interface vftbl
590 desc = a->header.objheader.vftbl->arraydesc;
591 componentvftbl = desc->componentvftbl;
592 valuevftbl = o->vftbl;
594 if ((desc->dimension - 1) == 0) {
597 /* {a is a one-dimensional array} */
598 /* {a is an array of references} */
600 if (valuevftbl == componentvftbl)
603 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
605 if ((base = classvalues.super_baseval) <= 0)
606 /* an array of interface references */
607 return (valuevftbl->interfacetablelength > -base &&
608 valuevftbl->interfacetable[base] != NULL);
610 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
611 <= (unsigned) classvalues.super_diffval;
616 /* {a has dimension > 1} */
617 /* {componentvftbl->arraydesc != NULL} */
619 /* check if o is an array */
620 if ((valuedesc = valuevftbl->arraydesc) == NULL)
622 /* {o is an array} */
624 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
628 /* This is an optimized version where a is guaranteed to be one-dimensional */
629 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
631 arraydescriptor *desc;
632 vftbl_t *elementvftbl;
636 castinfo classvalues;
640 /* The following is guaranteed (by verifier checks):
642 * *) a->...vftbl->arraydesc != NULL
643 * *) a->...vftbl->arraydesc->elementvftbl != NULL
644 * *) a->...vftbl->arraydesc->dimension == 1
645 * *) o->vftbl is not an interface vftbl
648 desc = a->header.objheader.vftbl->arraydesc;
649 elementvftbl = desc->elementvftbl;
650 valuevftbl = o->vftbl;
652 /* {a is a one-dimensional array} */
654 if (valuevftbl == elementvftbl)
657 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
659 if ((base = classvalues.super_baseval) <= 0)
660 /* an array of interface references */
661 return (valuevftbl->interfacetablelength > -base &&
662 valuevftbl->interfacetable[base] != NULL);
664 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
665 <= (unsigned) classvalues.super_diffval;
671 /* This is an optimized version where a is guaranteed to be a
672 * one-dimensional array of a class type */
673 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
675 vftbl_t *elementvftbl;
678 castinfo classvalues;
682 /* The following is guaranteed (by verifier checks):
684 * *) a->...vftbl->arraydesc != NULL
685 * *) a->...vftbl->arraydesc->elementvftbl != NULL
686 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
687 * *) a->...vftbl->arraydesc->dimension == 1
688 * *) o->vftbl is not an interface vftbl
691 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
692 valuevftbl = o->vftbl;
694 /* {a is a one-dimensional array} */
696 if (valuevftbl == elementvftbl)
699 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
701 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
702 <= (unsigned) classvalues.super_diffval;
708 /* builtin_new *****************************************************************
710 Creates a new instance of class c on the heap.
712 Return value: pointer to the object or NULL if no memory is
715 *******************************************************************************/
717 java_objectheader *builtin_new(classinfo *c)
719 java_objectheader *o;
721 /* is the class loaded */
725 /* is the class linked */
730 if (!c->initialized) {
732 log_message_class("Initialize class (from builtin_new): ", c);
734 if (!initialize_class(c))
738 o = heap_allocate(c->instancesize, true, c->finalizer);
743 MSET(o, 0, u1, c->instancesize);
747 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
755 /* builtin_newarray ************************************************************
757 Creates an array with the given vftbl on the heap.
759 Return value: pointer to the array or NULL if no memory is available
761 CAUTION: The given vftbl must be the vftbl of the *array* class,
762 not of the element class.
764 *******************************************************************************/
766 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
769 arraydescriptor *desc;
774 desc = arrayvftbl->arraydesc;
775 dataoffset = desc->dataoffset;
776 componentsize = desc->componentsize;
779 *exceptionptr = new_negativearraysizeexception();
783 actualsize = dataoffset + size * componentsize;
785 if (((u4) actualsize) < ((u4) size)) { /* overflow */
786 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
790 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
795 MSET(a, 0, u1, actualsize);
797 a->objheader.vftbl = arrayvftbl;
799 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
800 initObjectLock(&a->objheader);
809 /* builtin_anewarray ***********************************************************
811 Creates an array of references to the given class type on the heap.
813 Return value: pointer to the array or NULL if no memory is
816 *******************************************************************************/
818 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
822 /* is class loaded */
823 assert(component->loaded);
825 /* is class linked */
826 if (!component->linked)
827 if (!link_class(component))
830 c = class_array_of(component, true);
835 return (java_objectarray *) builtin_newarray(size, c->vftbl);
839 /* builtin_newarray_int ********************************************************
841 Creates an array of 32 bit Integers on the heap.
843 Return value: pointer to the array or NULL if no memory is
846 *******************************************************************************/
848 java_intarray *builtin_newarray_int(s4 size)
850 return (java_intarray *)
851 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
855 /* builtin_newarray_long *******************************************************
857 Creates an array of 64 bit Integers on the heap.
859 Return value: pointer to the array or NULL if no memory is
862 *******************************************************************************/
864 java_longarray *builtin_newarray_long(s4 size)
866 return (java_longarray *)
867 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
871 /* builtin_newarray_float ******************************************************
873 Creates an array of 32 bit IEEE floats on the heap.
875 Return value: pointer to the array or NULL if no memory is
878 *******************************************************************************/
880 java_floatarray *builtin_newarray_float(s4 size)
882 return (java_floatarray *)
883 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
887 /* builtin_newarray_double *****************************************************
889 Creates an array of 64 bit IEEE floats on the heap.
891 Return value: pointer to the array or NULL if no memory is
894 *******************************************************************************/
896 java_doublearray *builtin_newarray_double(s4 size)
898 return (java_doublearray *)
899 builtin_newarray(size,
900 primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
904 /* builtin_newarray_byte *******************************************************
906 Creates an array of 8 bit Integers on the heap.
908 Return value: pointer to the array or NULL if no memory is
911 *******************************************************************************/
913 java_bytearray *builtin_newarray_byte(s4 size)
915 return (java_bytearray *)
916 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
920 /* builtin_newarray_char *******************************************************
922 Creates an array of characters on the heap.
924 Return value: pointer to the array or NULL if no memory is
927 *******************************************************************************/
929 java_chararray *builtin_newarray_char(s4 size)
931 return (java_chararray *)
932 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
936 /* builtin_newarray_short ******************************************************
938 Creates an array of 16 bit Integers on the heap.
940 Return value: pointer to the array or NULL if no memory is
943 *******************************************************************************/
945 java_shortarray *builtin_newarray_short(s4 size)
947 return (java_shortarray *)
948 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
952 /* builtin_newarray_boolean ****************************************************
954 Creates an array of bytes on the heap. The array is designated as
955 an array of booleans (important for casts)
957 Return value: pointer to the array or NULL if no memory is
960 *******************************************************************************/
962 java_booleanarray *builtin_newarray_boolean(s4 size)
964 return (java_booleanarray *)
965 builtin_newarray(size,
966 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
970 /* builtin_multianewarray ******************************************************
972 Creates a multi-dimensional array on the heap. The dimensions are
973 passed in an array of longs.
976 n............number of dimensions to create
977 arrayvftbl...vftbl of the array class
978 dims.........array containing the size of each dimension to create
980 Return value: pointer to the array or NULL if no memory is
983 ******************************************************************************/
985 java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims)
989 vftbl_t *componentvftbl;
991 /* create this dimension */
994 a = builtin_newarray(size, arrayvftbl);
999 /* if this is the last dimension return */
1004 /* get the vftbl of the components to create */
1006 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
1008 /* The verifier guarantees that the dimension count is in the range. */
1010 /* create the component arrays */
1012 for (i = 0; i < size; i++) {
1013 java_arrayheader *ea =
1014 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1015 /* we save an s4 to a s8 slot, 8-byte aligned */
1017 builtin_multianewarray(n, componentvftbl, dims + 2);
1019 builtin_multianewarray(n, componentvftbl, dims + 1);
1025 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1032 /*****************************************************************************
1035 Various functions for printing a message at method entry or exit (for
1038 *****************************************************************************/
1040 u4 methodindent = 0;
1042 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1052 if (opt_verbose || runverbose || verboseexception) {
1053 /* calculate message length */
1057 strlen("Exception ") +
1058 utf_strlen(xptr->vftbl->class->name);
1061 logtextlen = strlen("Some Throwable");
1063 logtextlen += strlen(" thrown in ");
1067 utf_strlen(m->class->name) +
1069 utf_strlen(m->name) +
1070 utf_strlen(m->descriptor) +
1071 strlen("(NOSYNC,NATIVE");
1073 #if SIZEOF_VOID_P == 8
1075 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1077 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1080 if (m->class->sourcefile == NULL)
1081 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1083 logtextlen += utf_strlen(m->class->sourcefile);
1085 logtextlen += strlen(":65536)");
1088 logtextlen += strlen("call_java_method");
1090 logtextlen += strlen("0");
1092 /* allocate memory */
1094 dumpsize = dump_size();
1096 logtext = DMNEW(char, logtextlen);
1099 strcpy(logtext, "Exception ");
1100 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1103 strcpy(logtext, "Some Throwable");
1106 strcat(logtext, " thrown in ");
1109 utf_strcat_classname(logtext, m->class->name);
1110 strcat(logtext, ".");
1111 utf_strcat(logtext, m->name);
1112 utf_strcat(logtext, m->descriptor);
1114 if (m->flags & ACC_SYNCHRONIZED)
1115 strcat(logtext, "(SYNC");
1117 strcat(logtext, "(NOSYNC");
1119 if (m->flags & ACC_NATIVE) {
1120 strcat(logtext, ",NATIVE");
1122 #if SIZEOF_VOID_P == 8
1123 sprintf(logtext + strlen(logtext),
1124 ")(0x%016lx) at position 0x%016lx",
1125 (ptrint) m->entrypoint, (ptrint) pos);
1127 sprintf(logtext + strlen(logtext),
1128 ")(0x%08x) at position 0x%08x",
1129 (ptrint) m->entrypoint, (ptrint) pos);
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);
1143 if (m->class->sourcefile == NULL)
1144 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1146 utf_strcat(logtext, m->class->sourcefile);
1148 sprintf(logtext + strlen(logtext), ":%d)", line);
1152 strcat(logtext, "call_java_method");
1156 /* release memory */
1158 dump_release(dumpsize);
1165 /* builtin_trace_args **********************************************************
1169 *******************************************************************************/
1171 #ifdef TRACE_ARGS_NUM
1172 void builtin_trace_args(s8 a0, s8 a1,
1173 #if TRACE_ARGS_NUM >= 4
1175 #endif /* TRACE_ARGS_NUM >= 4 */
1176 #if TRACE_ARGS_NUM >= 6
1178 #endif /* TRACE_ARGS_NUM >= 6 */
1179 #if TRACE_ARGS_NUM == 8
1181 #endif /* TRACE_ARGS_NUM == 8 */
1192 /* calculate message length */
1195 methodindent + strlen("called: ") +
1196 utf_strlen(m->class->name) +
1198 utf_strlen(m->name) +
1199 utf_strlen(m->descriptor) +
1200 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1202 /* add maximal argument length */
1204 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1206 /* allocate memory */
1208 dumpsize = dump_size();
1210 logtext = DMNEW(char, logtextlen);
1212 for (i = 0; i < methodindent; i++)
1215 strcpy(logtext + methodindent, "called: ");
1217 utf_strcat_classname(logtext, m->class->name);
1218 strcat(logtext, ".");
1219 utf_strcat(logtext, m->name);
1220 utf_strcat(logtext, m->descriptor);
1222 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1223 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1224 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1225 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1226 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1227 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1228 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1229 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1230 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1231 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1232 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1234 strcat(logtext, "(");
1236 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1237 /* Only Arguments in integer Registers are passed correctly here */
1238 /* long longs spilled on Stack have an wrong offset of +4 */
1239 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1240 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1241 switch (md->paramcount) {
1245 #if SIZEOF_VOID_P == 4
1247 sprintf(logtext + strlen(logtext),
1253 sprintf(logtext + strlen(logtext),
1258 #if TRACE_ARGS_NUM >= 4
1260 sprintf(logtext + strlen(logtext),
1261 "0x%llx, 0x%llx, 0x%llx",
1266 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1268 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1271 #endif /* TRACE_ARGS_NUM >= 4 */
1273 #if TRACE_ARGS_NUM >= 6
1275 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1277 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1282 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1284 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1287 #endif /* TRACE_ARGS_NUM >= 6 */
1289 #if TRACE_ARGS_NUM == 8
1291 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1293 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1295 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1299 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1301 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1303 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1305 #endif /* TRACE_ARGS_NUM == 8 */
1308 #if TRACE_ARGS_NUM == 2
1309 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1311 #elif TRACE_ARGS_NUM == 4
1312 sprintf(logtext + strlen(logtext),
1313 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1314 a0, a1, a2, a3, md->paramcount - 4);
1316 #elif TRACE_ARGS_NUM == 6
1317 sprintf(logtext + strlen(logtext),
1318 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1319 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1321 #elif TRACE_ARGS_NUM == 8
1322 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1324 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1326 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1327 , a6, a7, md->paramcount - 8);
1331 #else /* SIZEOF_VOID_P == 4 */
1334 sprintf(logtext + strlen(logtext),
1340 sprintf(logtext + strlen(logtext),
1346 sprintf(logtext + strlen(logtext),
1347 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1351 sprintf(logtext + strlen(logtext),
1352 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1356 #if TRACE_ARGS_NUM >= 6
1358 sprintf(logtext + strlen(logtext),
1359 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1360 a0, a1, a2, a3, a4);
1364 sprintf(logtext + strlen(logtext),
1365 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1366 a0, a1, a2, a3, a4, a5);
1368 #endif /* TRACE_ARGS_NUM >= 6 */
1370 #if TRACE_ARGS_NUM == 8
1372 sprintf(logtext + strlen(logtext),
1373 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1374 a0, a1, a2, a3, a4, a5, a6);
1378 sprintf(logtext + strlen(logtext),
1379 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1380 a0, a1, a2, a3, a4, a5, a6, a7);
1382 #endif /* TRACE_ARGS_NUM == 8 */
1385 #if TRACE_ARGS_NUM == 4
1386 sprintf(logtext + strlen(logtext),
1387 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1388 a0, a1, a2, a3, md->paramcount - 4);
1390 #elif TRACE_ARGS_NUM == 6
1391 sprintf(logtext + strlen(logtext),
1392 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1393 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1395 #elif TRACE_ARGS_NUM == 8
1396 sprintf(logtext + strlen(logtext),
1397 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1398 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1401 #endif /* SIZEOF_VOID_P == 4 */
1404 strcat(logtext, ")");
1408 /* release memory */
1410 dump_release(dumpsize);
1417 /* builtin_displaymethodstop ***************************************************
1421 *******************************************************************************/
1423 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1434 /* calculate message length */
1437 methodindent + strlen("finished: ") +
1438 utf_strlen(m->class->name) +
1440 utf_strlen(m->name) +
1441 utf_strlen(m->descriptor) +
1442 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1444 /* add maximal argument length */
1446 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1448 /* allocate memory */
1450 dumpsize = dump_size();
1452 logtext = DMNEW(char, logtextlen);
1454 /* generate the message */
1456 for (i = 0; i < methodindent; i++)
1462 log_text("WARNING: unmatched methodindent--");
1464 strcpy(logtext + methodindent, "finished: ");
1465 utf_strcat_classname(logtext, m->class->name);
1466 strcat(logtext, ".");
1467 utf_strcat(logtext, m->name);
1468 utf_strcat(logtext, m->descriptor);
1470 switch (md->returntype.type) {
1472 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1476 #if SIZEOF_VOID_P == 4
1477 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1479 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1484 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1489 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1494 #if SIZEOF_VOID_P == 4
1495 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1497 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1504 /* release memory */
1506 dump_release(dumpsize);
1510 /****************************************************************************
1511 SYNCHRONIZATION FUNCTIONS
1512 *****************************************************************************/
1514 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1516 * Lock the mutex of an object.
1518 void internal_lock_mutex_for_object(java_objectheader *object)
1520 mutexHashEntry *entry;
1523 assert(object != 0);
1525 hashValue = MUTEX_HASH_VALUE(object);
1526 entry = &mutexHashTable[hashValue];
1528 if (entry->object != 0) {
1529 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1531 entry->mutex.holder = 0;
1532 entry->mutex.count = 0;
1533 entry->mutex.muxWaiters = 0;
1536 while (entry->next != 0 && entry->object != object)
1537 entry = entry->next;
1539 if (entry->object != object) {
1540 entry->next = firstFreeOverflowEntry;
1541 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1543 entry = entry->next;
1546 assert(entry->conditionCount == 0);
1551 entry->mutex.holder = 0;
1552 entry->mutex.count = 0;
1553 entry->mutex.muxWaiters = 0;
1556 if (entry->object == 0)
1557 entry->object = object;
1559 internal_lock_mutex(&entry->mutex);
1564 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1566 * Unlocks the mutex of an object.
1568 void internal_unlock_mutex_for_object (java_objectheader *object)
1571 mutexHashEntry *entry;
1573 hashValue = MUTEX_HASH_VALUE(object);
1574 entry = &mutexHashTable[hashValue];
1576 if (entry->object == object) {
1577 internal_unlock_mutex(&entry->mutex);
1580 while (entry->next != 0 && entry->next->object != object)
1581 entry = entry->next;
1583 assert(entry->next != 0);
1585 internal_unlock_mutex(&entry->next->mutex);
1587 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1588 mutexHashEntry *unlinked = entry->next;
1590 entry->next = unlinked->next;
1591 unlinked->next = firstFreeOverflowEntry;
1592 firstFreeOverflowEntry = unlinked;
1599 #if defined(USE_THREADS)
1600 void builtin_monitorenter(java_objectheader *o)
1602 #if !defined(NATIVE_THREADS)
1607 hashValue = MUTEX_HASH_VALUE(o);
1608 if (mutexHashTable[hashValue].object == o
1609 && mutexHashTable[hashValue].mutex.holder == currentThread)
1610 ++mutexHashTable[hashValue].mutex.count;
1612 internal_lock_mutex_for_object(o);
1616 monitorEnter((threadobject *) THREADOBJECT, o);
1622 #if defined(USE_THREADS)
1624 * Locks the class object - needed for static synchronized methods.
1625 * The use_class_as_object call is needed in order to circumvent a
1626 * possible deadlock with builtin_monitorenter called by another
1627 * thread calling use_class_as_object.
1629 void builtin_staticmonitorenter(classinfo *c)
1631 use_class_as_object(c);
1632 builtin_monitorenter(&c->header);
1637 #if defined(USE_THREADS)
1638 void builtin_monitorexit(java_objectheader *o)
1640 #if !defined(NATIVE_THREADS)
1645 hashValue = MUTEX_HASH_VALUE(o);
1646 if (mutexHashTable[hashValue].object == o) {
1647 if (mutexHashTable[hashValue].mutex.count == 1
1648 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1649 internal_unlock_mutex_for_object(o);
1651 --mutexHashTable[hashValue].mutex.count;
1654 internal_unlock_mutex_for_object(o);
1658 monitorExit((threadobject *) THREADOBJECT, o);
1664 /*****************************************************************************
1665 MISCELLANEOUS HELPER FUNCTIONS
1666 *****************************************************************************/
1670 /*********** Functions for integer divisions *****************************
1672 On some systems (eg. DEC ALPHA), integer division is not supported by the
1673 CPU. These helper functions implement the missing functionality.
1675 ******************************************************************************/
1677 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1678 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1681 /************** Functions for long arithmetics *******************************
1683 On systems where 64 bit Integers are not supported by the CPU, these
1684 functions are needed.
1686 ******************************************************************************/
1688 s8 builtin_ladd(s8 a, s8 b)
1701 s8 builtin_lsub(s8 a, s8 b)
1714 s8 builtin_lmul(s8 a, s8 b)
1727 s8 builtin_ldiv(s8 a, s8 b)
1740 s8 builtin_lrem(s8 a, s8 b)
1753 s8 builtin_lshl(s8 a, s4 b)
1766 s8 builtin_lshr(s8 a, s4 b)
1779 s8 builtin_lushr(s8 a, s4 b)
1784 c = ((u8) a) >> (b & 63);
1792 s8 builtin_land(s8 a, s8 b)
1805 s8 builtin_lor(s8 a, s8 b)
1818 s8 builtin_lxor(s8 a, s8 b)
1831 s8 builtin_lneg(s8 a)
1844 s4 builtin_lcmp(s8 a, s8 b)
1847 if (a < b) return -1;
1848 if (a > b) return 1;
1859 /*********** Functions for floating point operations *************************/
1861 /* used to convert FLT_xxx defines into float values */
1863 static inline float intBitsToFloat(s4 i)
1872 /* used to convert DBL_xxx defines into double values */
1874 static inline float longBitsToDouble(s8 l)
1883 float builtin_fadd(float a, float b)
1885 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1886 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1897 if (copysignf(1.0, a) == copysignf(1.0, b))
1900 return intBitsToFloat(FLT_NAN);
1906 float builtin_fsub(float a, float b)
1908 return builtin_fadd(a, builtin_fneg(b));
1912 float builtin_fmul(float a, float b)
1914 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1915 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1917 if (finitef(b)) return a * b;
1919 if (a == 0) return intBitsToFloat(FLT_NAN);
1920 else return copysignf(b, copysignf(1.0, b)*a);
1925 if (b == 0) return intBitsToFloat(FLT_NAN);
1926 else return copysignf(a, copysignf(1.0, a)*b);
1929 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1935 /* builtin_ddiv ****************************************************************
1937 Implementation as described in VM Spec.
1939 *******************************************************************************/
1941 float builtin_fdiv(float a, float b)
1945 /* If neither value1' nor value2' is NaN, the sign of the result */
1946 /* is positive if both values have the same sign, negative if the */
1947 /* values have different signs. */
1953 /* If either value1' or value2' is NaN, the result is NaN. */
1955 return intBitsToFloat(FLT_NAN);
1958 /* Division of a finite value by an infinity results in a */
1959 /* signed zero, with the sign-producing rule just given. */
1961 /* is sign equal? */
1963 if (copysignf(1.0, a) == copysignf(1.0, b))
1972 /* If either value1' or value2' is NaN, the result is NaN. */
1974 return intBitsToFloat(FLT_NAN);
1976 } else if (finitef(b)) {
1977 /* Division of an infinity by a finite value results in a signed */
1978 /* infinity, with the sign-producing rule just given. */
1980 /* is sign equal? */
1982 if (copysignf(1.0, a) == copysignf(1.0, b))
1983 return intBitsToFloat(FLT_POSINF);
1985 return intBitsToFloat(FLT_NEGINF);
1988 /* Division of an infinity by an infinity results in NaN. */
1990 return intBitsToFloat(FLT_NAN);
1996 float builtin_frem(float a, float b)
2002 float builtin_fneg(float a)
2004 if (isnanf(a)) return a;
2006 if (finitef(a)) return -a;
2007 else return copysignf(a, -copysignf(1.0, a));
2012 s4 builtin_fcmpl(float a, float b)
2014 if (isnanf(a)) return -1;
2015 if (isnanf(b)) return -1;
2016 if (!finitef(a) || !finitef(b)) {
2017 a = finitef(a) ? 0 : copysignf(1.0, a);
2018 b = finitef(b) ? 0 : copysignf(1.0, b);
2020 if (a > b) return 1;
2021 if (a == b) return 0;
2026 s4 builtin_fcmpg(float a, float b)
2028 if (isnanf(a)) return 1;
2029 if (isnanf(b)) return 1;
2030 if (!finitef(a) || !finitef(b)) {
2031 a = finitef(a) ? 0 : copysignf(1.0, a);
2032 b = finitef(b) ? 0 : copysignf(1.0, b);
2034 if (a > b) return 1;
2035 if (a == b) return 0;
2041 /************************* Functions for doubles ****************************/
2043 double builtin_dadd(double a, double b)
2045 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2046 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2048 if (finite(b)) return a + b;
2052 if (finite(b)) return a;
2054 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2055 else return longBitsToDouble(DBL_NAN);
2061 double builtin_dsub(double a, double b)
2063 return builtin_dadd(a, builtin_dneg(b));
2067 double builtin_dmul(double a, double b)
2069 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2070 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2072 if (finite(b)) return a * b;
2074 if (a == 0) return longBitsToDouble(DBL_NAN);
2075 else return copysign(b, copysign(1.0, b) * a);
2080 if (b == 0) return longBitsToDouble(DBL_NAN);
2081 else return copysign(a, copysign(1.0, a) * b);
2084 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2090 /* builtin_ddiv ****************************************************************
2092 Implementation as described in VM Spec.
2094 *******************************************************************************/
2096 double builtin_ddiv(double a, double b)
2100 /* If neither value1' nor value2' is NaN, the sign of the result */
2101 /* is positive if both values have the same sign, negative if the */
2102 /* values have different signs. */
2108 /* If either value1' or value2' is NaN, the result is NaN. */
2110 return longBitsToDouble(DBL_NAN);
2113 /* Division of a finite value by an infinity results in a */
2114 /* signed zero, with the sign-producing rule just given. */
2116 /* is sign equal? */
2118 if (copysign(1.0, a) == copysign(1.0, b))
2127 /* If either value1' or value2' is NaN, the result is NaN. */
2129 return longBitsToDouble(DBL_NAN);
2131 } else if (finite(b)) {
2132 /* Division of an infinity by a finite value results in a signed */
2133 /* infinity, with the sign-producing rule just given. */
2135 /* is sign equal? */
2137 if (copysign(1.0, a) == copysign(1.0, b))
2138 return longBitsToDouble(DBL_POSINF);
2140 return longBitsToDouble(DBL_NEGINF);
2143 /* Division of an infinity by an infinity results in NaN. */
2145 return longBitsToDouble(DBL_NAN);
2151 double builtin_drem(double a, double b)
2156 /* builtin_dneg ****************************************************************
2158 Implemented as described in VM Spec.
2160 *******************************************************************************/
2162 double builtin_dneg(double a)
2165 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2172 /* If the operand is a zero, the result is the zero of opposite */
2178 /* If the operand is an infinity, the result is the infinity of */
2179 /* opposite sign. */
2181 return copysign(a, -copysign(1.0, a));
2187 s4 builtin_dcmpl(double a, double b)
2189 if (isnan(a)) return -1;
2190 if (isnan(b)) return -1;
2191 if (!finite(a) || !finite(b)) {
2192 a = finite(a) ? 0 : copysign(1.0, a);
2193 b = finite(b) ? 0 : copysign(1.0, b);
2195 if (a > b) return 1;
2196 if (a == b) return 0;
2201 s4 builtin_dcmpg(double a, double b)
2203 if (isnan(a)) return 1;
2204 if (isnan(b)) return 1;
2205 if (!finite(a) || !finite(b)) {
2206 a = finite(a) ? 0 : copysign(1.0, a);
2207 b = finite(b) ? 0 : copysign(1.0, b);
2209 if (a > b) return 1;
2210 if (a == b) return 0;
2215 /*********************** Conversion operations ****************************/
2217 s8 builtin_i2l(s4 i)
2230 float builtin_i2f(s4 a)
2232 float f = (float) a;
2237 double builtin_i2d(s4 a)
2239 double d = (double) a;
2244 s4 builtin_l2i(s8 l)
2254 float builtin_l2f(s8 a)
2257 float f = (float) a;
2265 double builtin_l2d(s8 a)
2268 double d = (double) a;
2276 s4 builtin_f2i(float a)
2280 i = builtin_d2i((double) a);
2291 if (a < (-2147483648))
2292 return (-2147483648);
2295 f = copysignf((float) 1.0, a);
2298 return (-2147483648); */
2302 s8 builtin_f2l(float a)
2306 l = builtin_d2l((double) a);
2313 if (a > 9223372036854775807L)
2314 return 9223372036854775807L;
2315 if (a < (-9223372036854775808L))
2316 return (-9223372036854775808L);
2321 f = copysignf((float) 1.0, a);
2323 return 9223372036854775807L;
2324 return (-9223372036854775808L); */
2328 double builtin_f2d(float a)
2330 if (finitef(a)) return (double) a;
2333 return longBitsToDouble(DBL_NAN);
2335 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2340 s4 builtin_d2i(double a)
2345 if (a >= 2147483647)
2347 if (a <= (-2147483647-1))
2348 return (-2147483647-1);
2353 d = copysign(1.0, a);
2356 return (-2147483647-1);
2360 s8 builtin_d2l(double a)
2365 if (a >= 9223372036854775807LL)
2366 return 9223372036854775807LL;
2367 if (a <= (-9223372036854775807LL-1))
2368 return (-9223372036854775807LL-1);
2373 d = copysign(1.0, a);
2375 return 9223372036854775807LL;
2376 return (-9223372036854775807LL-1);
2380 float builtin_d2f(double a)
2386 return intBitsToFloat(FLT_NAN);
2388 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2393 /* builtin_clone_array *********************************************************
2395 Wrapper function for cloning arrays.
2397 *******************************************************************************/
2399 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2401 java_arrayheader *ah;
2402 java_lang_Cloneable *c;
2404 c = (java_lang_Object *) o;
2406 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2412 /* builtin_asm_get_exceptionptrptr *********************************************
2414 this is a wrapper for calls from asmpart
2416 *******************************************************************************/
2418 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2419 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2421 return builtin_get_exceptionptrptr();
2426 methodinfo *builtin_asm_get_threadrootmethod(void)
2428 return *threadrootmethod;
2432 void *builtin_asm_get_stackframeinfo(void)
2434 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2435 return &THREADINFO->_stackframeinfo;
2437 /* XXX FIXME FOR OLD THREAD IMPL (jowenn) */
2439 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2444 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,
2445 stacktraceelement *begin,
2446 stacktraceelement *end)
2448 /* stacktraceelement *el;*/
2451 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2452 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2454 *el=MNEW(stacktraceelement,s+1); /*GC*/
2456 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2459 /* XXX change this if line numbers bigger than u2 are allowed, the */
2460 /* currently supported class file format does no allow that */
2462 (*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 */
2468 * These are local overrides for various environment variables in Emacs.
2469 * Please do not remove this and leave it at the end of the file, where
2470 * Emacs will automagically detect them.
2471 * ---------------------------------------------------------------------
2474 * indent-tabs-mode: t