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 3010 2005-07-12 21:01:59Z 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_entry_debug_dump ***********************************************
269 Prints a builtintable_entry in human-readable form.
271 *******************************************************************************/
273 void builtintable_entry_debug_dump(FILE *file, builtintable_entry *bte)
279 fprintf(file,"(builtintable_entry *)NULL");
285 name = "<name=NULL>";
286 desc = (bte->md) ? "parsed " : bte->descriptor;
288 desc = "<desc=NULL>";
289 fprintf(file,"BUILTIN(%d,%p,%s %s",
290 bte->opcode,(void*)bte->fp,name,desc);
291 descriptor_debug_print_methoddesc(file,bte->md);
296 /* builtintable_get_internal ***************************************************
298 Finds an entry in the builtintable for internal functions and
299 returns the a pointer to the structure.
301 *******************************************************************************/
303 builtintable_entry *builtintable_get_internal(functionptr fp)
307 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
308 if (builtintable_internal[i].fp == fp)
309 return &builtintable_internal[i];
316 /* builtintable_get_automatic **************************************************
318 Finds an entry in the builtintable for functions which are replaced
319 automatically and returns the a pointer to the structure.
321 *******************************************************************************/
323 builtintable_entry *builtintable_get_automatic(s4 opcode)
325 builtintable_entry *first;
326 builtintable_entry *last;
327 builtintable_entry *middle;
331 /* calculate table size statically (`- 1' comment see builtintable.inc) */
333 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
335 first = builtintable_automatic;
336 last = builtintable_automatic + entries;
338 while (entries > 0) {
340 middle = first + half;
342 if (middle->opcode < opcode) {
349 return (first != last ? first : NULL);
353 /*****************************************************************************
355 *****************************************************************************/
359 /*************** internal function: builtin_isanysubclass *********************
361 Checks a subclass relation between two classes. Implemented interfaces
362 are interpreted as super classes.
363 Return value: 1 ... sub is subclass of super
366 *****************************************************************************/
367 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
370 castinfo classvalues;
375 if (super->flags & ACC_INTERFACE)
376 return (sub->vftbl->interfacetablelength > super->index) &&
377 (sub->vftbl->interfacetable[-super->index] != NULL);
379 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
381 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
382 (u4) classvalues.super_diffval;
388 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
392 castinfo classvalues;
397 asm_getclassvalues_atomic(super, sub, &classvalues);
399 if ((base = classvalues.super_baseval) <= 0)
400 /* super is an interface */
401 res = (sub->interfacetablelength > -base) &&
402 (sub->interfacetable[base] != NULL);
404 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
405 <= (u4) classvalues.super_diffval;
411 /****************** function: builtin_instanceof *****************************
413 Checks if an object is an instance of some given class (or subclass of
414 that class). If class is an interface, checks if the interface is
416 Return value: 1 ... obj is an instance of class or implements the interface
417 0 ... otherwise or if obj == NULL
419 *****************************************************************************/
421 /* XXX should use vftbl */
422 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
425 log_text ("builtin_instanceof called");
430 return builtin_isanysubclass(obj->vftbl->class, class);
435 /**************** function: builtin_checkcast *******************************
437 The same as builtin_instanceof except that 1 is returned when
440 ****************************************************************************/
442 /* XXX should use vftbl */
443 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
446 log_text("builtin_checkcast called");
451 if (builtin_isanysubclass(obj->vftbl->class, class))
455 printf("#### checkcast failed ");
456 utf_display(obj->vftbl->class->name);
458 utf_display(class->name);
466 /* builtin_descriptorscompatible ***********************************************
468 Checks if two array type descriptors are assignment compatible
470 Return value: 1 ... target = desc is possible
473 *******************************************************************************/
475 static s4 builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
480 if (desc->arraytype != target->arraytype)
483 if (desc->arraytype != ARRAYTYPE_OBJECT)
486 /* {both arrays are arrays of references} */
488 if (desc->dimension == target->dimension) {
489 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
490 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
491 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
493 if (desc->dimension < target->dimension) return 0;
495 /* {desc has higher dimension than target} */
496 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
500 /* builtin_arraycheckcast ******************************************************
502 Checks if an object is really a subtype of the requested array
503 type. The object has to be an array to begin with. For simple
504 arrays (int, short, double, etc.) the types have to match exactly.
505 For arrays of objects, the type of elements in the array has to be
506 a subtype (or the same type) of the requested element type. For
507 arrays of arrays (which in turn can again be arrays of arrays), the
508 types at the lowest level have to satisfy the corresponding sub
511 *******************************************************************************/
513 s4 builtin_arraycheckcast(java_objectheader *o, vftbl_t *target)
515 arraydescriptor *desc;
520 if ((desc = o->vftbl->arraydesc) == NULL)
523 return builtin_descriptorscompatible(desc, target->arraydesc);
527 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
532 return builtin_arraycheckcast(obj, target);
536 /************************** exception functions *******************************
538 ******************************************************************************/
540 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
542 java_lang_Throwable *t;
548 t = (java_lang_Throwable *) xptr;
550 /* calculate message length */
552 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
556 utf_strlen(xptr->vftbl->class->name) +
558 javastring_strlen((java_objectheader *) t->detailMessage);
561 logtextlen += strlen("(nil)");
563 /* allocate memory */
565 dumpsize = dump_size();
567 logtext = DMNEW(char, logtextlen);
569 strcpy(logtext, "Builtin exception thrown: ");
572 utf_sprint_classname(logtext + strlen(logtext),
573 xptr->vftbl->class->name);
575 if (t->detailMessage) {
578 buf = javastring_tochar((java_objectheader *) t->detailMessage);
579 strcat(logtext, ": ");
580 strcat(logtext, buf);
581 MFREE(buf, char, strlen(buf));
585 strcat(logtext, "(nil)");
592 dump_release(dumpsize);
595 *exceptionptr = xptr;
602 /* builtin_canstore ************************************************************
604 Checks, if an object can be stored in an array.
606 Return value: 1 ... possible
609 *******************************************************************************/
611 s4 builtin_canstore(java_objectarray *a, java_objectheader *o)
613 arraydescriptor *desc;
614 arraydescriptor *valuedesc;
615 vftbl_t *componentvftbl;
618 castinfo classvalues;
623 /* The following is guaranteed (by verifier checks):
625 * *) a->...vftbl->arraydesc != NULL
626 * *) a->...vftbl->arraydesc->componentvftbl != NULL
627 * *) o->vftbl is not an interface vftbl
630 desc = a->header.objheader.vftbl->arraydesc;
631 componentvftbl = desc->componentvftbl;
632 valuevftbl = o->vftbl;
634 if ((desc->dimension - 1) == 0) {
637 /* {a is a one-dimensional array} */
638 /* {a is an array of references} */
640 if (valuevftbl == componentvftbl)
643 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
645 if ((base = classvalues.super_baseval) <= 0)
646 /* an array of interface references */
647 return (valuevftbl->interfacetablelength > -base &&
648 valuevftbl->interfacetable[base] != NULL);
650 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
651 <= (unsigned) classvalues.super_diffval;
656 /* {a has dimension > 1} */
657 /* {componentvftbl->arraydesc != NULL} */
659 /* check if o is an array */
660 if ((valuedesc = valuevftbl->arraydesc) == NULL)
662 /* {o is an array} */
664 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
668 /* This is an optimized version where a is guaranteed to be one-dimensional */
669 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
671 arraydescriptor *desc;
672 vftbl_t *elementvftbl;
676 castinfo classvalues;
680 /* The following is guaranteed (by verifier checks):
682 * *) a->...vftbl->arraydesc != NULL
683 * *) a->...vftbl->arraydesc->elementvftbl != NULL
684 * *) a->...vftbl->arraydesc->dimension == 1
685 * *) o->vftbl is not an interface vftbl
688 desc = a->header.objheader.vftbl->arraydesc;
689 elementvftbl = desc->elementvftbl;
690 valuevftbl = o->vftbl;
692 /* {a is a one-dimensional array} */
694 if (valuevftbl == elementvftbl)
697 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
699 if ((base = classvalues.super_baseval) <= 0)
700 /* an array of interface references */
701 return (valuevftbl->interfacetablelength > -base &&
702 valuevftbl->interfacetable[base] != NULL);
704 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
705 <= (unsigned) classvalues.super_diffval;
711 /* This is an optimized version where a is guaranteed to be a
712 * one-dimensional array of a class type */
713 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
715 vftbl_t *elementvftbl;
718 castinfo classvalues;
722 /* The following is guaranteed (by verifier checks):
724 * *) a->...vftbl->arraydesc != NULL
725 * *) a->...vftbl->arraydesc->elementvftbl != NULL
726 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
727 * *) a->...vftbl->arraydesc->dimension == 1
728 * *) o->vftbl is not an interface vftbl
731 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
732 valuevftbl = o->vftbl;
734 /* {a is a one-dimensional array} */
736 if (valuevftbl == elementvftbl)
739 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
741 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
742 <= (unsigned) classvalues.super_diffval;
748 /* builtin_new *****************************************************************
750 Creates a new instance of class c on the heap.
752 Return value: pointer to the object or NULL if no memory is
755 *******************************************************************************/
757 java_objectheader *builtin_new(classinfo *c)
759 java_objectheader *o;
761 /* is the class loaded */
765 /* is the class linked */
770 if (!c->initialized) {
772 log_message_class("Initialize class (from builtin_new): ", c);
774 if (!initialize_class(c))
778 o = heap_allocate(c->instancesize, true, c->finalizer);
783 MSET(o, 0, u1, c->instancesize);
787 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
795 /* builtin_newarray ************************************************************
797 Creates an array with the given vftbl on the heap.
799 Return value: pointer to the array or NULL if no memory is available
801 CAUTION: The given vftbl must be the vftbl of the *array* class,
802 not of the element class.
804 *******************************************************************************/
806 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
809 arraydescriptor *desc;
814 desc = arrayvftbl->arraydesc;
815 dataoffset = desc->dataoffset;
816 componentsize = desc->componentsize;
819 *exceptionptr = new_negativearraysizeexception();
823 actualsize = dataoffset + size * componentsize;
825 if (((u4) actualsize) < ((u4) size)) { /* overflow */
826 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
830 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
835 MSET(a, 0, u1, actualsize);
837 a->objheader.vftbl = arrayvftbl;
839 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
840 initObjectLock(&a->objheader);
849 /* builtin_anewarray ***********************************************************
851 Creates an array of references to the given class type on the heap.
853 Return value: pointer to the array or NULL if no memory is
856 *******************************************************************************/
858 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
862 /* is class loaded */
863 assert(component->loaded);
865 /* is class linked */
866 if (!component->linked)
867 if (!link_class(component))
870 c = class_array_of(component, true);
875 return (java_objectarray *) builtin_newarray(size, c->vftbl);
879 /* builtin_newarray_int ********************************************************
881 Creates an array of 32 bit Integers on the heap.
883 Return value: pointer to the array or NULL if no memory is
886 *******************************************************************************/
888 java_intarray *builtin_newarray_int(s4 size)
890 return (java_intarray *)
891 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
895 /* builtin_newarray_long *******************************************************
897 Creates an array of 64 bit Integers on the heap.
899 Return value: pointer to the array or NULL if no memory is
902 *******************************************************************************/
904 java_longarray *builtin_newarray_long(s4 size)
906 return (java_longarray *)
907 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
911 /* builtin_newarray_float ******************************************************
913 Creates an array of 32 bit IEEE floats on the heap.
915 Return value: pointer to the array or NULL if no memory is
918 *******************************************************************************/
920 java_floatarray *builtin_newarray_float(s4 size)
922 return (java_floatarray *)
923 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
927 /* builtin_newarray_double *****************************************************
929 Creates an array of 64 bit IEEE floats on the heap.
931 Return value: pointer to the array or NULL if no memory is
934 *******************************************************************************/
936 java_doublearray *builtin_newarray_double(s4 size)
938 return (java_doublearray *)
939 builtin_newarray(size,
940 primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
944 /* builtin_newarray_byte *******************************************************
946 Creates an array of 8 bit Integers on the heap.
948 Return value: pointer to the array or NULL if no memory is
951 *******************************************************************************/
953 java_bytearray *builtin_newarray_byte(s4 size)
955 return (java_bytearray *)
956 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
960 /* builtin_newarray_char *******************************************************
962 Creates an array of characters on the heap.
964 Return value: pointer to the array or NULL if no memory is
967 *******************************************************************************/
969 java_chararray *builtin_newarray_char(s4 size)
971 return (java_chararray *)
972 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
976 /* builtin_newarray_short ******************************************************
978 Creates an array of 16 bit Integers on the heap.
980 Return value: pointer to the array or NULL if no memory is
983 *******************************************************************************/
985 java_shortarray *builtin_newarray_short(s4 size)
987 return (java_shortarray *)
988 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
992 /* builtin_newarray_boolean ****************************************************
994 Creates an array of bytes on the heap. The array is designated as
995 an array of booleans (important for casts)
997 Return value: pointer to the array or NULL if no memory is
1000 *******************************************************************************/
1002 java_booleanarray *builtin_newarray_boolean(s4 size)
1004 return (java_booleanarray *)
1005 builtin_newarray(size,
1006 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
1010 /* builtin_multianewarray ******************************************************
1012 Creates a multi-dimensional array on the heap. The dimensions are
1013 passed in an array of longs.
1016 n............number of dimensions to create
1017 arrayvftbl...vftbl of the array class
1018 dims.........array containing the size of each dimension to create
1020 Return value: pointer to the array or NULL if no memory is
1023 ******************************************************************************/
1025 java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims)
1028 java_arrayheader *a;
1029 vftbl_t *componentvftbl;
1031 /* create this dimension */
1033 size = (s4) dims[0];
1034 a = builtin_newarray(size, arrayvftbl);
1039 /* if this is the last dimension return */
1044 /* get the vftbl of the components to create */
1046 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
1048 /* The verifier guarantees that the dimension count is in the range. */
1050 /* create the component arrays */
1052 for (i = 0; i < size; i++) {
1053 java_arrayheader *ea =
1054 builtin_multianewarray(n, componentvftbl, dims + 1);
1059 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1066 /*****************************************************************************
1069 Various functions for printing a message at method entry or exit (for
1072 *****************************************************************************/
1074 u4 methodindent = 0;
1076 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1090 log_text("WARNING: unmatched methodindent--");
1093 if (opt_verbose || runverbose || verboseexception) {
1094 /* calculate message length */
1098 strlen("Exception ") +
1099 utf_strlen(xptr->vftbl->class->name);
1102 logtextlen = strlen("Some Throwable");
1104 logtextlen += strlen(" thrown in ");
1108 utf_strlen(m->class->name) +
1110 utf_strlen(m->name) +
1111 strlen("(NOSYNC,NATIVE");
1113 #if SIZEOF_VOID_P == 8
1115 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1117 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1120 if (m->class->sourcefile == NULL)
1121 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1123 logtextlen += utf_strlen(m->class->sourcefile);
1125 logtextlen += strlen(":65536)");
1128 logtextlen += strlen("call_java_method");
1130 logtextlen += strlen("0");
1132 /* allocate memory */
1134 dumpsize = dump_size();
1136 logtext = DMNEW(char, logtextlen);
1139 strcpy(logtext, "Exception ");
1140 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1143 strcpy(logtext, "Some Throwable");
1146 strcat(logtext, " thrown in ");
1149 utf_strcat_classname(logtext, m->class->name);
1150 strcat(logtext, ".");
1151 utf_strcat(logtext, m->name);
1153 if (m->flags & ACC_SYNCHRONIZED)
1154 strcat(logtext, "(SYNC");
1156 strcat(logtext, "(NOSYNC");
1158 if (m->flags & ACC_NATIVE) {
1159 strcat(logtext, ",NATIVE");
1161 #if SIZEOF_VOID_P == 8
1162 sprintf(logtext + strlen(logtext),
1163 ")(0x%016lx) at position 0x%016lx",
1164 (ptrint) m->entrypoint, (ptrint) pos);
1166 sprintf(logtext + strlen(logtext),
1167 ")(0x%08x) at position 0x%08x",
1168 (ptrint) m->entrypoint, (ptrint) pos);
1172 #if SIZEOF_VOID_P == 8
1173 sprintf(logtext + strlen(logtext),
1174 ")(0x%016lx) at position 0x%016lx (",
1175 (ptrint) m->entrypoint, (ptrint) pos);
1177 sprintf(logtext + strlen(logtext),
1178 ")(0x%08x) at position 0x%08x (",
1179 (ptrint) m->entrypoint, (ptrint) pos);
1182 if (m->class->sourcefile == NULL)
1183 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1185 utf_strcat(logtext, m->class->sourcefile);
1187 sprintf(logtext + strlen(logtext), ":%d)", line);
1191 strcat(logtext, "call_java_method");
1195 /* release memory */
1197 dump_release(dumpsize);
1204 /* builtin_trace_args **********************************************************
1208 *******************************************************************************/
1210 #ifdef TRACE_ARGS_NUM
1211 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1212 #if TRACE_ARGS_NUM >= 6
1215 #if TRACE_ARGS_NUM == 8
1228 /* calculate message length */
1231 methodindent + strlen("called: ") +
1232 utf_strlen(m->class->name) +
1234 utf_strlen(m->name) +
1235 utf_strlen(m->descriptor) +
1236 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1238 /* add maximal argument length */
1240 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1242 /* allocate memory */
1244 dumpsize = dump_size();
1246 logtext = DMNEW(char, logtextlen);
1248 for (i = 0; i < methodindent; i++)
1251 strcpy(logtext + methodindent, "called: ");
1253 utf_strcat_classname(logtext, m->class->name);
1254 strcat(logtext, ".");
1255 utf_strcat(logtext, m->name);
1256 utf_strcat(logtext, m->descriptor);
1258 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1259 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1260 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1261 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1262 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1263 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1264 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1265 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1266 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1267 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1268 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1270 strcat(logtext, "(");
1272 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1273 /* Only Arguments in integer Registers are passed correctly here */
1274 /* long longs spilled on Stack have an wrong offset of +4 */
1275 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1276 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1277 switch (md->paramcount) {
1281 #if SIZEOF_VOID_P == 4
1283 sprintf(logtext + strlen(logtext),
1289 sprintf(logtext + strlen(logtext),
1295 sprintf(logtext + strlen(logtext),
1296 "0x%llx, 0x%llx, 0x%llx",
1301 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1303 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1307 #if TRACE_ARGS_NUM >= 6
1309 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1311 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1316 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1318 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1321 #endif /* TRACE_ARGS_NUM >= 6 */
1323 #if TRACE_ARGS_NUM == 8
1325 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1327 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1329 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
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", a6, a7);
1339 #endif /* TRACE_ARGS_NUM == 8 */
1342 #if TRACE_ARGS_NUM == 4
1343 sprintf(logtext + strlen(logtext),
1344 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1345 a0, a1, a2, a3, md->paramcount - 4);
1347 #elif TRACE_ARGS_NUM == 6
1348 sprintf(logtext + strlen(logtext),
1349 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1350 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1352 #elif TRACE_ARGS_NUM == 8
1353 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1355 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1357 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1358 , a6, a7, md->paramcount - 8);
1362 #else /* SIZEOF_VOID_P == 4 */
1365 sprintf(logtext + strlen(logtext),
1371 sprintf(logtext + strlen(logtext),
1377 sprintf(logtext + strlen(logtext),
1378 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1382 sprintf(logtext + strlen(logtext),
1383 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1387 #if TRACE_ARGS_NUM >= 6
1389 sprintf(logtext + strlen(logtext),
1390 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1391 a0, a1, a2, a3, a4);
1395 sprintf(logtext + strlen(logtext),
1396 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1397 a0, a1, a2, a3, a4, a5);
1399 #endif /* TRACE_ARGS_NUM >= 6 */
1401 #if TRACE_ARGS_NUM == 8
1403 sprintf(logtext + strlen(logtext),
1404 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1405 a0, a1, a2, a3, a4, a5, a6);
1409 sprintf(logtext + strlen(logtext),
1410 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1411 a0, a1, a2, a3, a4, a5, a6, a7);
1413 #endif /* TRACE_ARGS_NUM == 8 */
1416 #if TRACE_ARGS_NUM == 4
1417 sprintf(logtext + strlen(logtext),
1418 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1419 a0, a1, a2, a3, md->paramcount - 4);
1421 #elif TRACE_ARGS_NUM == 6
1422 sprintf(logtext + strlen(logtext),
1423 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1424 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1426 #elif TRACE_ARGS_NUM == 8
1427 sprintf(logtext + strlen(logtext),
1428 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1429 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1432 #endif /* SIZEOF_VOID_P == 4 */
1435 strcat(logtext, ")");
1439 /* release memory */
1441 dump_release(dumpsize);
1448 /* builtin_displaymethodstop ***************************************************
1452 *******************************************************************************/
1454 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1465 /* calculate message length */
1468 methodindent + strlen("finished: ") +
1469 utf_strlen(m->class->name) +
1471 utf_strlen(m->name) +
1472 utf_strlen(m->descriptor) +
1473 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1475 /* add maximal argument length */
1477 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1479 /* allocate memory */
1481 dumpsize = dump_size();
1483 logtext = DMNEW(char, logtextlen);
1485 /* generate the message */
1487 for (i = 0; i < methodindent; i++)
1493 log_text("WARNING: unmatched methodindent--");
1495 strcpy(logtext + methodindent, "finished: ");
1496 utf_strcat_classname(logtext, m->class->name);
1497 strcat(logtext, ".");
1498 utf_strcat(logtext, m->name);
1499 utf_strcat(logtext, m->descriptor);
1501 switch (md->returntype.type) {
1503 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1507 #if SIZEOF_VOID_P == 4
1508 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1510 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1515 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1520 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1525 #if SIZEOF_VOID_P == 4
1526 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1528 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1535 /* release memory */
1537 dump_release(dumpsize);
1541 /****************************************************************************
1542 SYNCHRONIZATION FUNCTIONS
1543 *****************************************************************************/
1545 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1547 * Lock the mutex of an object.
1549 void internal_lock_mutex_for_object(java_objectheader *object)
1551 mutexHashEntry *entry;
1554 assert(object != 0);
1556 hashValue = MUTEX_HASH_VALUE(object);
1557 entry = &mutexHashTable[hashValue];
1559 if (entry->object != 0) {
1560 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1562 entry->mutex.holder = 0;
1563 entry->mutex.count = 0;
1564 entry->mutex.muxWaiters = 0;
1567 while (entry->next != 0 && entry->object != object)
1568 entry = entry->next;
1570 if (entry->object != object) {
1571 entry->next = firstFreeOverflowEntry;
1572 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1574 entry = entry->next;
1577 assert(entry->conditionCount == 0);
1582 entry->mutex.holder = 0;
1583 entry->mutex.count = 0;
1584 entry->mutex.muxWaiters = 0;
1587 if (entry->object == 0)
1588 entry->object = object;
1590 internal_lock_mutex(&entry->mutex);
1595 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1597 * Unlocks the mutex of an object.
1599 void internal_unlock_mutex_for_object (java_objectheader *object)
1602 mutexHashEntry *entry;
1604 hashValue = MUTEX_HASH_VALUE(object);
1605 entry = &mutexHashTable[hashValue];
1607 if (entry->object == object) {
1608 internal_unlock_mutex(&entry->mutex);
1611 while (entry->next != 0 && entry->next->object != object)
1612 entry = entry->next;
1614 assert(entry->next != 0);
1616 internal_unlock_mutex(&entry->next->mutex);
1618 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1619 mutexHashEntry *unlinked = entry->next;
1621 entry->next = unlinked->next;
1622 unlinked->next = firstFreeOverflowEntry;
1623 firstFreeOverflowEntry = unlinked;
1630 #if defined(USE_THREADS)
1631 void builtin_monitorenter(java_objectheader *o)
1633 #if !defined(NATIVE_THREADS)
1638 hashValue = MUTEX_HASH_VALUE(o);
1639 if (mutexHashTable[hashValue].object == o
1640 && mutexHashTable[hashValue].mutex.holder == currentThread)
1641 ++mutexHashTable[hashValue].mutex.count;
1643 internal_lock_mutex_for_object(o);
1647 monitorEnter((threadobject *) THREADOBJECT, o);
1653 #if defined(USE_THREADS)
1655 * Locks the class object - needed for static synchronized methods.
1656 * The use_class_as_object call is needed in order to circumvent a
1657 * possible deadlock with builtin_monitorenter called by another
1658 * thread calling use_class_as_object.
1660 void builtin_staticmonitorenter(classinfo *c)
1662 use_class_as_object(c);
1663 builtin_monitorenter(&c->header);
1668 #if defined(USE_THREADS)
1669 void builtin_monitorexit(java_objectheader *o)
1671 #if !defined(NATIVE_THREADS)
1676 hashValue = MUTEX_HASH_VALUE(o);
1677 if (mutexHashTable[hashValue].object == o) {
1678 if (mutexHashTable[hashValue].mutex.count == 1
1679 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1680 internal_unlock_mutex_for_object(o);
1682 --mutexHashTable[hashValue].mutex.count;
1685 internal_unlock_mutex_for_object(o);
1689 monitorExit((threadobject *) THREADOBJECT, o);
1695 /*****************************************************************************
1696 MISCELLANEOUS HELPER FUNCTIONS
1697 *****************************************************************************/
1701 /*********** Functions for integer divisions *****************************
1703 On some systems (eg. DEC ALPHA), integer division is not supported by the
1704 CPU. These helper functions implement the missing functionality.
1706 ******************************************************************************/
1708 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1709 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1712 /************** Functions for long arithmetics *******************************
1714 On systems where 64 bit Integers are not supported by the CPU, these
1715 functions are needed.
1717 ******************************************************************************/
1720 s8 builtin_ladd(s8 a, s8 b)
1725 return builtin_i2l(0);
1729 s8 builtin_lsub(s8 a, s8 b)
1734 return builtin_i2l(0);
1738 s8 builtin_lmul(s8 a, s8 b)
1743 return builtin_i2l(0);
1747 s8 builtin_ldiv(s8 a, s8 b)
1752 return builtin_i2l(0);
1756 s8 builtin_lrem(s8 a, s8 b)
1761 return builtin_i2l(0);
1765 s8 builtin_lshl(s8 a, s4 b)
1768 return a << (b & 63);
1770 return builtin_i2l(0);
1774 s8 builtin_lshr(s8 a, s4 b)
1777 return a >> (b & 63);
1779 return builtin_i2l(0);
1783 s8 builtin_lushr(s8 a, s4 b)
1786 return ((u8) a) >> (b & 63);
1788 return builtin_i2l(0);
1792 s8 builtin_land(s8 a, s8 b)
1797 return builtin_i2l(0);
1801 s8 builtin_lor(s8 a, s8 b)
1806 return builtin_i2l(0);
1810 s8 builtin_lxor(s8 a, s8 b)
1815 return builtin_i2l(0);
1819 s8 builtin_lneg(s8 a)
1824 return builtin_i2l(0);
1828 s4 builtin_lcmp(s8 a, s8 b)
1831 if (a < b) return -1;
1832 if (a > b) return 1;
1843 /*********** Functions for floating point operations *************************/
1845 float builtin_fadd(float a, float b)
1847 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1848 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1859 if (copysignf(1.0, a) == copysignf(1.0, b))
1862 return intBitsToFloat(FLT_NAN);
1868 float builtin_fsub(float a, float b)
1870 return builtin_fadd(a, builtin_fneg(b));
1874 float builtin_fmul(float a, float b)
1876 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1877 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1879 if (finitef(b)) return a * b;
1881 if (a == 0) return intBitsToFloat(FLT_NAN);
1882 else return copysignf(b, copysignf(1.0, b)*a);
1887 if (b == 0) return intBitsToFloat(FLT_NAN);
1888 else return copysignf(a, copysignf(1.0, a)*b);
1891 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1897 /* builtin_ddiv ****************************************************************
1899 Implementation as described in VM Spec.
1901 *******************************************************************************/
1903 float builtin_fdiv(float a, float b)
1907 /* If neither value1' nor value2' is NaN, the sign of the result */
1908 /* is positive if both values have the same sign, negative if the */
1909 /* values have different signs. */
1915 /* If either value1' or value2' is NaN, the result is NaN. */
1917 return intBitsToFloat(FLT_NAN);
1920 /* Division of a finite value by an infinity results in a */
1921 /* signed zero, with the sign-producing rule just given. */
1923 /* is sign equal? */
1925 if (copysignf(1.0, a) == copysignf(1.0, b))
1934 /* If either value1' or value2' is NaN, the result is NaN. */
1936 return intBitsToFloat(FLT_NAN);
1938 } else if (finitef(b)) {
1939 /* Division of an infinity by a finite value results in a signed */
1940 /* infinity, with the sign-producing rule just given. */
1942 /* is sign equal? */
1944 if (copysignf(1.0, a) == copysignf(1.0, b))
1945 return intBitsToFloat(FLT_POSINF);
1947 return intBitsToFloat(FLT_NEGINF);
1950 /* Division of an infinity by an infinity results in NaN. */
1952 return intBitsToFloat(FLT_NAN);
1958 float builtin_frem(float a, float b)
1964 float builtin_fneg(float a)
1966 if (isnanf(a)) return a;
1968 if (finitef(a)) return -a;
1969 else return copysignf(a, -copysignf(1.0, a));
1974 s4 builtin_fcmpl(float a, float b)
1976 if (isnanf(a)) return -1;
1977 if (isnanf(b)) return -1;
1978 if (!finitef(a) || !finitef(b)) {
1979 a = finitef(a) ? 0 : copysignf(1.0, a);
1980 b = finitef(b) ? 0 : copysignf(1.0, b);
1982 if (a > b) return 1;
1983 if (a == b) return 0;
1988 s4 builtin_fcmpg(float a, float b)
1990 if (isnanf(a)) return 1;
1991 if (isnanf(b)) return 1;
1992 if (!finitef(a) || !finitef(b)) {
1993 a = finitef(a) ? 0 : copysignf(1.0, a);
1994 b = finitef(b) ? 0 : copysignf(1.0, b);
1996 if (a > b) return 1;
1997 if (a == b) return 0;
2003 /************************* Functions for doubles ****************************/
2005 double builtin_dadd(double a, double b)
2007 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2008 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2010 if (finite(b)) return a + b;
2014 if (finite(b)) return a;
2016 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2017 else return longBitsToDouble(DBL_NAN);
2023 double builtin_dsub(double a, double b)
2025 return builtin_dadd(a, builtin_dneg(b));
2029 double builtin_dmul(double a, double b)
2031 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2032 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2034 if (finite(b)) return a * b;
2036 if (a == 0) return longBitsToDouble(DBL_NAN);
2037 else return copysign(b, copysign(1.0, b) * a);
2042 if (b == 0) return longBitsToDouble(DBL_NAN);
2043 else return copysign(a, copysign(1.0, a) * b);
2046 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2052 /* builtin_ddiv ****************************************************************
2054 Implementation as described in VM Spec.
2056 *******************************************************************************/
2058 double builtin_ddiv(double a, double b)
2062 /* If neither value1' nor value2' is NaN, the sign of the result */
2063 /* is positive if both values have the same sign, negative if the */
2064 /* values have different signs. */
2070 /* If either value1' or value2' is NaN, the result is NaN. */
2072 return longBitsToDouble(DBL_NAN);
2075 /* Division of a finite value by an infinity results in a */
2076 /* signed zero, with the sign-producing rule just given. */
2078 /* is sign equal? */
2080 if (copysign(1.0, a) == copysign(1.0, b))
2089 /* If either value1' or value2' is NaN, the result is NaN. */
2091 return longBitsToDouble(DBL_NAN);
2093 } else if (finite(b)) {
2094 /* Division of an infinity by a finite value results in a signed */
2095 /* infinity, with the sign-producing rule just given. */
2097 /* is sign equal? */
2099 if (copysign(1.0, a) == copysign(1.0, b))
2100 return longBitsToDouble(DBL_POSINF);
2102 return longBitsToDouble(DBL_NEGINF);
2105 /* Division of an infinity by an infinity results in NaN. */
2107 return longBitsToDouble(DBL_NAN);
2113 double builtin_drem(double a, double b)
2118 /* builtin_dneg ****************************************************************
2120 Implemented as described in VM Spec.
2122 *******************************************************************************/
2124 double builtin_dneg(double a)
2127 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2134 /* If the operand is a zero, the result is the zero of opposite */
2140 /* If the operand is an infinity, the result is the infinity of */
2141 /* opposite sign. */
2143 return copysign(a, -copysign(1.0, a));
2149 s4 builtin_dcmpl(double a, double b)
2151 if (isnan(a)) return -1;
2152 if (isnan(b)) return -1;
2153 if (!finite(a) || !finite(b)) {
2154 a = finite(a) ? 0 : copysign(1.0, a);
2155 b = finite(b) ? 0 : copysign(1.0, b);
2157 if (a > b) return 1;
2158 if (a == b) return 0;
2163 s4 builtin_dcmpg(double a, double b)
2165 if (isnan(a)) return 1;
2166 if (isnan(b)) return 1;
2167 if (!finite(a) || !finite(b)) {
2168 a = finite(a) ? 0 : copysign(1.0, a);
2169 b = finite(b) ? 0 : copysign(1.0, b);
2171 if (a > b) return 1;
2172 if (a == b) return 0;
2177 /*********************** Conversion operations ****************************/
2179 s8 builtin_i2l(s4 i)
2192 float builtin_i2f(s4 a)
2194 float f = (float) a;
2199 double builtin_i2d(s4 a)
2201 double d = (double) a;
2206 s4 builtin_l2i(s8 l)
2216 float builtin_l2f(s8 a)
2219 float f = (float) a;
2227 double builtin_l2d(s8 a)
2230 double d = (double) a;
2238 s4 builtin_f2i(float a)
2241 return builtin_d2i((double) a);
2250 if (a < (-2147483648))
2251 return (-2147483648);
2254 f = copysignf((float) 1.0, a);
2257 return (-2147483648); */
2261 s8 builtin_f2l(float a)
2264 return builtin_d2l((double) a);
2269 if (a > 9223372036854775807L)
2270 return 9223372036854775807L;
2271 if (a < (-9223372036854775808L))
2272 return (-9223372036854775808L);
2277 f = copysignf((float) 1.0, a);
2279 return 9223372036854775807L;
2280 return (-9223372036854775808L); */
2284 double builtin_f2d(float a)
2286 if (finitef(a)) return (double) a;
2289 return longBitsToDouble(DBL_NAN);
2291 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2296 s4 builtin_d2i(double a)
2301 if (a >= 2147483647)
2303 if (a <= (-2147483647-1))
2304 return (-2147483647-1);
2309 d = copysign(1.0, a);
2312 return (-2147483647-1);
2316 s8 builtin_d2l(double a)
2321 if (a >= 9223372036854775807LL)
2322 return 9223372036854775807LL;
2323 if (a <= (-9223372036854775807LL-1))
2324 return (-9223372036854775807LL-1);
2329 d = copysign(1.0, a);
2331 return 9223372036854775807LL;
2332 return (-9223372036854775807LL-1);
2336 float builtin_d2f(double a)
2342 return intBitsToFloat(FLT_NAN);
2344 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2349 /* used to convert FLT_xxx defines into float values */
2351 inline float intBitsToFloat(s4 i)
2360 /* used to convert DBL_xxx defines into double values */
2362 inline float longBitsToDouble(s8 l)
2371 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2373 return (java_arrayheader *)
2374 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2378 s4 builtin_dummy(void)
2380 log_text("Internal error: builtin_dummy called (native function is missing)");
2383 /* keep the compiler happy */
2389 /* builtin_asm_get_exceptionptrptr *********************************************
2391 this is a wrapper for calls from asmpart
2393 *******************************************************************************/
2395 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2396 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2398 return builtin_get_exceptionptrptr();
2403 methodinfo *builtin_asm_get_threadrootmethod(void)
2405 return *threadrootmethod;
2409 void *builtin_asm_get_stackframeinfo(void)
2411 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2412 return &THREADINFO->_stackframeinfo;
2414 /* XXX FIXME FOR OLD THREAD IMPL (jowenn) */
2416 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2421 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,
2422 stacktraceelement *begin,
2423 stacktraceelement *end)
2425 /* stacktraceelement *el;*/
2428 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2429 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2431 *el=MNEW(stacktraceelement,s+1); /*GC*/
2433 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2436 /* XXX change this if line numbers bigger than u2 are allowed, the */
2437 /* currently supported class file format does no allow that */
2439 (*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 */
2445 * These are local overrides for various environment variables in Emacs.
2446 * Please do not remove this and leave it at the end of the file, where
2447 * Emacs will automagically detect them.
2448 * ---------------------------------------------------------------------
2451 * indent-tabs-mode: t