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 2909 2005-07-05 08:46:37Z twisti $
55 #include "mm/memory.h"
56 #include "native/native.h"
57 #include "native/include/java_lang_Cloneable.h"
58 #include "native/include/java_lang_Object.h" /* required by VMObject */
59 #include "native/include/java_lang_VMObject.h"
61 #if defined(USE_THREADS)
62 # if defined(NATIVE_THREADS)
63 # include "threads/native/threads.h"
65 # include "threads/green/threads.h"
66 # include "threads/green/locks.h"
70 #include "toolbox/logging.h"
71 #include "toolbox/util.h"
72 #include "vm/builtin.h"
73 #include "vm/exceptions.h"
74 #include "vm/global.h"
75 #include "vm/initialize.h"
76 #include "vm/loader.h"
77 #include "vm/options.h"
78 #include "vm/stringlocal.h"
79 #include "vm/tables.h"
80 #include "vm/jit/asmpart.h"
81 #include "vm/jit/patcher.h"
84 #undef DEBUG /*define DEBUG 1*/
86 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
87 THREADSPECIFIC void *_thread_nativestackframeinfo = NULL;
90 /* include builtin tables *****************************************************/
92 #include "vm/builtintable.inc"
95 /* builtintable_init ***********************************************************
97 Parse the descriptors of builtin functions and create the parsed
100 *******************************************************************************/
102 static bool builtintable_init(void)
104 descriptor_pool *descpool;
108 s4 entries_automatic;
111 /* mark start of dump memory area */
113 dumpsize = dump_size();
115 /* create a new descriptor pool */
117 descpool = descriptor_pool_new(class_java_lang_Object);
119 /* add some entries we need */
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
124 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
127 /* calculate table entries statically */
130 sizeof(builtintable_internal) / sizeof(builtintable_entry);
133 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
134 - 1; /* last filler entry (comment see builtintable.inc) */
136 /* first add all descriptors to the pool */
138 for (i = 0; i < entries_internal; i++) {
139 /* create a utf8 string from descriptor */
141 descriptor = utf_new_char(builtintable_internal[i].descriptor);
143 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
144 /* release dump area */
146 dump_release(dumpsize);
152 for (i = 0; i < entries_automatic; i++) {
153 /* create a utf8 string from descriptor */
155 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
157 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
158 /* release dump area */
160 dump_release(dumpsize);
166 /* create the class reference table */
168 (void) descriptor_pool_create_classrefs(descpool, NULL);
170 /* allocate space for the parsed descriptors */
172 descriptor_pool_alloc_parsed_descriptors(descpool);
174 /* now parse all descriptors */
176 for (i = 0; i < entries_internal; i++) {
177 /* create a utf8 string from descriptor */
179 descriptor = utf_new_char(builtintable_internal[i].descriptor);
181 /* parse the descriptor, builtin is always static (no `this' pointer) */
183 builtintable_internal[i].md =
184 descriptor_pool_parse_method_descriptor(descpool, descriptor,
188 for (i = 0; i < entries_automatic; i++) {
189 /* create a utf8 string from descriptor */
191 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
193 /* parse the descriptor, builtin is always static (no `this' pointer) */
195 builtintable_automatic[i].md =
196 descriptor_pool_parse_method_descriptor(descpool, descriptor,
200 /* release dump area */
202 dump_release(dumpsize);
208 /* builtintable_comparator *****************************************************
210 qsort comparator for the automatic builtin table.
212 *******************************************************************************/
214 static int builtintable_comparator(const void *a, const void *b)
216 builtintable_entry *bte1;
217 builtintable_entry *bte2;
219 bte1 = (builtintable_entry *) a;
220 bte2 = (builtintable_entry *) b;
222 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
226 /* builtintable_sort_automatic *************************************************
228 Sorts the automatic builtin table.
230 *******************************************************************************/
232 static void builtintable_sort_automatic(void)
236 /* calculate table size statically (`- 1' comment see builtintable.inc) */
238 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
240 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
241 builtintable_comparator);
245 /* builtin_init ****************************************************************
249 *******************************************************************************/
251 bool builtin_init(void)
253 /* initialize the builtin tables */
255 if (!builtintable_init())
258 /* sort builtin tables */
260 builtintable_sort_automatic();
266 /* builtintable_entry_debug_dump ***********************************************
268 Prints a builtintable_entry in human-readable form.
270 *******************************************************************************/
272 void builtintable_entry_debug_dump(FILE *file, builtintable_entry *bte)
278 fprintf(file,"(builtintable_entry *)NULL");
284 name = "<name=NULL>";
285 desc = (bte->md) ? "parsed " : bte->descriptor;
287 desc = "<desc=NULL>";
288 fprintf(file,"BUILTIN(%d,%p,%s %s",
289 bte->opcode,(void*)bte->fp,name,desc);
290 descriptor_debug_print_methoddesc(file,bte->md);
295 /* builtintable_get_internal ***************************************************
297 Finds an entry in the builtintable for internal functions and
298 returns the a pointer to the structure.
300 *******************************************************************************/
302 builtintable_entry *builtintable_get_internal(functionptr fp)
306 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
307 if (builtintable_internal[i].fp == fp)
308 return &builtintable_internal[i];
315 /* builtintable_get_automatic **************************************************
317 Finds an entry in the builtintable for functions which are replaced
318 automatically and returns the a pointer to the structure.
320 *******************************************************************************/
322 builtintable_entry *builtintable_get_automatic(s4 opcode)
324 builtintable_entry *first;
325 builtintable_entry *last;
326 builtintable_entry *middle;
330 /* calculate table size statically (`- 1' comment see builtintable.inc) */
332 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
334 first = builtintable_automatic;
335 last = builtintable_automatic + entries;
337 while (entries > 0) {
339 middle = first + half;
341 if (middle->opcode < opcode) {
348 return (first != last ? first : NULL);
352 /*****************************************************************************
354 *****************************************************************************/
358 /*************** internal function: builtin_isanysubclass *********************
360 Checks a subclass relation between two classes. Implemented interfaces
361 are interpreted as super classes.
362 Return value: 1 ... sub is subclass of super
365 *****************************************************************************/
366 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
369 castinfo classvalues;
374 if (super->flags & ACC_INTERFACE)
375 return (sub->vftbl->interfacetablelength > super->index) &&
376 (sub->vftbl->interfacetable[-super->index] != NULL);
378 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
380 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
381 (u4) classvalues.super_diffval;
387 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
391 castinfo classvalues;
396 asm_getclassvalues_atomic(super, sub, &classvalues);
398 if ((base = classvalues.super_baseval) <= 0)
399 /* super is an interface */
400 res = (sub->interfacetablelength > -base) &&
401 (sub->interfacetable[base] != NULL);
403 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
404 <= (u4) classvalues.super_diffval;
410 /****************** function: builtin_instanceof *****************************
412 Checks if an object is an instance of some given class (or subclass of
413 that class). If class is an interface, checks if the interface is
415 Return value: 1 ... obj is an instance of class or implements the interface
416 0 ... otherwise or if obj == NULL
418 *****************************************************************************/
420 /* XXX should use vftbl */
421 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
424 log_text ("builtin_instanceof called");
429 return builtin_isanysubclass(obj->vftbl->class, class);
434 /**************** function: builtin_checkcast *******************************
436 The same as builtin_instanceof except that 1 is returned when
439 ****************************************************************************/
441 /* XXX should use vftbl */
442 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
445 log_text("builtin_checkcast called");
450 if (builtin_isanysubclass(obj->vftbl->class, class))
454 printf("#### checkcast failed ");
455 utf_display(obj->vftbl->class->name);
457 utf_display(class->name);
465 /* builtin_descriptorscompatible ***********************************************
467 Checks if two array type descriptors are assignment compatible
469 Return value: 1 ... target = desc is possible
472 *******************************************************************************/
474 static s4 builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
479 if (desc->arraytype != target->arraytype)
482 if (desc->arraytype != ARRAYTYPE_OBJECT)
485 /* {both arrays are arrays of references} */
487 if (desc->dimension == target->dimension) {
488 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
489 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
490 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
492 if (desc->dimension < target->dimension) return 0;
494 /* {desc has higher dimension than target} */
495 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
499 /* builtin_arraycheckcast ******************************************************
501 Checks if an object is really a subtype of the requested array
502 type. The object has to be an array to begin with. For simple
503 arrays (int, short, double, etc.) the types have to match exactly.
504 For arrays of objects, the type of elements in the array has to be
505 a subtype (or the same type) of the requested element type. For
506 arrays of arrays (which in turn can again be arrays of arrays), the
507 types at the lowest level have to satisfy the corresponding sub
510 *******************************************************************************/
512 s4 builtin_arraycheckcast(java_objectheader *o, vftbl_t *target)
514 arraydescriptor *desc;
519 if ((desc = o->vftbl->arraydesc) == NULL)
522 return builtin_descriptorscompatible(desc, target->arraydesc);
526 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
531 return builtin_arraycheckcast(obj, target);
535 /************************** exception functions *******************************
537 ******************************************************************************/
539 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
541 java_lang_Throwable *t;
547 t = (java_lang_Throwable *) xptr;
549 /* calculate message length */
551 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
555 utf_strlen(xptr->vftbl->class->name) +
557 javastring_strlen((java_objectheader *) t->detailMessage);
560 logtextlen += strlen("(nil)");
562 /* allocate memory */
564 dumpsize = dump_size();
566 logtext = DMNEW(char, logtextlen);
568 strcpy(logtext, "Builtin exception thrown: ");
571 utf_sprint_classname(logtext + strlen(logtext),
572 xptr->vftbl->class->name);
574 if (t->detailMessage) {
577 buf = javastring_tochar((java_objectheader *) t->detailMessage);
578 strcat(logtext, ": ");
579 strcat(logtext, buf);
580 MFREE(buf, char, strlen(buf));
584 strcat(logtext, "(nil)");
591 dump_release(dumpsize);
594 *exceptionptr = xptr;
601 /* builtin_canstore ************************************************************
603 Checks, if an object can be stored in an array.
605 Return value: 1 ... possible
608 *******************************************************************************/
610 s4 builtin_canstore(java_objectarray *a, java_objectheader *o)
612 arraydescriptor *desc;
613 arraydescriptor *valuedesc;
614 vftbl_t *componentvftbl;
617 castinfo classvalues;
622 /* The following is guaranteed (by verifier checks):
624 * *) a->...vftbl->arraydesc != NULL
625 * *) a->...vftbl->arraydesc->componentvftbl != NULL
626 * *) o->vftbl is not an interface vftbl
629 desc = a->header.objheader.vftbl->arraydesc;
630 componentvftbl = desc->componentvftbl;
631 valuevftbl = o->vftbl;
633 if ((desc->dimension - 1) == 0) {
636 /* {a is a one-dimensional array} */
637 /* {a is an array of references} */
639 if (valuevftbl == componentvftbl)
642 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
644 if ((base = classvalues.super_baseval) <= 0)
645 /* an array of interface references */
646 return (valuevftbl->interfacetablelength > -base &&
647 valuevftbl->interfacetable[base] != NULL);
649 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
650 <= (unsigned) classvalues.super_diffval;
655 /* {a has dimension > 1} */
656 /* {componentvftbl->arraydesc != NULL} */
658 /* check if o is an array */
659 if ((valuedesc = valuevftbl->arraydesc) == NULL)
661 /* {o is an array} */
663 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
667 /* This is an optimized version where a is guaranteed to be one-dimensional */
668 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
670 arraydescriptor *desc;
671 vftbl_t *elementvftbl;
675 castinfo classvalues;
679 /* The following is guaranteed (by verifier checks):
681 * *) a->...vftbl->arraydesc != NULL
682 * *) a->...vftbl->arraydesc->elementvftbl != NULL
683 * *) a->...vftbl->arraydesc->dimension == 1
684 * *) o->vftbl is not an interface vftbl
687 desc = a->header.objheader.vftbl->arraydesc;
688 elementvftbl = desc->elementvftbl;
689 valuevftbl = o->vftbl;
691 /* {a is a one-dimensional array} */
693 if (valuevftbl == elementvftbl)
696 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
698 if ((base = classvalues.super_baseval) <= 0)
699 /* an array of interface references */
700 return (valuevftbl->interfacetablelength > -base &&
701 valuevftbl->interfacetable[base] != NULL);
703 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
704 <= (unsigned) classvalues.super_diffval;
710 /* This is an optimized version where a is guaranteed to be a
711 * one-dimensional array of a class type */
712 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
714 vftbl_t *elementvftbl;
717 castinfo classvalues;
721 /* The following is guaranteed (by verifier checks):
723 * *) a->...vftbl->arraydesc != NULL
724 * *) a->...vftbl->arraydesc->elementvftbl != NULL
725 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
726 * *) a->...vftbl->arraydesc->dimension == 1
727 * *) o->vftbl is not an interface vftbl
730 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
731 valuevftbl = o->vftbl;
733 /* {a is a one-dimensional array} */
735 if (valuevftbl == elementvftbl)
738 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
740 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
741 <= (unsigned) classvalues.super_diffval;
747 /* builtin_new *****************************************************************
749 Creates a new instance of class c on the heap.
751 Return value: pointer to the object or NULL if no memory is
754 *******************************************************************************/
756 java_objectheader *builtin_new(classinfo *c)
758 java_objectheader *o;
760 /* is the class loaded */
764 /* is the class linked */
769 if (!c->initialized) {
771 log_message_class("Initialize class (from builtin_new): ", c);
773 if (!initialize_class(c))
777 o = heap_allocate(c->instancesize, true, c->finalizer);
782 MSET(o, 0, u1, c->instancesize);
786 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
794 /* builtin_newarray ************************************************************
796 Creates an array with the given vftbl on the heap.
798 Return value: pointer to the array or NULL if no memory is available
800 CAUTION: The given vftbl must be the vftbl of the *array* class,
801 not of the element class.
803 *******************************************************************************/
805 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
808 arraydescriptor *desc;
813 desc = arrayvftbl->arraydesc;
814 dataoffset = desc->dataoffset;
815 componentsize = desc->componentsize;
818 *exceptionptr = new_negativearraysizeexception();
822 actualsize = dataoffset + size * componentsize;
824 if (((u4) actualsize) < ((u4) size)) { /* overflow */
825 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
829 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
834 MSET(a, 0, u1, actualsize);
836 a->objheader.vftbl = arrayvftbl;
838 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
839 initObjectLock(&a->objheader);
848 /* builtin_anewarray ***********************************************************
850 Creates an array of references to the given class type on the heap.
852 Return value: pointer to the array or NULL if no memory is
855 *******************************************************************************/
857 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
861 /* is class loaded */
862 assert(component->loaded);
864 /* is class linked */
865 if (!component->linked)
866 if (!link_class(component))
869 c = class_array_of(component, true);
874 return (java_objectarray *) builtin_newarray(size, c->vftbl);
878 /* builtin_newarray_int ********************************************************
880 Creates an array of 32 bit Integers on the heap.
882 Return value: pointer to the array or NULL if no memory is
885 *******************************************************************************/
887 java_intarray *builtin_newarray_int(s4 size)
889 return (java_intarray *)
890 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
894 /* builtin_newarray_long *******************************************************
896 Creates an array of 64 bit Integers on the heap.
898 Return value: pointer to the array or NULL if no memory is
901 *******************************************************************************/
903 java_longarray *builtin_newarray_long(s4 size)
905 return (java_longarray *)
906 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
910 /* builtin_newarray_float ******************************************************
912 Creates an array of 32 bit IEEE floats on the heap.
914 Return value: pointer to the array or NULL if no memory is
917 *******************************************************************************/
919 java_floatarray *builtin_newarray_float(s4 size)
921 return (java_floatarray *)
922 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
926 /* builtin_newarray_double *****************************************************
928 Creates an array of 64 bit IEEE floats on the heap.
930 Return value: pointer to the array or NULL if no memory is
933 *******************************************************************************/
935 java_doublearray *builtin_newarray_double(s4 size)
937 return (java_doublearray *)
938 builtin_newarray(size,
939 primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
943 /* builtin_newarray_byte *******************************************************
945 Creates an array of 8 bit Integers on the heap.
947 Return value: pointer to the array or NULL if no memory is
950 *******************************************************************************/
952 java_bytearray *builtin_newarray_byte(s4 size)
954 return (java_bytearray *)
955 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
959 /* builtin_newarray_char *******************************************************
961 Creates an array of characters on the heap.
963 Return value: pointer to the array or NULL if no memory is
966 *******************************************************************************/
968 java_chararray *builtin_newarray_char(s4 size)
970 return (java_chararray *)
971 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
975 /* builtin_newarray_short ******************************************************
977 Creates an array of 16 bit Integers on the heap.
979 Return value: pointer to the array or NULL if no memory is
982 *******************************************************************************/
984 java_shortarray *builtin_newarray_short(s4 size)
986 return (java_shortarray *)
987 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
991 /* builtin_newarray_boolean ****************************************************
993 Creates an array of bytes on the heap. The array is designated as
994 an array of booleans (important for casts)
996 Return value: pointer to the array or NULL if no memory is
999 *******************************************************************************/
1001 java_booleanarray *builtin_newarray_boolean(s4 size)
1003 return (java_booleanarray *)
1004 builtin_newarray(size,
1005 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
1009 /* builtin_multianewarray ******************************************************
1011 Creates a multi-dimensional array on the heap. The dimensions are
1012 passed in an array of longs.
1015 n............number of dimensions to create
1016 arrayvftbl...vftbl of the array class
1017 dims.........array containing the size of each dimension to create
1019 Return value: pointer to the array or NULL if no memory is
1022 ******************************************************************************/
1024 java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims)
1027 java_arrayheader *a;
1028 vftbl_t *componentvftbl;
1030 /* create this dimension */
1032 size = (s4) dims[0];
1033 a = builtin_newarray(size, arrayvftbl);
1038 /* if this is the last dimension return */
1043 /* get the vftbl of the components to create */
1045 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
1047 /* The verifier guarantees that the dimension count is in the range. */
1049 /* create the component arrays */
1051 for (i = 0; i < size; i++) {
1052 java_arrayheader *ea =
1053 builtin_multianewarray(n, componentvftbl, dims + 1);
1058 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1065 /*****************************************************************************
1068 Various functions for printing a message at method entry or exit (for
1071 *****************************************************************************/
1073 u4 methodindent = 0;
1075 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1089 log_text("WARNING: unmatched methodindent--");
1092 if (opt_verbose || runverbose || verboseexception) {
1093 /* calculate message length */
1097 strlen("Exception ") +
1098 utf_strlen(xptr->vftbl->class->name);
1101 logtextlen = strlen("Some Throwable");
1103 logtextlen += strlen(" thrown in ");
1107 utf_strlen(m->class->name) +
1109 utf_strlen(m->name) +
1110 strlen("(NOSYNC,NATIVE");
1112 #if SIZEOF_VOID_P == 8
1114 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1116 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1119 if (m->class->sourcefile == NULL)
1120 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1122 logtextlen += utf_strlen(m->class->sourcefile);
1124 logtextlen += strlen(":65536)");
1127 logtextlen += strlen("call_java_method");
1129 logtextlen += strlen("0");
1131 /* allocate memory */
1133 dumpsize = dump_size();
1135 logtext = DMNEW(char, logtextlen);
1138 strcpy(logtext, "Exception ");
1139 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1142 strcpy(logtext, "Some Throwable");
1145 strcat(logtext, " thrown in ");
1148 utf_strcat_classname(logtext, m->class->name);
1149 strcat(logtext, ".");
1150 utf_strcat(logtext, m->name);
1152 if (m->flags & ACC_SYNCHRONIZED)
1153 strcat(logtext, "(SYNC");
1155 strcat(logtext, "(NOSYNC");
1157 if (m->flags & ACC_NATIVE) {
1158 strcat(logtext, ",NATIVE");
1160 #if SIZEOF_VOID_P == 8
1161 sprintf(logtext + strlen(logtext),
1162 ")(0x%016lx) at position 0x%016lx",
1163 (ptrint) m->entrypoint, (ptrint) pos);
1165 sprintf(logtext + strlen(logtext),
1166 ")(0x%08x) at position 0x%08x",
1167 (ptrint) m->entrypoint, (ptrint) pos);
1171 #if SIZEOF_VOID_P == 8
1172 sprintf(logtext + strlen(logtext),
1173 ")(0x%016lx) at position 0x%016lx (",
1174 (ptrint) m->entrypoint, (ptrint) pos);
1176 sprintf(logtext + strlen(logtext),
1177 ")(0x%08x) at position 0x%08x (",
1178 (ptrint) m->entrypoint, (ptrint) pos);
1181 if (m->class->sourcefile == NULL)
1182 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1184 utf_strcat(logtext, m->class->sourcefile);
1186 sprintf(logtext + strlen(logtext), ":%d)", line);
1190 strcat(logtext, "call_java_method");
1194 /* release memory */
1196 dump_release(dumpsize);
1203 /* builtin_trace_args **********************************************************
1207 *******************************************************************************/
1209 #ifdef TRACE_ARGS_NUM
1210 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1211 #if TRACE_ARGS_NUM >= 6
1214 #if TRACE_ARGS_NUM == 8
1227 /* calculate message length */
1230 methodindent + strlen("called: ") +
1231 utf_strlen(m->class->name) +
1233 utf_strlen(m->name) +
1234 utf_strlen(m->descriptor) +
1235 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1237 /* add maximal argument length */
1239 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1241 /* allocate memory */
1243 dumpsize = dump_size();
1245 logtext = DMNEW(char, logtextlen);
1247 for (i = 0; i < methodindent; i++)
1250 strcpy(logtext + methodindent, "called: ");
1252 utf_strcat_classname(logtext, m->class->name);
1253 strcat(logtext, ".");
1254 utf_strcat(logtext, m->name);
1255 utf_strcat(logtext, m->descriptor);
1257 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1258 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1259 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1260 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1261 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1262 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1263 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1264 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1265 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1266 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1267 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1269 strcat(logtext, "(");
1271 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1272 /* Only Arguments in integer Registers are passed correctly here */
1273 /* long longs spilled on Stack have an wrong offset of +4 */
1274 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1275 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1276 switch (md->paramcount) {
1280 #if SIZEOF_VOID_P == 4
1282 sprintf(logtext + strlen(logtext),
1288 sprintf(logtext + strlen(logtext),
1294 sprintf(logtext + strlen(logtext),
1295 "0x%llx, 0x%llx, 0x%llx",
1300 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1302 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1306 #if TRACE_ARGS_NUM >= 6
1308 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1310 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1315 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1317 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1320 #endif /* TRACE_ARGS_NUM >= 6 */
1322 #if TRACE_ARGS_NUM == 8
1324 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1326 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1328 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1332 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1334 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1336 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1338 #endif /* TRACE_ARGS_NUM == 8 */
1341 #if TRACE_ARGS_NUM == 4
1342 sprintf(logtext + strlen(logtext),
1343 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1344 a0, a1, a2, a3, m->paramcount - 4);
1346 #elif TRACE_ARGS_NUM == 6
1347 sprintf(logtext + strlen(logtext),
1348 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1349 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1351 #elif TRACE_ARGS_NUM == 8
1352 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1354 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1356 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1357 , a6, a7, m->paramcount - 8);
1361 #else /* SIZEOF_VOID_P == 4 */
1364 sprintf(logtext + strlen(logtext),
1370 sprintf(logtext + strlen(logtext),
1376 sprintf(logtext + strlen(logtext),
1377 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1381 sprintf(logtext + strlen(logtext),
1382 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1386 #if TRACE_ARGS_NUM >= 6
1388 sprintf(logtext + strlen(logtext),
1389 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1390 a0, a1, a2, a3, a4);
1394 sprintf(logtext + strlen(logtext),
1395 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1396 a0, a1, a2, a3, a4, a5);
1398 #endif /* TRACE_ARGS_NUM >= 6 */
1400 #if TRACE_ARGS_NUM == 8
1402 sprintf(logtext + strlen(logtext),
1403 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1404 a0, a1, a2, a3, a4, a5, a6);
1408 sprintf(logtext + strlen(logtext),
1409 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1410 a0, a1, a2, a3, a4, a5, a6, a7);
1412 #endif /* TRACE_ARGS_NUM == 8 */
1415 #if TRACE_ARGS_NUM == 4
1416 sprintf(logtext + strlen(logtext),
1417 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1418 a0, a1, a2, a3, m->paramcount - 4);
1420 #elif TRACE_ARGS_NUM == 6
1421 sprintf(logtext + strlen(logtext),
1422 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1423 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1425 #elif TRACE_ARGS_NUM == 8
1426 sprintf(logtext + strlen(logtext),
1427 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1428 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1431 #endif /* SIZEOF_VOID_P == 4 */
1434 strcat(logtext, ")");
1438 /* release memory */
1440 dump_release(dumpsize);
1447 /* builtin_displaymethodstop ***************************************************
1451 *******************************************************************************/
1453 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1464 /* calculate message length */
1467 methodindent + strlen("finished: ") +
1468 utf_strlen(m->class->name) +
1470 utf_strlen(m->name) +
1471 utf_strlen(m->descriptor) +
1472 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1474 /* add maximal argument length */
1476 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1478 /* allocate memory */
1480 dumpsize = dump_size();
1482 logtext = DMNEW(char, logtextlen);
1484 /* generate the message */
1486 for (i = 0; i < methodindent; i++)
1492 log_text("WARNING: unmatched methodindent--");
1494 strcpy(logtext + methodindent, "finished: ");
1495 utf_strcat_classname(logtext, m->class->name);
1496 strcat(logtext, ".");
1497 utf_strcat(logtext, m->name);
1498 utf_strcat(logtext, m->descriptor);
1500 switch (md->returntype.type) {
1502 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1506 #if SIZEOF_VOID_P == 4
1507 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1509 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1514 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1519 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1524 #if SIZEOF_VOID_P == 4
1525 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1527 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1534 /* release memory */
1536 dump_release(dumpsize);
1540 /****************************************************************************
1541 SYNCHRONIZATION FUNCTIONS
1542 *****************************************************************************/
1544 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1546 * Lock the mutex of an object.
1548 void internal_lock_mutex_for_object(java_objectheader *object)
1550 mutexHashEntry *entry;
1553 assert(object != 0);
1555 hashValue = MUTEX_HASH_VALUE(object);
1556 entry = &mutexHashTable[hashValue];
1558 if (entry->object != 0) {
1559 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1561 entry->mutex.holder = 0;
1562 entry->mutex.count = 0;
1563 entry->mutex.muxWaiters = 0;
1566 while (entry->next != 0 && entry->object != object)
1567 entry = entry->next;
1569 if (entry->object != object) {
1570 entry->next = firstFreeOverflowEntry;
1571 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1573 entry = entry->next;
1576 assert(entry->conditionCount == 0);
1581 entry->mutex.holder = 0;
1582 entry->mutex.count = 0;
1583 entry->mutex.muxWaiters = 0;
1586 if (entry->object == 0)
1587 entry->object = object;
1589 internal_lock_mutex(&entry->mutex);
1594 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1596 * Unlocks the mutex of an object.
1598 void internal_unlock_mutex_for_object (java_objectheader *object)
1601 mutexHashEntry *entry;
1603 hashValue = MUTEX_HASH_VALUE(object);
1604 entry = &mutexHashTable[hashValue];
1606 if (entry->object == object) {
1607 internal_unlock_mutex(&entry->mutex);
1610 while (entry->next != 0 && entry->next->object != object)
1611 entry = entry->next;
1613 assert(entry->next != 0);
1615 internal_unlock_mutex(&entry->next->mutex);
1617 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1618 mutexHashEntry *unlinked = entry->next;
1620 entry->next = unlinked->next;
1621 unlinked->next = firstFreeOverflowEntry;
1622 firstFreeOverflowEntry = unlinked;
1629 #if defined(USE_THREADS)
1630 void builtin_monitorenter(java_objectheader *o)
1632 #if !defined(NATIVE_THREADS)
1637 hashValue = MUTEX_HASH_VALUE(o);
1638 if (mutexHashTable[hashValue].object == o
1639 && mutexHashTable[hashValue].mutex.holder == currentThread)
1640 ++mutexHashTable[hashValue].mutex.count;
1642 internal_lock_mutex_for_object(o);
1646 monitorEnter((threadobject *) THREADOBJECT, o);
1652 #if defined(USE_THREADS)
1654 * Locks the class object - needed for static synchronized methods.
1655 * The use_class_as_object call is needed in order to circumvent a
1656 * possible deadlock with builtin_monitorenter called by another
1657 * thread calling use_class_as_object.
1659 void builtin_staticmonitorenter(classinfo *c)
1661 use_class_as_object(c);
1662 builtin_monitorenter(&c->header);
1667 #if defined(USE_THREADS)
1668 void builtin_monitorexit(java_objectheader *o)
1670 #if !defined(NATIVE_THREADS)
1675 hashValue = MUTEX_HASH_VALUE(o);
1676 if (mutexHashTable[hashValue].object == o) {
1677 if (mutexHashTable[hashValue].mutex.count == 1
1678 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1679 internal_unlock_mutex_for_object(o);
1681 --mutexHashTable[hashValue].mutex.count;
1684 internal_unlock_mutex_for_object(o);
1688 monitorExit((threadobject *) THREADOBJECT, o);
1694 /*****************************************************************************
1695 MISCELLANEOUS HELPER FUNCTIONS
1696 *****************************************************************************/
1700 /*********** Functions for integer divisions *****************************
1702 On some systems (eg. DEC ALPHA), integer division is not supported by the
1703 CPU. These helper functions implement the missing functionality.
1705 ******************************************************************************/
1707 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1708 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1711 /************** Functions for long arithmetics *******************************
1713 On systems where 64 bit Integers are not supported by the CPU, these
1714 functions are needed.
1716 ******************************************************************************/
1719 s8 builtin_ladd(s8 a, s8 b)
1724 return builtin_i2l(0);
1728 s8 builtin_lsub(s8 a, s8 b)
1733 return builtin_i2l(0);
1737 s8 builtin_lmul(s8 a, s8 b)
1742 return builtin_i2l(0);
1746 s8 builtin_ldiv(s8 a, s8 b)
1751 return builtin_i2l(0);
1755 s8 builtin_lrem(s8 a, s8 b)
1760 return builtin_i2l(0);
1764 s8 builtin_lshl(s8 a, s4 b)
1767 return a << (b & 63);
1769 return builtin_i2l(0);
1773 s8 builtin_lshr(s8 a, s4 b)
1776 return a >> (b & 63);
1778 return builtin_i2l(0);
1782 s8 builtin_lushr(s8 a, s4 b)
1785 return ((u8) a) >> (b & 63);
1787 return builtin_i2l(0);
1791 s8 builtin_land(s8 a, s8 b)
1796 return builtin_i2l(0);
1800 s8 builtin_lor(s8 a, s8 b)
1805 return builtin_i2l(0);
1809 s8 builtin_lxor(s8 a, s8 b)
1814 return builtin_i2l(0);
1818 s8 builtin_lneg(s8 a)
1823 return builtin_i2l(0);
1827 s4 builtin_lcmp(s8 a, s8 b)
1830 if (a < b) return -1;
1831 if (a > b) return 1;
1842 /*********** Functions for floating point operations *************************/
1844 float builtin_fadd(float a, float b)
1846 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1847 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1858 if (copysignf(1.0, a) == copysignf(1.0, b))
1861 return intBitsToFloat(FLT_NAN);
1867 float builtin_fsub(float a, float b)
1869 return builtin_fadd(a, builtin_fneg(b));
1873 float builtin_fmul(float a, float b)
1875 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1876 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1878 if (finitef(b)) return a * b;
1880 if (a == 0) return intBitsToFloat(FLT_NAN);
1881 else return copysignf(b, copysignf(1.0, b)*a);
1886 if (b == 0) return intBitsToFloat(FLT_NAN);
1887 else return copysignf(a, copysignf(1.0, a)*b);
1890 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1896 /* builtin_ddiv ****************************************************************
1898 Implementation as described in VM Spec.
1900 *******************************************************************************/
1902 float builtin_fdiv(float a, float b)
1906 /* If neither value1' nor value2' is NaN, the sign of the result */
1907 /* is positive if both values have the same sign, negative if the */
1908 /* values have different signs. */
1914 /* If either value1' or value2' is NaN, the result is NaN. */
1916 return intBitsToFloat(FLT_NAN);
1919 /* Division of a finite value by an infinity results in a */
1920 /* signed zero, with the sign-producing rule just given. */
1922 /* is sign equal? */
1924 if (copysignf(1.0, a) == copysignf(1.0, b))
1933 /* If either value1' or value2' is NaN, the result is NaN. */
1935 return intBitsToFloat(FLT_NAN);
1937 } else if (finitef(b)) {
1938 /* Division of an infinity by a finite value results in a signed */
1939 /* infinity, with the sign-producing rule just given. */
1941 /* is sign equal? */
1943 if (copysignf(1.0, a) == copysignf(1.0, b))
1944 return intBitsToFloat(FLT_POSINF);
1946 return intBitsToFloat(FLT_NEGINF);
1949 /* Division of an infinity by an infinity results in NaN. */
1951 return intBitsToFloat(FLT_NAN);
1957 float builtin_frem(float a, float b)
1963 float builtin_fneg(float a)
1965 if (isnanf(a)) return a;
1967 if (finitef(a)) return -a;
1968 else return copysignf(a, -copysignf(1.0, a));
1973 s4 builtin_fcmpl(float a, float b)
1975 if (isnanf(a)) return -1;
1976 if (isnanf(b)) return -1;
1977 if (!finitef(a) || !finitef(b)) {
1978 a = finitef(a) ? 0 : copysignf(1.0, a);
1979 b = finitef(b) ? 0 : copysignf(1.0, b);
1981 if (a > b) return 1;
1982 if (a == b) return 0;
1987 s4 builtin_fcmpg(float a, float b)
1989 if (isnanf(a)) return 1;
1990 if (isnanf(b)) return 1;
1991 if (!finitef(a) || !finitef(b)) {
1992 a = finitef(a) ? 0 : copysignf(1.0, a);
1993 b = finitef(b) ? 0 : copysignf(1.0, b);
1995 if (a > b) return 1;
1996 if (a == b) return 0;
2002 /************************* Functions for doubles ****************************/
2004 double builtin_dadd(double a, double b)
2006 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2007 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2009 if (finite(b)) return a + b;
2013 if (finite(b)) return a;
2015 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2016 else return longBitsToDouble(DBL_NAN);
2022 double builtin_dsub(double a, double b)
2024 return builtin_dadd(a, builtin_dneg(b));
2028 double builtin_dmul(double a, double b)
2030 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2031 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2033 if (finite(b)) return a * b;
2035 if (a == 0) return longBitsToDouble(DBL_NAN);
2036 else return copysign(b, copysign(1.0, b) * a);
2041 if (b == 0) return longBitsToDouble(DBL_NAN);
2042 else return copysign(a, copysign(1.0, a) * b);
2045 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2051 /* builtin_ddiv ****************************************************************
2053 Implementation as described in VM Spec.
2055 *******************************************************************************/
2057 double builtin_ddiv(double a, double b)
2061 /* If neither value1' nor value2' is NaN, the sign of the result */
2062 /* is positive if both values have the same sign, negative if the */
2063 /* values have different signs. */
2069 /* If either value1' or value2' is NaN, the result is NaN. */
2071 return longBitsToDouble(DBL_NAN);
2074 /* Division of a finite value by an infinity results in a */
2075 /* signed zero, with the sign-producing rule just given. */
2077 /* is sign equal? */
2079 if (copysign(1.0, a) == copysign(1.0, b))
2088 /* If either value1' or value2' is NaN, the result is NaN. */
2090 return longBitsToDouble(DBL_NAN);
2092 } else if (finite(b)) {
2093 /* Division of an infinity by a finite value results in a signed */
2094 /* infinity, with the sign-producing rule just given. */
2096 /* is sign equal? */
2098 if (copysign(1.0, a) == copysign(1.0, b))
2099 return longBitsToDouble(DBL_POSINF);
2101 return longBitsToDouble(DBL_NEGINF);
2104 /* Division of an infinity by an infinity results in NaN. */
2106 return longBitsToDouble(DBL_NAN);
2112 double builtin_drem(double a, double b)
2117 /* builtin_dneg ****************************************************************
2119 Implemented as described in VM Spec.
2121 *******************************************************************************/
2123 double builtin_dneg(double a)
2126 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2133 /* If the operand is a zero, the result is the zero of opposite */
2139 /* If the operand is an infinity, the result is the infinity of */
2140 /* opposite sign. */
2142 return copysign(a, -copysign(1.0, a));
2148 s4 builtin_dcmpl(double a, double b)
2150 if (isnan(a)) return -1;
2151 if (isnan(b)) return -1;
2152 if (!finite(a) || !finite(b)) {
2153 a = finite(a) ? 0 : copysign(1.0, a);
2154 b = finite(b) ? 0 : copysign(1.0, b);
2156 if (a > b) return 1;
2157 if (a == b) return 0;
2162 s4 builtin_dcmpg(double a, double b)
2164 if (isnan(a)) return 1;
2165 if (isnan(b)) return 1;
2166 if (!finite(a) || !finite(b)) {
2167 a = finite(a) ? 0 : copysign(1.0, a);
2168 b = finite(b) ? 0 : copysign(1.0, b);
2170 if (a > b) return 1;
2171 if (a == b) return 0;
2176 /*********************** Conversion operations ****************************/
2178 s8 builtin_i2l(s4 i)
2191 float builtin_i2f(s4 a)
2193 float f = (float) a;
2198 double builtin_i2d(s4 a)
2200 double d = (double) a;
2205 s4 builtin_l2i(s8 l)
2215 float builtin_l2f(s8 a)
2218 float f = (float) a;
2226 double builtin_l2d(s8 a)
2229 double d = (double) a;
2237 s4 builtin_f2i(float a)
2240 return builtin_d2i((double) a);
2249 if (a < (-2147483648))
2250 return (-2147483648);
2253 f = copysignf((float) 1.0, a);
2256 return (-2147483648); */
2260 s8 builtin_f2l(float a)
2263 return builtin_d2l((double) a);
2268 if (a > 9223372036854775807L)
2269 return 9223372036854775807L;
2270 if (a < (-9223372036854775808L))
2271 return (-9223372036854775808L);
2276 f = copysignf((float) 1.0, a);
2278 return 9223372036854775807L;
2279 return (-9223372036854775808L); */
2283 double builtin_f2d(float a)
2285 if (finitef(a)) return (double) a;
2288 return longBitsToDouble(DBL_NAN);
2290 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2295 s4 builtin_d2i(double a)
2300 if (a >= 2147483647)
2302 if (a <= (-2147483647-1))
2303 return (-2147483647-1);
2308 d = copysign(1.0, a);
2311 return (-2147483647-1);
2315 s8 builtin_d2l(double a)
2320 if (a >= 9223372036854775807LL)
2321 return 9223372036854775807LL;
2322 if (a <= (-9223372036854775807LL-1))
2323 return (-9223372036854775807LL-1);
2328 d = copysign(1.0, a);
2330 return 9223372036854775807LL;
2331 return (-9223372036854775807LL-1);
2335 float builtin_d2f(double a)
2341 return intBitsToFloat(FLT_NAN);
2343 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2348 /* used to convert FLT_xxx defines into float values */
2350 inline float intBitsToFloat(s4 i)
2359 /* used to convert DBL_xxx defines into double values */
2361 inline float longBitsToDouble(s8 l)
2370 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2372 return (java_arrayheader *)
2373 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2377 s4 builtin_dummy(void)
2379 log_text("Internal error: builtin_dummy called (native function is missing)");
2382 /* keep the compiler happy */
2388 /* builtin_asm_get_exceptionptrptr *********************************************
2390 this is a wrapper for calls from asmpart
2392 *******************************************************************************/
2394 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2395 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2397 return builtin_get_exceptionptrptr();
2402 methodinfo *builtin_asm_get_threadrootmethod(void)
2404 return *threadrootmethod;
2408 void *builtin_asm_get_stackframeinfo(void)
2410 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2411 return &THREADINFO->_stackframeinfo;
2413 /* XXX FIXME FOR OLD THREAD IMPL (jowenn) */
2415 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2420 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,
2421 stacktraceelement *begin,
2422 stacktraceelement *end)
2424 /* stacktraceelement *el;*/
2427 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2428 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2430 *el=MNEW(stacktraceelement,s+1); /*GC*/
2432 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2435 /* XXX change this if line numbers bigger than u2 are allowed, the */
2436 /* currently supported class file format does no allow that */
2438 (*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 */
2444 * These are local overrides for various environment variables in Emacs.
2445 * Please do not remove this and leave it at the end of the file, where
2446 * Emacs will automagically detect them.
2447 * ---------------------------------------------------------------------
2450 * indent-tabs-mode: t