X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fbuiltin.c;h=57918bdcaada8b461545d8ef80213210775ef5d2;hb=cc78025b4ac412a74a0535eb910578ec335122b4;hp=2a4de6f21bd80eca4dc1be83cf8bdb4158bbf32a;hpb=52d1e2557fe42c8836c6b3dd8670862247e748c4;p=cacao.git diff --git a/src/vm/builtin.c b/src/vm/builtin.c index 2a4de6f21..57918bdca 100644 --- a/src/vm/builtin.c +++ b/src/vm/builtin.c @@ -1,9 +1,9 @@ -/* vm/builtin.c - functions for unsupported operations +/* src/vm/builtin.c - functions for unsupported operations - Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates, - R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, - C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, - Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel, + C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, + E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, + J. Wenninger, Institut f. Computersprachen - TU Wien This file is part of CACAO. @@ -19,34 +19,48 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - Contact: cacao@complang.tuwien.ac.at + Contact: cacao@cacaojvm.org Authors: Reinhard Grafl Andreas Krall Mark Probst + Changes: Christian Thalinger + Edwin Steiner + Contains C functions for JavaVM Instructions that cannot be translated to machine language directly. Consequently, the generated machine code for these instructions contains function calls instead of machine instructions, using the C calling convention. - $Id: builtin.c 1934 2005-02-10 10:58:43Z twisti $ + $Id: builtin.c 4690 2006-03-27 11:37:46Z twisti $ */ +#include "config.h" + #include -#include #include +#include +#include + +#include "vm/types.h" + +#include "arch.h" +#include "md-abi.h" + +#include "fdlibm/fdlibm.h" #include "mm/boehm.h" #include "mm/memory.h" #include "native/native.h" #include "native/include/java_lang_Cloneable.h" +#include "native/include/java_lang_Object.h" /* required by VMObject */ #include "native/include/java_lang_VMObject.h" #if defined(USE_THREADS) @@ -59,20 +73,250 @@ #endif #include "toolbox/logging.h" +#include "toolbox/util.h" #include "vm/builtin.h" +#include "vm/class.h" #include "vm/exceptions.h" #include "vm/global.h" +#include "vm/initialize.h" #include "vm/loader.h" #include "vm/options.h" #include "vm/stringlocal.h" -#include "vm/tables.h" #include "vm/jit/asmpart.h" +#include "vm/jit/patcher.h" + + +/* include builtin tables *****************************************************/ + +#include "vm/builtintable.inc" + + +/* builtintable_init *********************************************************** + + Parse the descriptors of builtin functions and create the parsed + descriptors. + +*******************************************************************************/ + +static bool builtintable_init(void) +{ + descriptor_pool *descpool; + s4 dumpsize; + utf *descriptor; + s4 entries_internal; + s4 entries_automatic; + s4 i; + + /* mark start of dump memory area */ + + dumpsize = dump_size(); + + /* create a new descriptor pool */ + + descpool = descriptor_pool_new(class_java_lang_Object); + + /* add some entries we need */ + + if (!descriptor_pool_add_class(descpool, utf_java_lang_Object)) + return false; + + if (!descriptor_pool_add_class(descpool, utf_java_lang_Class)) + return false; + + /* calculate table entries statically */ + + entries_internal = + sizeof(builtintable_internal) / sizeof(builtintable_entry); + + entries_automatic = + sizeof(builtintable_automatic) / sizeof(builtintable_entry) + - 1; /* last filler entry (comment see builtintable.inc) */ + + /* first add all descriptors to the pool */ + + for (i = 0; i < entries_internal; i++) { + /* create a utf8 string from descriptor */ + + descriptor = utf_new_char(builtintable_internal[i].descriptor); + + if (!descriptor_pool_add(descpool, descriptor, NULL)) { + /* release dump area */ + + dump_release(dumpsize); + + return false; + } + } + + for (i = 0; i < entries_automatic; i++) { + /* create a utf8 string from descriptor */ + + descriptor = utf_new_char(builtintable_automatic[i].descriptor); + + if (!descriptor_pool_add(descpool, descriptor, NULL)) { + /* release dump area */ + + dump_release(dumpsize); + + return false; + } + } + + /* create the class reference table */ + + (void) descriptor_pool_create_classrefs(descpool, NULL); + + /* allocate space for the parsed descriptors */ + + descriptor_pool_alloc_parsed_descriptors(descpool); + + /* now parse all descriptors */ + + for (i = 0; i < entries_internal; i++) { + /* create a utf8 string from descriptor */ + + descriptor = utf_new_char(builtintable_internal[i].descriptor); + + /* parse the descriptor, builtin is always static (no `this' pointer) */ + + builtintable_internal[i].md = + descriptor_pool_parse_method_descriptor(descpool, descriptor, + ACC_STATIC, NULL); + } + + for (i = 0; i < entries_automatic; i++) { + /* create a utf8 string from descriptor */ + + descriptor = utf_new_char(builtintable_automatic[i].descriptor); + + /* parse the descriptor, builtin is always static (no `this' pointer) */ + + builtintable_automatic[i].md = + descriptor_pool_parse_method_descriptor(descpool, descriptor, + ACC_STATIC, NULL); + } + + /* release dump area */ + + dump_release(dumpsize); + + return true; +} + + +/* builtintable_comparator ***************************************************** + + qsort comparator for the automatic builtin table. + +*******************************************************************************/ + +static int builtintable_comparator(const void *a, const void *b) +{ + builtintable_entry *bte1; + builtintable_entry *bte2; + + bte1 = (builtintable_entry *) a; + bte2 = (builtintable_entry *) b; + + return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode); +} + + +/* builtintable_sort_automatic ************************************************* + + Sorts the automatic builtin table. + +*******************************************************************************/ + +static void builtintable_sort_automatic(void) +{ + s4 entries; + + /* calculate table size statically (`- 1' comment see builtintable.inc) */ + + entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1; + + qsort(builtintable_automatic, entries, sizeof(builtintable_entry), + builtintable_comparator); +} + + +/* builtin_init **************************************************************** + + XXX + +*******************************************************************************/ + +bool builtin_init(void) +{ + /* initialize the builtin tables */ + + if (!builtintable_init()) + return false; + + /* sort builtin tables */ + + builtintable_sort_automatic(); + + return true; +} + + +/* builtintable_get_internal *************************************************** + + Finds an entry in the builtintable for internal functions and + returns the a pointer to the structure. + +*******************************************************************************/ + +builtintable_entry *builtintable_get_internal(functionptr fp) +{ + s4 i; + + for (i = 0; builtintable_internal[i].fp != NULL; i++) { + if (builtintable_internal[i].fp == fp) + return &builtintable_internal[i]; + } + + return NULL; +} + + +/* builtintable_get_automatic ************************************************** + + Finds an entry in the builtintable for functions which are replaced + automatically and returns the a pointer to the structure. + +*******************************************************************************/ + +builtintable_entry *builtintable_get_automatic(s4 opcode) +{ + builtintable_entry *first; + builtintable_entry *last; + builtintable_entry *middle; + s4 half; + s4 entries; + + /* calculate table size statically (`- 1' comment see builtintable.inc) */ + entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1; -#undef DEBUG /*define DEBUG 1*/ + first = builtintable_automatic; + last = builtintable_automatic + entries; + + while (entries > 0) { + half = entries / 2; + middle = first + half; + + if (middle->opcode < opcode) { + first = middle + 1; + entries -= half + 1; + } else + entries = half; + } -THREADSPECIFIC methodinfo* _threadrootmethod = NULL; -THREADSPECIFIC void *_thread_nativestackframeinfo = NULL; + return (first != last ? first : NULL); +} /***************************************************************************** @@ -97,14 +341,16 @@ s4 builtin_isanysubclass(classinfo *sub, classinfo *super) if (sub == super) return 1; - if (super->flags & ACC_INTERFACE) - return (sub->vftbl->interfacetablelength > super->index) && + if (super->flags & ACC_INTERFACE) { + res = (sub->vftbl->interfacetablelength > super->index) && (sub->vftbl->interfacetable[-super->index] != NULL); - asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues); + } else { + ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues); - res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <= - (u4) classvalues.super_diffval; + res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <= + (u4) classvalues.super_diffval; + } return res; } @@ -119,15 +365,16 @@ s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super) if (sub == super) return 1; - asm_getclassvalues_atomic(super, sub, &classvalues); + ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues); - if ((base = classvalues.super_baseval) <= 0) + if ((base = classvalues.super_baseval) <= 0) { /* super is an interface */ res = (sub->interfacetablelength > -base) && (sub->interfacetable[base] != NULL); - else + } else { res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <= (u4) classvalues.super_diffval; + } return res; } @@ -143,14 +390,12 @@ s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super) *****************************************************************************/ -/* XXX should use vftbl */ s4 builtin_instanceof(java_objectheader *obj, classinfo *class) { -#ifdef DEBUG - log_text ("builtin_instanceof called"); -#endif - if (!obj) return 0; - return builtin_isanysubclass (obj->vftbl->class, class); + if (!obj) + return 0; + + return builtin_isanysubclass(obj->vftbl->class, class); } @@ -162,89 +407,96 @@ s4 builtin_instanceof(java_objectheader *obj, classinfo *class) ****************************************************************************/ -/* XXX should use vftbl */ s4 builtin_checkcast(java_objectheader *obj, classinfo *class) { -#ifdef DEBUG - log_text("builtin_checkcast called"); -#endif - if (obj == NULL) return 1; + if (builtin_isanysubclass(obj->vftbl->class, class)) return 1; -#if DEBUG - printf("#### checkcast failed "); - utf_display(obj->vftbl->class->name); - printf(" -> "); - utf_display(class->name); - printf("\n"); -#endif - return 0; } -/*********** internal function: builtin_descriptorscompatible ****************** +/* builtin_descriptorscompatible *********************************************** - Checks if two array type descriptors are assignment compatible - Return value: 1 ... target = desc is possible - 0 ... otherwise + Checks if two array type descriptors are assignment compatible + + Return value: 1 ... target = desc is possible + 0 ... otherwise -******************************************************************************/ +*******************************************************************************/ -static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target) +static s4 builtin_descriptorscompatible(arraydescriptor *desc, + arraydescriptor *target) { - if (desc==target) return 1; - if (desc->arraytype != target->arraytype) return 0; - if (desc->arraytype != ARRAYTYPE_OBJECT) return 1; + if (desc == target) + return 1; + + if (desc->arraytype != target->arraytype) + return 0; + + if (desc->arraytype != ARRAYTYPE_OBJECT) + return 1; /* {both arrays are arrays of references} */ + if (desc->dimension == target->dimension) { - /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/ - if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1; - return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl); + /* an array which contains elements of interface types is + allowed to be casted to Object (JOWENN)*/ + + if ((desc->elementvftbl->baseval < 0) && + (target->elementvftbl->baseval == 1)) + return 1; + + return builtin_isanysubclass_vftbl(desc->elementvftbl, + target->elementvftbl); } - if (desc->dimension < target->dimension) return 0; + + if (desc->dimension < target->dimension) + return 0; /* {desc has higher dimension than target} */ - return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl); + + return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, + target->elementvftbl); } -/******************** function: builtin_checkarraycast *********************** +/* builtin_arraycheckcast ****************************************************** - Checks if an object is really a subtype of the requested array type. - The object has to be an array to begin with. For simple arrays (int, short, - double, etc.) the types have to match exactly. - For arrays of objects, the type of elements in the array has to be a - subtype (or the same type) of the requested element type. For arrays of - arrays (which in turn can again be arrays of arrays), the types at the - lowest level have to satisfy the corresponding sub class relation. + Checks if an object is really a subtype of the requested array + type. The object has to be an array to begin with. For simple + arrays (int, short, double, etc.) the types have to match exactly. + For arrays of objects, the type of elements in the array has to be + a subtype (or the same type) of the requested element type. For + arrays of arrays (which in turn can again be arrays of arrays), the + types at the lowest level have to satisfy the corresponding sub + class relation. - Return value: 1 ... cast is possible - 0 ... otherwise - - ATTENTION: a cast with a NULL pointer is always possible. - -*****************************************************************************/ +*******************************************************************************/ -s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target) +s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass) { arraydescriptor *desc; - - if (!o) return 1; - if ((desc = o->vftbl->arraydesc) == NULL) return 0; - return builtin_descriptorscompatible(desc, target->arraydesc); + if (!o) + return 1; + + if ((desc = o->vftbl->arraydesc) == NULL) + return 0; + + return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc); } -s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target) +s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass) { - if (!obj) return 1; - return builtin_checkarraycast(obj, target); + if (!o) + return 0; + + return builtin_arraycheckcast(o, targetclass); } @@ -252,15 +504,39 @@ s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target) ******************************************************************************/ +#if !defined(NDEBUG) java_objectheader *builtin_throw_exception(java_objectheader *xptr) { + java_lang_Throwable *t; + char *logtext; + s4 logtextlen; + s4 dumpsize; + if (opt_verbose) { - char logtext[MAXLOGTEXT]; - sprintf(logtext, "Builtin exception thrown: "); + t = (java_lang_Throwable *) xptr; + + /* calculate message length */ - if (xptr) { - java_lang_Throwable *t = (java_lang_Throwable *) xptr; + logtextlen = strlen("Builtin exception thrown: ") + strlen("0"); + if (t) { + logtextlen += + utf_strlen(xptr->vftbl->class->name) + + strlen(": ") + + javastring_strlen(t->detailMessage); + + } else + logtextlen += strlen("(nil)"); + + /* allocate memory */ + + dumpsize = dump_size(); + + logtext = DMNEW(char, logtextlen); + + strcpy(logtext, "Builtin exception thrown: "); + + if (t) { utf_sprint_classname(logtext + strlen(logtext), xptr->vftbl->class->name); @@ -268,85 +544,94 @@ java_objectheader *builtin_throw_exception(java_objectheader *xptr) char *buf; buf = javastring_tochar((java_objectheader *) t->detailMessage); - sprintf(logtext + strlen(logtext), ": %s", buf); + strcat(logtext, ": "); + strcat(logtext, buf); MFREE(buf, char, strlen(buf)); } } else { - sprintf(logtext + strlen(logtext), "Error: "); + strcat(logtext, "(nil)"); } log_text(logtext); + + /* release memory */ + + dump_release(dumpsize); } *exceptionptr = xptr; return xptr; } +#endif /* !defined(NDEBUG) */ +/* builtin_canstore ************************************************************ -/******************* function: builtin_canstore ******************************* + Checks, if an object can be stored in an array. - Checks, if an object can be stored in an array. - Return value: 1 ... possible - 0 ... otherwise + Return value: 1 ... possible + 0 ... otherwise -******************************************************************************/ +*******************************************************************************/ -s4 builtin_canstore (java_objectarray *a, java_objectheader *o) +s4 builtin_canstore(java_objectarray *oa, java_objectheader *o) { arraydescriptor *desc; arraydescriptor *valuedesc; - vftbl_t *componentvftbl; - vftbl_t *valuevftbl; - int dim_m1; - int base; - castinfo classvalues; - - if (!o) return 1; + vftbl_t *componentvftbl; + vftbl_t *valuevftbl; + s4 base; + castinfo classvalues; + + if (!o) + return 1; /* The following is guaranteed (by verifier checks): * - * *) a->...vftbl->arraydesc != NULL - * *) a->...vftbl->arraydesc->componentvftbl != NULL + * *) oa->...vftbl->arraydesc != NULL + * *) oa->...vftbl->arraydesc->componentvftbl != NULL * *) o->vftbl is not an interface vftbl */ - desc = a->header.objheader.vftbl->arraydesc; - componentvftbl = desc->componentvftbl; - valuevftbl = o->vftbl; + desc = oa->header.objheader.vftbl->arraydesc; + componentvftbl = desc->componentvftbl; + valuevftbl = o->vftbl; - if ((dim_m1 = desc->dimension - 1) == 0) { + if ((desc->dimension - 1) == 0) { s4 res; - /* {a is a one-dimensional array} */ - /* {a is an array of references} */ + /* {oa is a one-dimensional array} */ + /* {oa is an array of references} */ if (valuevftbl == componentvftbl) return 1; - asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues); + ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues); if ((base = classvalues.super_baseval) <= 0) /* an array of interface references */ return (valuevftbl->interfacetablelength > -base && valuevftbl->interfacetable[base] != NULL); - res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) - <= (unsigned) classvalues.super_diffval; + res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval) + <= (unsigned) classvalues.super_diffval); return res; - } - /* {a has dimension > 1} */ + } + + /* {oa has dimension > 1} */ /* {componentvftbl->arraydesc != NULL} */ /* check if o is an array */ + if ((valuedesc = valuevftbl->arraydesc) == NULL) return 0; + /* {o is an array} */ - return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc); + return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc); } @@ -379,7 +664,7 @@ s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o) if (valuevftbl == elementvftbl) return 1; - asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues); + ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues); if ((base = classvalues.super_baseval) <= 0) /* an array of interface references */ @@ -421,7 +706,7 @@ s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o) if (valuevftbl == elementvftbl) return 1; - asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues); + ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues); res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) <= (unsigned) classvalues.super_diffval; @@ -430,52 +715,55 @@ s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o) } -/******************** Function: builtin_new ********************************** +/* builtin_new ***************************************************************** - Creates a new instance of class c on the heap. - Return value: pointer to the object or NULL if no memory is - available - -*****************************************************************************/ + Creates a new instance of class c on the heap. -#define ALIGNMENT 3 -#define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1)) + Return value: pointer to the object or NULL if no memory is + available + +*******************************************************************************/ java_objectheader *builtin_new(classinfo *c) { java_objectheader *o; /* is the class loaded */ - if (!c->loaded) - if (!class_load(c)) - return NULL; + + assert(c->state & CLASS_LOADED); + + /* check if we can instantiate this class */ + + if (c->flags & ACC_ABSTRACT) { + *exceptionptr = + new_exception_utfmessage(string_java_lang_InstantiationError, + c->name); + return NULL; + } /* is the class linked */ - if (!c->linked) - if (!class_link(c)) + + if (!(c->state & CLASS_LINKED)) + if (!link_class(c)) return NULL; - if (!c->initialized) { + if (!(c->state & CLASS_INITIALIZED)) { +#if !defined(NDEBUG) if (initverbose) log_message_class("Initialize class (from builtin_new): ", c); +#endif - if (!class_init(c)) + if (!initialize_class(c)) return NULL; } -#ifdef SIZE_FROM_CLASSINFO - c->alignedsize = align_size(c->instancesize); - o = heap_allocate(c->alignedsize, true, c->finalizer); -#else o = heap_allocate(c->instancesize, true, c->finalizer); -#endif if (!o) return NULL; - memset(o, 0, c->instancesize); - o->vftbl = c->vftbl; + #if defined(USE_THREADS) && defined(NATIVE_THREADS) initObjectLock(o); #endif @@ -484,260 +772,273 @@ java_objectheader *builtin_new(classinfo *c) } -/********************** Function: builtin_newarray ************************** +/* builtin_newarray ************************************************************ - Creates an array with the given vftbl on the heap. + Creates an array with the given vftbl on the heap. This function + takes as class argument an array class. - Return value: pointer to the array or NULL if no memory is available + Return value: pointer to the array or NULL if no memory is available - CAUTION: The given vftbl must be the vftbl of the *array* class, - not of the element class. - -*****************************************************************************/ +*******************************************************************************/ -java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl) +java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass) { + arraydescriptor *desc; + s4 dataoffset; + s4 componentsize; + s4 actualsize; java_arrayheader *a; - arraydescriptor *desc; - s4 dataoffset; - s4 componentsize; - s4 actualsize; - desc = arrayvftbl->arraydesc; - dataoffset = desc->dataoffset; + desc = arrayclass->vftbl->arraydesc; + dataoffset = desc->dataoffset; componentsize = desc->componentsize; if (size < 0) { - *exceptionptr = - new_exception(string_java_lang_NegativeArraySizeException); + exceptions_throw_negativearraysizeexception(); return NULL; } -#ifdef SIZE_FROM_CLASSINFO - actualsize = align_size(dataoffset + size * componentsize); actualsize = dataoffset + size * componentsize; -#else - actualsize = 0; -#endif if (((u4) actualsize) < ((u4) size)) { /* overflow */ *exceptionptr = new_exception(string_java_lang_OutOfMemoryError); return NULL; } - a = heap_allocate(actualsize, - (desc->arraytype == ARRAYTYPE_OBJECT), - NULL); + a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL); if (!a) return NULL; - memset(a, 0, actualsize); + a->objheader.vftbl = arrayclass->vftbl; - a->objheader.vftbl = arrayvftbl; #if defined(USE_THREADS) && defined(NATIVE_THREADS) initObjectLock(&a->objheader); #endif + a->size = size; -#ifdef SIZE_FROM_CLASSINFO - a->alignedsize = actualsize; -#endif return a; } -/********************** Function: builtin_anewarray ************************* - - Creates an array of references to the given class type on the heap. +/* builtin_anewarray *********************************************************** - Return value: pointer to the array or NULL if no memory is available + Creates an array of references to the given class type on the heap. - XXX This function does not do The Right Thing, because it uses a - classinfo pointer at runtime. builtin_newarray should be used - instead. + Return value: pointer to the array or NULL if no memory is + available -*****************************************************************************/ +*******************************************************************************/ -java_objectarray *builtin_anewarray(s4 size, classinfo *component) +java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass) { + classinfo *arrayclass; + /* is class loaded */ - if (!component->loaded) - if (!class_load(component)) - return NULL; + + assert(componentclass->state & CLASS_LOADED); /* is class linked */ - if (!component->linked) - if (!class_link(component)) + + if (!(componentclass->state & CLASS_LINKED)) + if (!link_class(componentclass)) return NULL; - return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl); -} + arrayclass = class_array_of(componentclass, true); + + if (!arrayclass) + return NULL; + return (java_objectarray *) builtin_newarray(size, arrayclass); +} -/******************** Function: builtin_newarray_int *********************** - Creates an array of 32 bit Integers on the heap. +/* builtin_newarray_boolean **************************************************** - Return value: pointer to the array or NULL if no memory is available + Creates an array of bytes on the heap. The array is designated as + an array of booleans (important for casts) + + Return value: pointer to the array or NULL if no memory is + available -*****************************************************************************/ +*******************************************************************************/ -java_intarray *builtin_newarray_int(s4 size) +java_booleanarray *builtin_newarray_boolean(s4 size) { - return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl); + return (java_booleanarray *) + builtin_newarray(size, + primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass); } -/******************** Function: builtin_newarray_long *********************** +/* builtin_newarray_byte ******************************************************* - Creates an array of 64 bit Integers on the heap. + Creates an array of 8 bit Integers on the heap. - Return value: pointer to the array or NULL if no memory is available + Return value: pointer to the array or NULL if no memory is + available -*****************************************************************************/ +*******************************************************************************/ -java_longarray *builtin_newarray_long(s4 size) +java_bytearray *builtin_newarray_byte(s4 size) { - return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl); + return (java_bytearray *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass); } -/******************** function: builtin_newarray_float *********************** +/* builtin_newarray_char ******************************************************* - Creates an array of 32 bit IEEE floats on the heap. + Creates an array of characters on the heap. - Return value: pointer to the array or NULL if no memory is available + Return value: pointer to the array or NULL if no memory is + available -*****************************************************************************/ +*******************************************************************************/ -java_floatarray *builtin_newarray_float(s4 size) +java_chararray *builtin_newarray_char(s4 size) { - return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl); + return (java_chararray *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass); } -/******************** function: builtin_newarray_double *********************** +/* builtin_newarray_short ****************************************************** - Creates an array of 64 bit IEEE floats on the heap. + Creates an array of 16 bit Integers on the heap. - Return value: pointer to the array or NULL if no memory is available + Return value: pointer to the array or NULL if no memory is + available -*****************************************************************************/ +*******************************************************************************/ -java_doublearray *builtin_newarray_double(s4 size) +java_shortarray *builtin_newarray_short(s4 size) { - return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl); + return (java_shortarray *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass); } -/******************** function: builtin_newarray_byte *********************** +/* builtin_newarray_int ******************************************************** - Creates an array of 8 bit Integers on the heap. + Creates an array of 32 bit Integers on the heap. - Return value: pointer to the array or NULL if no memory is available + Return value: pointer to the array or NULL if no memory is + available -*****************************************************************************/ +*******************************************************************************/ -java_bytearray *builtin_newarray_byte(s4 size) +java_intarray *builtin_newarray_int(s4 size) { - return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl); + return (java_intarray *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass); } -/******************** function: builtin_newarray_char ************************ +/* builtin_newarray_long ******************************************************* - Creates an array of characters on the heap. + Creates an array of 64 bit Integers on the heap. - Return value: pointer to the array or NULL if no memory is available + Return value: pointer to the array or NULL if no memory is + available -*****************************************************************************/ +*******************************************************************************/ -java_chararray *builtin_newarray_char(s4 size) +java_longarray *builtin_newarray_long(s4 size) { - return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl); + return (java_longarray *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass); } -/******************** function: builtin_newarray_short *********************** +/* builtin_newarray_float ****************************************************** - Creates an array of 16 bit Integers on the heap. + Creates an array of 32 bit IEEE floats on the heap. - Return value: pointer to the array or NULL if no memory is available + Return value: pointer to the array or NULL if no memory is + available -*****************************************************************************/ +*******************************************************************************/ -java_shortarray *builtin_newarray_short(s4 size) +java_floatarray *builtin_newarray_float(s4 size) { - return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl); + return (java_floatarray *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass); } -/******************** function: builtin_newarray_boolean ************************ +/* builtin_newarray_double ***************************************************** - Creates an array of bytes on the heap. The array is designated as an array - of booleans (important for casts) - - Return value: pointer to the array or NULL if no memory is available + Creates an array of 64 bit IEEE floats on the heap. -*****************************************************************************/ + Return value: pointer to the array or NULL if no memory is + available -java_booleanarray *builtin_newarray_boolean(s4 size) +*******************************************************************************/ + +java_doublearray *builtin_newarray_double(s4 size) { - return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl); + return (java_doublearray *) + builtin_newarray(size, + primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass); } -/**************** function: builtin_nmultianewarray *************************** +/* builtin_multianewarray_intern *********************************************** - Creates a multi-dimensional array on the heap. The dimensions are passed in - an array of longs. + Creates a multi-dimensional array on the heap. The dimensions are + passed in an array of longs. - Arguments: - n............number of dimensions to create - arrayvftbl...vftbl of the array class - dims.........array containing the size of each dimension to create + Arguments: + n............number of dimensions to create + arrayvftbl...vftbl of the array class + dims.........array containing the size of each dimension to create - Return value: pointer to the array or NULL if no memory is available + Return value: pointer to the array or NULL if no memory is + available ******************************************************************************/ -java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims) -/* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */ +static java_arrayheader *builtin_multianewarray_intern(int n, + classinfo *arrayclass, + long *dims) { - s4 size, i; + s4 size; java_arrayheader *a; - vftbl_t *componentvftbl; + classinfo *componentclass; + s4 i; -/* utf_display(arrayclass->name); */ - -/* class_load(arrayclass); */ -/* class_link(arrayclass); */ - /* create this dimension */ + size = (s4) dims[0]; - a = builtin_newarray(size, arrayvftbl); -/* a = builtin_newarray(size, arrayclass->vftbl); */ + a = builtin_newarray(size, arrayclass); if (!a) return NULL; /* if this is the last dimension return */ + if (!--n) return a; - /* get the vftbl of the components to create */ - componentvftbl = arrayvftbl->arraydesc->componentvftbl; -/* component = arrayclass->vftbl->arraydesc; */ + /* get the class of the components to create */ + + componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class; - /* The verifier guarantees this. */ - /* if (!componentvftbl) */ - /* panic ("multianewarray with too many dimensions"); */ + /* The verifier guarantees that the dimension count is in the range. */ /* create the component arrays */ + for (i = 0; i < size; i++) { - java_arrayheader *ea = - builtin_nmultianewarray(n, componentvftbl, dims + 1); + java_arrayheader *ea = +#if defined(__MIPS__) && (SIZEOF_VOID_P == 4) + /* we save an s4 to a s8 slot, 8-byte aligned */ + + builtin_multianewarray_intern(n, componentclass, dims + 2); +#else + builtin_multianewarray_intern(n, componentclass, dims + 1); +#endif if (!ea) return NULL; @@ -749,6 +1050,41 @@ java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims } +/* builtin_multianewarray ****************************************************** + + Wrapper for builtin_multianewarray_intern which checks all + dimensions before we start allocating. + +******************************************************************************/ + +java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass, + long *dims) +{ + s4 i; + s4 size; + + /* check all dimensions before doing anything */ + + for (i = 0; i < n; i++) { +#if defined(__MIPS__) && (SIZEOF_VOID_P == 4) + /* we save an s4 to a s8 slot, 8-byte aligned */ + size = (s4) dims[i * 2]; +#else + size = (s4) dims[i]; +#endif + + if (size < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + } + + /* now call the real function */ + + return builtin_multianewarray_intern(n, arrayclass, dims); +} + + /***************************************************************************** METHOD LOGGING @@ -757,306 +1093,575 @@ java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims *****************************************************************************/ -u4 methodindent = 0; +#if !defined(NDEBUG) +static s4 methodindent = 0; +static u4 callcount = 0; java_objectheader *builtin_trace_exception(java_objectheader *xptr, methodinfo *m, void *pos, - s4 line, - s4 noindent) + s4 indent) { - if (!noindent) { - if (methodindent) - methodindent--; + char *logtext; + s4 logtextlen; + s4 dumpsize; + codeinfo *code; + + if (opt_verbosecall && indent) + methodindent--; + + /* calculate message length */ + + if (xptr) { + logtextlen = + strlen("Exception ") + + utf_strlen(xptr->vftbl->class->name); + + } else { + logtextlen = strlen("Some Throwable"); + } + + logtextlen += strlen(" thrown in "); + + if (m) { + logtextlen += + utf_strlen(m->class->name) + + strlen(".") + + utf_strlen(m->name) + + utf_strlen(m->descriptor) + + strlen("(NOSYNC,NATIVE"); + +#if SIZEOF_VOID_P == 8 + logtextlen += + strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 ("); +#else + logtextlen += strlen(")(0x12345678) at position 0x12345678 ("); +#endif + + if (m->class->sourcefile == NULL) + logtextlen += strlen(""); else - log_text("WARNING: unmatched methodindent--"); + logtextlen += utf_strlen(m->class->sourcefile); + + logtextlen += strlen(":65536)"); + + } else + logtextlen += strlen("call_java_method"); + + logtextlen += strlen("0"); + + /* allocate memory */ + + dumpsize = dump_size(); + + logtext = DMNEW(char, logtextlen); + + if (xptr) { + strcpy(logtext, "Exception "); + utf_strcat_classname(logtext, xptr->vftbl->class->name); + + } else { + strcpy(logtext, "Some Throwable"); } - if (opt_verbose || runverbose || verboseexception) { - if (xptr) { - printf("Exception "); - utf_display_classname(xptr->vftbl->class->name); - } else { - printf("Some Throwable"); - } - printf(" thrown in "); + strcat(logtext, " thrown in "); - if (m) { - utf_display_classname(m->class->name); - printf("."); - utf_display(m->name); - if (m->flags & ACC_SYNCHRONIZED) { - printf("(SYNC"); + if (m) { + utf_strcat_classname(logtext, m->class->name); + strcat(logtext, "."); + utf_strcat(logtext, m->name); + utf_strcat(logtext, m->descriptor); - } else{ - printf("(NOSYNC"); - } + if (m->flags & ACC_SYNCHRONIZED) + strcat(logtext, "(SYNC"); + else + strcat(logtext, "(NOSYNC"); + + if (m->flags & ACC_NATIVE) { + strcat(logtext, ",NATIVE"); + + code = m->code; - if (m->flags & ACC_NATIVE) { - printf(",NATIVE"); -#if POINTERSIZE == 8 - printf(")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos); +#if SIZEOF_VOID_P == 8 + sprintf(logtext + strlen(logtext), + ")(0x%016lx) at position 0x%016lx", + (ptrint) code->entrypoint, (ptrint) pos); #else - printf(")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos); + sprintf(logtext + strlen(logtext), + ")(0x%08x) at position 0x%08x", + (ptrint) code->entrypoint, (ptrint) pos); #endif - } else { -#if POINTERSIZE == 8 - printf(")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos); + } else { + + /* XXX preliminary: This should get the actual codeinfo */ + /* in which the exception happened. */ + code = m->code; + +#if SIZEOF_VOID_P == 8 + sprintf(logtext + strlen(logtext), + ")(0x%016lx) at position 0x%016lx (", + (ptrint) code->entrypoint, (ptrint) pos); #else - printf(")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos); + sprintf(logtext + strlen(logtext), + ")(0x%08x) at position 0x%08x (", + (ptrint) code->entrypoint, (ptrint) pos); #endif - if (m->class->sourcefile == NULL) { - printf(""); - } else { - utf_display(m->class->sourcefile); - } - printf(":%d)\n", line); - } + if (m->class->sourcefile == NULL) + strcat(logtext, ""); + else + utf_strcat(logtext, m->class->sourcefile); - } else - printf("call_java_method\n"); - fflush(stdout); - } + sprintf(logtext + strlen(logtext), ":%d)", 0); + } + + } else + strcat(logtext, "call_java_method"); + + log_text(logtext); + + /* release memory */ + + dump_release(dumpsize); return xptr; } +#endif /* !defined(NDEBUG) */ + +/* builtin_trace_args ********************************************************** + + XXX + +*******************************************************************************/ + +#if !defined(NDEBUG) #ifdef TRACE_ARGS_NUM -void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, +void builtin_trace_args(s8 a0, s8 a1, +#if TRACE_ARGS_NUM >= 4 + s8 a2, s8 a3, +#endif /* TRACE_ARGS_NUM >= 4 */ #if TRACE_ARGS_NUM >= 6 s8 a4, s8 a5, -#endif +#endif /* TRACE_ARGS_NUM >= 6 */ #if TRACE_ARGS_NUM == 8 s8 a6, s8 a7, -#endif +#endif /* TRACE_ARGS_NUM == 8 */ methodinfo *m) { - s4 i; - char logtext[MAXLOGTEXT]; - for (i = 0; i < methodindent; i++) - logtext[i] = '\t'; - - sprintf(logtext + methodindent, "called: "); - utf_sprint_classname(logtext + strlen(logtext), m->class->name); - sprintf(logtext + strlen(logtext), "."); - utf_sprint(logtext + strlen(logtext), m->name); - utf_sprint_classname(logtext + strlen(logtext), m->descriptor); - - if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC"); - if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE"); - if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED"); - if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC"); - if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL"); - if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED"); - if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE"); - if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT"); - if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE"); - if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE"); - if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT"); - + methoddesc *md; + char *logtext; + s4 logtextlen; + s4 dumpsize; + s4 i; + s4 pos; + + md = m->parseddesc; + + /* calculate message length */ + + logtextlen = + strlen("4294967295 ") + + strlen("-2147483647-") + /* INT_MAX should be sufficient */ + methodindent + + strlen("called: ") + + utf_strlen(m->class->name) + + strlen(".") + + utf_strlen(m->name) + + utf_strlen(m->descriptor) + + strlen(" SYNCHRONIZED") + strlen("(") + strlen(")"); + + /* add maximal argument length */ + + logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)"); + + /* allocate memory */ + + dumpsize = dump_size(); + + logtext = DMNEW(char, logtextlen); - sprintf(logtext + strlen(logtext), "("); + callcount++; - switch (m->paramcount) { + sprintf(logtext, "%10d ", callcount); + sprintf(logtext + strlen(logtext), "-%d-", methodindent); + + pos = strlen(logtext); + + for (i = 0; i < methodindent; i++) + logtext[pos++] = '\t'; + + strcpy(logtext + pos, "called: "); + + utf_strcat_classname(logtext, m->class->name); + strcat(logtext, "."); + utf_strcat(logtext, m->name); + utf_strcat(logtext, m->descriptor); + + if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC"); + if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE"); + if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED"); + if (m->flags & ACC_STATIC) strcat(logtext, " STATIC"); + if (m->flags & ACC_FINAL) strcat(logtext, " FINAL"); + if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED"); + if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE"); + if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT"); + if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE"); + if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE"); + if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT"); + + strcat(logtext, "("); + + /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */ + /* Only Arguments in integer Registers are passed correctly here */ + /* long longs spilled on Stack have an wrong offset of +4 */ + /* So preliminary Bugfix: Only pass 3 params at once to sprintf */ + /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */ + switch (md->paramcount) { case 0: break; -#if defined(__I386__) || defined(__POWERPC__) +#if SIZEOF_VOID_P == 4 case 1: - sprintf(logtext+strlen(logtext), "%llx", a0); + sprintf(logtext + strlen(logtext), + "0x%llx", + a0); break; case 2: - sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1); + sprintf(logtext + strlen(logtext), + "0x%llx, 0x%llx", + a0, a1); break; +#if TRACE_ARGS_NUM >= 4 case 3: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2); + sprintf(logtext + strlen(logtext), + "0x%llx, 0x%llx, 0x%llx", + a0, a1, a2); break; case 4: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx", - a0, a1, a2, a3); + sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx" + , a0, a1, a2); + sprintf(logtext + strlen(logtext), ", 0x%llx", a3); + break; +#endif /* TRACE_ARGS_NUM >= 4 */ #if TRACE_ARGS_NUM >= 6 case 5: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx", - a0, a1, a2, a3, a4); + sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx" + , a0, a1, a2); + sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4); break; + case 6: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx", - a0, a1, a2, a3, a4, a5); + sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx" + , a0, a1, a2); + sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx" + , a3, a4, a5); break; #endif /* TRACE_ARGS_NUM >= 6 */ #if TRACE_ARGS_NUM == 8 case 7: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx", - a0, a1, a2, a3, a4, a5, a6); + sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx" + , a0, a1, a2); + sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx" + , a3, a4, a5); + sprintf(logtext + strlen(logtext), ", 0x%llx", a6); break; case 8: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx", - a0, a1, a2, a3, a4, a5, a6, a7); + sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx" + , a0, a1, a2); + sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx" + , a3, a4, a5); + sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7); break; +#endif /* TRACE_ARGS_NUM == 8 */ default: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)", - a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8); - break; -#else /* TRACE_ARGS_NUM == 8 */ - default: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)", - a0, a1, a2, a3, a4, a5, m->paramcount - 6); +#if TRACE_ARGS_NUM == 2 + sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2); + +#elif TRACE_ARGS_NUM == 4 + sprintf(logtext + strlen(logtext), + "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)", + a0, a1, a2, a3, md->paramcount - 4); + +#elif TRACE_ARGS_NUM == 6 + sprintf(logtext + strlen(logtext), + "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)", + a0, a1, a2, a3, a4, a5, md->paramcount - 6); + +#elif TRACE_ARGS_NUM == 8 + sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx," + , a0, a1, a2); + sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx," + , a3, a4, a5); + sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)" + , a6, a7, md->paramcount - 8); +#endif break; -#endif /* TRACE_ARGS_NUM == 8 */ -#else /* defined(__I386__) || defined(__POWERPC__) */ + +#else /* SIZEOF_VOID_P == 4 */ + case 1: - sprintf(logtext+strlen(logtext), "%lx", a0); + sprintf(logtext + strlen(logtext), + "0x%lx", + a0); break; case 2: - sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx", + a0, a1); break; case 3: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx, 0x%lx", a0, a1, a2); break; case 4: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx", - a0, a1, a2, a3); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx, 0x%lx, 0x%lx", + a0, a1, a2, a3); break; #if TRACE_ARGS_NUM >= 6 case 5: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx", - a0, a1, a2, a3, a4); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx", + a0, a1, a2, a3, a4); break; case 6: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx", - a0, a1, a2, a3, a4, a5); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx", + a0, a1, a2, a3, a4, a5); break; #endif /* TRACE_ARGS_NUM >= 6 */ #if TRACE_ARGS_NUM == 8 case 7: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx", - a0, a1, a2, a3, a4, a5, a6); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx", + a0, a1, a2, a3, a4, a5, a6); break; case 8: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx", - a0, a1, a2, a3, a4, a5, a6, a7); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx", + a0, a1, a2, a3, a4, a5, a6, a7); break; #endif /* TRACE_ARGS_NUM == 8 */ default: #if TRACE_ARGS_NUM == 4 - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)", - a0, a1, a2, a3, m->paramcount - 4); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)", + a0, a1, a2, a3, md->paramcount - 4); #elif TRACE_ARGS_NUM == 6 - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)", - a0, a1, a2, a3, a4, a5, m->paramcount - 6); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)", + a0, a1, a2, a3, a4, a5, md->paramcount - 6); #elif TRACE_ARGS_NUM == 8 - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)", - a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8); + sprintf(logtext + strlen(logtext), + "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)", + a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8); #endif break; -#endif /* defined(__I386__) || defined(__POWERPC__) */ +#endif /* SIZEOF_VOID_P == 4 */ } - sprintf(logtext + strlen(logtext), ")"); + strcat(logtext, ")"); + log_text(logtext); + /* release memory */ + + dump_release(dumpsize); + methodindent++; } #endif +#endif /* !defined(NDEBUG) */ -void builtin_displaymethodstart(methodinfo *m) -{ - char logtext[MAXLOGTEXT]; - sprintf(logtext, " "); - sprintf(logtext + methodindent, "called: "); - utf_sprint(logtext + strlen(logtext), m->class->name); - sprintf(logtext + strlen(logtext), "."); - utf_sprint(logtext + strlen(logtext), m->name); - utf_sprint(logtext + strlen(logtext), m->descriptor); - - if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC"); - if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE"); - if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED"); - if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC"); - if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL"); - if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED"); - if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE"); - if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT"); - if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE"); - if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE"); - if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT"); +/* builtin_displaymethodstop *************************************************** - log_text(logtext); - methodindent++; -} + XXX +*******************************************************************************/ +#if !defined(NDEBUG) void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f) { - int i; - char logtext[MAXLOGTEXT]; - for (i = 0; i < methodindent; i++) - logtext[i] = '\t'; + methoddesc *md; + char *logtext; + s4 logtextlen; + s4 dumpsize; + s4 i; + s4 pos; + java_objectheader *o; + java_lang_String *s; + classinfo *c; + s4 len; + utf *u; + imm_union imu; + + md = m->parseddesc; + + /* calculate message length */ + + logtextlen = + strlen("4294967295 ") + + strlen("-2147483647-") + /* INT_MAX should be sufficient */ + methodindent + + strlen("finished: ") + + utf_strlen(m->class->name) + + strlen(".") + + utf_strlen(m->name) + + utf_strlen(m->descriptor) + + strlen(" SYNCHRONIZED") + strlen("(") + strlen(")"); + + /* add maximal argument length */ + + logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)"); + + /* allocate memory */ + + dumpsize = dump_size(); + + logtext = DMNEW(char, logtextlen); + + /* outdent the log message */ + if (methodindent) methodindent--; else log_text("WARNING: unmatched methodindent--"); - sprintf(logtext + methodindent, "finished: "); - utf_sprint_classname(logtext + strlen(logtext), m->class->name); - sprintf(logtext + strlen(logtext), "."); - utf_sprint(logtext + strlen(logtext), m->name); - utf_sprint_classname(logtext + strlen(logtext), m->descriptor); + /* generate the message */ + + sprintf(logtext, " "); + sprintf(logtext + strlen(logtext), "-%d-", methodindent); + + pos = strlen(logtext); + + for (i = 0; i < methodindent; i++) + logtext[pos++] = '\t'; + + strcpy(logtext + pos, "finished: "); + utf_strcat_classname(logtext, m->class->name); + strcat(logtext, "."); + utf_strcat(logtext, m->name); + utf_strcat(logtext, m->descriptor); - switch (m->returntype) { + switch (md->returntype.type) { case TYPE_INT: - sprintf(logtext + strlen(logtext), "->%d", (s4) l); + sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l); break; - case TYPE_LONG: -#if defined(__I386__) || defined(__POWERPC__) - sprintf(logtext + strlen(logtext), "->%lld", (s8) l); + case TYPE_LNG: +#if SIZEOF_VOID_P == 4 + sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l); #else - sprintf(logtext + strlen(logtext), "->%ld", (s8) l); + sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l); #endif break; - case TYPE_ADDRESS: -#if defined(__I386__) || defined(__POWERPC__) - sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l)); -#else - sprintf(logtext + strlen(logtext), "->%p", (u1*) l); -#endif + case TYPE_ADR: + sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l); + + /* check return argument for java.lang.Class or java.lang.String */ + + o = (java_objectheader *) (ptrint) l; + + if (o != NULL) { + if (o->vftbl->class == class_java_lang_String) { + /* get java.lang.String object and the length of the + string */ + + s= (java_lang_String *) (ptrint) l; + + len = strlen(", String = \"") + javastring_strlen(s) + + strlen("\""); + + /* realloc memory for string length */ + + DMREALLOC(logtext, char, logtextlen, logtextlen + len); + + /* convert to utf8 string and strcat it to the logtext */ + + u = javastring_toutf(s, false); + + strcat(logtext, ", String = \""); + utf_strcat(logtext, u); + strcat(logtext, "\""); + + } else { + if (o->vftbl->class == class_java_lang_Class) { + /* if the object returned is a java.lang.Class + cast it to classinfo structure and get the name + of the class */ + + c = (classinfo *) (ptrint) l; + + u = c->name; + + } else { + /* if the object returned is not a java.lang.String or + a java.lang.Class just print the name of the class */ + + u = o->vftbl->class->name; + } + + len = strlen(", Class = \"") + utf_strlen(u) + strlen("\""); + + /* realloc memory for string length */ + + DMREALLOC(logtext, char, logtextlen, logtextlen + len); + + /* strcat to the logtext */ + + strcat(logtext, ", Class = \""); + utf_strcat(logtext, u); + strcat(logtext, "\""); + } + } break; - case TYPE_FLOAT: - sprintf(logtext + strlen(logtext), "->%g", f); + case TYPE_FLT: + imu.f = f; + sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i); break; - case TYPE_DOUBLE: - sprintf(logtext + strlen(logtext), "->%g", d); + case TYPE_DBL: + imu.d = d; +#if SIZEOF_VOID_P == 4 + sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l); +#else + sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l); +#endif break; } + log_text(logtext); + + /* release memory */ + + dump_release(dumpsize); } +#endif /* !defined(NDEBUG) */ /**************************************************************************** @@ -1174,20 +1779,16 @@ void builtin_monitorenter(java_objectheader *o) #if defined(USE_THREADS) /* * Locks the class object - needed for static synchronized methods. - * The use_class_as_object call is needed in order to circumvent a - * possible deadlock with builtin_monitorenter called by another - * thread calling use_class_as_object. */ void builtin_staticmonitorenter(classinfo *c) { - use_class_as_object(c); - builtin_monitorenter(&c->header); + builtin_monitorenter(&c->object.header); } #endif #if defined(USE_THREADS) -void *builtin_monitorexit(java_objectheader *o) +void builtin_monitorexit(java_objectheader *o) { #if !defined(NATIVE_THREADS) int hashValue; @@ -1206,10 +1807,8 @@ void *builtin_monitorexit(java_objectheader *o) internal_unlock_mutex_for_object(o); --blockInts; - return o; #else monitorExit((threadobject *) THREADOBJECT, o); - return o; #endif } #endif @@ -1226,145 +1825,250 @@ void *builtin_monitorexit(java_objectheader *o) On some systems (eg. DEC ALPHA), integer division is not supported by the CPU. These helper functions implement the missing functionality. -******************************************************************************/ +******************************************************************************/ + +#if !SUPPORT_DIVISION +s4 builtin_idiv(s4 a, s4 b) +{ + s4 c; + + c = a / b; + + return c; +} + +s4 builtin_irem(s4 a, s4 b) +{ + s4 c; + + c = a % b; -s4 builtin_idiv(s4 a, s4 b) { return a / b; } -s4 builtin_irem(s4 a, s4 b) { return a % b; } + return c; +} +#endif /* !SUPPORT_DIVISION */ -/************** Functions for long arithmetics ******************************* +/* functions for long arithmetics ********************************************** - On systems where 64 bit Integers are not supported by the CPU, these - functions are needed. + On systems where 64 bit Integers are not supported by the CPU, + these functions are needed. ******************************************************************************/ - +#if !(SUPPORT_LONG && SUPPORT_LONG_ADD) s8 builtin_ladd(s8 a, s8 b) -{ +{ + s8 c; + #if U8_AVAILABLE - return a + b; + c = a + b; #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } -s8 builtin_lsub(s8 a, s8 b) -{ +s8 builtin_lsub(s8 a, s8 b) +{ + s8 c; + #if U8_AVAILABLE - return a - b; + c = a - b; #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } -s8 builtin_lmul(s8 a, s8 b) -{ +s8 builtin_lneg(s8 a) +{ + s8 c; + #if U8_AVAILABLE - return a * b; + c = -a; #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } +#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */ + + +#if !(SUPPORT_LONG && SUPPORT_LONG_MUL) +s8 builtin_lmul(s8 a, s8 b) +{ + s8 c; -s8 builtin_ldiv(s8 a, s8 b) -{ #if U8_AVAILABLE - return a / b; + c = a * b; #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } +#endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */ + + +#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) +s8 builtin_ldiv(s8 a, s8 b) +{ + s8 c; -s8 builtin_lrem(s8 a, s8 b) -{ #if U8_AVAILABLE - return a % b; + c = a / b; #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } -s8 builtin_lshl(s8 a, s4 b) -{ +s8 builtin_lrem(s8 a, s8 b) +{ + s8 c; + #if U8_AVAILABLE - return a << (b & 63); + c = a % b; #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } +#endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */ + + +#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) +s8 builtin_lshl(s8 a, s4 b) +{ + s8 c; -s8 builtin_lshr(s8 a, s4 b) -{ #if U8_AVAILABLE - return a >> (b & 63); + c = a << (b & 63); #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } -s8 builtin_lushr(s8 a, s4 b) -{ +s8 builtin_lshr(s8 a, s4 b) +{ + s8 c; + #if U8_AVAILABLE - return ((u8) a) >> (b & 63); + c = a >> (b & 63); #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } -s8 builtin_land(s8 a, s8 b) -{ +s8 builtin_lushr(s8 a, s4 b) +{ + s8 c; + #if U8_AVAILABLE - return a & b; + c = ((u8) a) >> (b & 63); #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } +#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */ + + +#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) +s8 builtin_land(s8 a, s8 b) +{ + s8 c; -s8 builtin_lor(s8 a, s8 b) -{ #if U8_AVAILABLE - return a | b; + c = a & b; #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } -s8 builtin_lxor(s8 a, s8 b) -{ +s8 builtin_lor(s8 a, s8 b) +{ + s8 c; + #if U8_AVAILABLE - return a ^ b; + c = a | b; #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } -s8 builtin_lneg(s8 a) -{ +s8 builtin_lxor(s8 a, s8 b) +{ + s8 c; + #if U8_AVAILABLE - return -a; + c = a ^ b; #else - return builtin_i2l(0); + c = builtin_i2l(0); #endif + + return c; } +#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */ -s4 builtin_lcmp(s8 a, s8 b) + +#if !(SUPPORT_LONG && SUPPORT_LONG_CMP) +s4 builtin_lcmp(s8 a, s8 b) { #if U8_AVAILABLE - if (a < b) return -1; - if (a > b) return 1; + if (a < b) + return -1; + + if (a > b) + return 1; + return 0; #else return 0; #endif } +#endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */ + + +/* functions for unsupported floating instructions ****************************/ + +/* used to convert FLT_xxx defines into float values */ + +static inline float intBitsToFloat(s4 i) +{ + imm_union imb; + + imb.i = i; + return imb.f; +} +/* used to convert DBL_xxx defines into double values */ +static inline float longBitsToDouble(s8 l) +{ + imm_union imb; + imb.l = l; + return imb.d; +} -/*********** Functions for floating point operations *************************/ +#if !SUPPORT_FLOAT float builtin_fadd(float a, float b) { if (isnanf(a)) return intBitsToFloat(FLT_NAN); @@ -1417,25 +2121,64 @@ float builtin_fmul(float a, float b) } +/* builtin_ddiv **************************************************************** + + Implementation as described in VM Spec. + +*******************************************************************************/ + float builtin_fdiv(float a, float b) { - if (finitef(a) && finitef(b)) { - if (b != 0) + if (finitef(a)) { + if (finitef(b)) { + /* If neither value1' nor value2' is NaN, the sign of the result */ + /* is positive if both values have the same sign, negative if the */ + /* values have different signs. */ + return a / b; - else { - if (a > 0) + + } else { + if (isnanf(b)) { + /* If either value1' or value2' is NaN, the result is NaN. */ + + return intBitsToFloat(FLT_NAN); + + } else { + /* Division of a finite value by an infinity results in a */ + /* signed zero, with the sign-producing rule just given. */ + + /* is sign equal? */ + + if (copysignf(1.0, a) == copysignf(1.0, b)) + return 0.0; + else + return -0.0; + } + } + + } else { + if (isnanf(a)) { + /* If either value1' or value2' is NaN, the result is NaN. */ + + return intBitsToFloat(FLT_NAN); + + } else if (finitef(b)) { + /* Division of an infinity by a finite value results in a signed */ + /* infinity, with the sign-producing rule just given. */ + + /* is sign equal? */ + + if (copysignf(1.0, a) == copysignf(1.0, b)) return intBitsToFloat(FLT_POSINF); - else if (a < 0) + else return intBitsToFloat(FLT_NEGINF); - } - } - return intBitsToFloat(FLT_NAN); -} + } else { + /* Division of an infinity by an infinity results in NaN. */ -float builtin_frem(float a, float b) -{ - return fmodf(a, b); + return intBitsToFloat(FLT_NAN); + } + } } @@ -1447,8 +2190,10 @@ float builtin_fneg(float a) else return copysignf(a, -copysignf(1.0, a)); } } +#endif /* !SUPPORT_FLOAT */ +#if !SUPPORT_FLOAT || defined(ENABLE_INTRP) s4 builtin_fcmpl(float a, float b) { if (isnanf(a)) return -1; @@ -1475,11 +2220,18 @@ s4 builtin_fcmpg(float a, float b) if (a == b) return 0; return -1; } +#endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */ + +float builtin_frem(float a, float b) +{ + return fmodf(a, b); +} -/************************* Functions for doubles ****************************/ +/* functions for unsupported double instructions ******************************/ +#if !SUPPORT_DOUBLE double builtin_dadd(double a, double b) { if (isnan(a)) return longBitsToDouble(DBL_NAN); @@ -1527,62 +2279,100 @@ double builtin_dmul(double a, double b) } +/* builtin_ddiv **************************************************************** + + Implementation as described in VM Spec. + +*******************************************************************************/ + double builtin_ddiv(double a, double b) { if (finite(a)) { if (finite(b)) { + /* If neither value1' nor value2' is NaN, the sign of the result */ + /* is positive if both values have the same sign, negative if the */ + /* values have different signs. */ + return a / b; } else { - if (isnan(b)) + if (isnan(b)) { + /* If either value1' or value2' is NaN, the result is NaN. */ + return longBitsToDouble(DBL_NAN); - else - return copysign(0.0, b); + + } else { + /* Division of a finite value by an infinity results in a */ + /* signed zero, with the sign-producing rule just given. */ + + /* is sign equal? */ + + if (copysign(1.0, a) == copysign(1.0, b)) + return 0.0; + else + return -0.0; + } } } else { - if (finite(b)) { - if (a > 0) + if (isnan(a)) { + /* If either value1' or value2' is NaN, the result is NaN. */ + + return longBitsToDouble(DBL_NAN); + + } else if (finite(b)) { + /* Division of an infinity by a finite value results in a signed */ + /* infinity, with the sign-producing rule just given. */ + + /* is sign equal? */ + + if (copysign(1.0, a) == copysign(1.0, b)) return longBitsToDouble(DBL_POSINF); - else if (a < 0) + else return longBitsToDouble(DBL_NEGINF); - } else + } else { + /* Division of an infinity by an infinity results in NaN. */ + return longBitsToDouble(DBL_NAN); + } } - -/* if (finite(a) && finite(b)) { */ -/* if (b != 0) */ -/* return a / b; */ -/* else { */ -/* if (a > 0) */ -/* return longBitsToDouble(DBL_POSINF); */ -/* else if (a < 0) */ -/* return longBitsToDouble(DBL_NEGINF); */ -/* } */ -/* } */ - - /* keep compiler happy */ - return 0; } -double builtin_drem(double a, double b) -{ - return fmod(a, b); -} +/* builtin_dneg **************************************************************** + + Implemented as described in VM Spec. +*******************************************************************************/ double builtin_dneg(double a) { - if (isnan(a)) return a; - else { - if (finite(a)) return -a; - else return copysign(a, -copysign(1.0, a)); + if (isnan(a)) { + /* If the operand is NaN, the result is NaN (recall that NaN has no */ + /* sign). */ + + return a; + + } else { + if (finite(a)) { + /* If the operand is a zero, the result is the zero of opposite */ + /* sign. */ + + return -a; + + } else { + /* If the operand is an infinity, the result is the infinity of */ + /* opposite sign. */ + + return copysign(a, -copysign(1.0, a)); + } } } +#endif /* !SUPPORT_DOUBLE */ +#if !SUPPORT_DOUBLE || defined(ENABLE_INTRP) s4 builtin_dcmpl(double a, double b) { if (isnan(a)) return -1; @@ -1609,10 +2399,18 @@ s4 builtin_dcmpg(double a, double b) if (a == b) return 0; return -1; } +#endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */ + + +double builtin_drem(double a, double b) +{ + return fmod(a, b); +} -/*********************** Conversion operations ****************************/ +/* conversion operations ******************************************************/ +#if 0 s8 builtin_i2l(s4 i) { #if U8_AVAILABLE @@ -1625,31 +2423,36 @@ s8 builtin_i2l(s4 i) #endif } +s4 builtin_l2i(s8 l) +{ +#if U8_AVAILABLE + return (s4) l; +#else + return l.low; +#endif +} +#endif + +#if !(SUPPORT_FLOAT && SUPPORT_I2F) float builtin_i2f(s4 a) { float f = (float) a; return f; } +#endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */ +#if !(SUPPORT_DOUBLE && SUPPORT_I2D) double builtin_i2d(s4 a) { double d = (double) a; return d; } +#endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */ -s4 builtin_l2i(s8 l) -{ -#if U8_AVAILABLE - return (s4) l; -#else - return l.low; -#endif -} - - +#if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) float builtin_l2f(s8 a) { #if U8_AVAILABLE @@ -1659,8 +2462,10 @@ float builtin_l2f(s8 a) return 0.0; #endif } +#endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */ +#if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) double builtin_l2d(s8 a) { #if U8_AVAILABLE @@ -1670,12 +2475,17 @@ double builtin_l2d(s8 a) return 0.0; #endif } +#endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */ +#if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) s4 builtin_f2i(float a) { + s4 i; + + i = builtin_d2i((double) a); - return builtin_d2i((double) a); + return i; /* float f; @@ -1693,12 +2503,17 @@ s4 builtin_f2i(float a) return 2147483647; return (-2147483648); */ } +#endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */ +#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) s8 builtin_f2l(float a) { + s8 l; + + l = builtin_d2l((double) a); - return builtin_d2l((double) a); + return l; /* float f; @@ -1716,20 +2531,10 @@ s8 builtin_f2l(float a) return 9223372036854775807L; return (-9223372036854775808L); */ } +#endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */ -double builtin_f2d(float a) -{ - if (finitef(a)) return (double) a; - else { - if (isnanf(a)) - return longBitsToDouble(DBL_NAN); - else - return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) ); - } -} - - +#if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) s4 builtin_d2i(double a) { double d; @@ -1748,8 +2553,10 @@ s4 builtin_d2i(double a) return 2147483647; return (-2147483647-1); } +#endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */ +#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) s8 builtin_d2l(double a) { double d; @@ -1768,8 +2575,21 @@ s8 builtin_d2l(double a) return 9223372036854775807LL; return (-9223372036854775807LL-1); } +#endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */ +#if !(SUPPORT_FLOAT && SUPPORT_DOUBLE) +double builtin_f2d(float a) +{ + if (finitef(a)) return (double) a; + else { + if (isnanf(a)) + return longBitsToDouble(DBL_NAN); + else + return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) ); + } +} + float builtin_d2f(double a) { if (finite(a)) @@ -1781,41 +2601,25 @@ float builtin_d2f(double a) return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a)); } } +#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */ -/* used to convert FLT_xxx defines into float values */ - -inline float intBitsToFloat(s4 i) -{ - imm_union imb; - - imb.i = i; - return imb.f; -} - - -/* used to convert DBL_xxx defines into double values */ - -inline float longBitsToDouble(s8 l) -{ - imm_union imb; +/* builtin_clone_array ********************************************************* - imb.l = l; - return imb.d; -} + Wrapper function for cloning arrays. +*******************************************************************************/ java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o) { - return (java_arrayheader *) - Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o); -} + java_arrayheader *ah; + java_lang_Cloneable *c; + c = (java_lang_Cloneable *) o; -s4 builtin_dummy() -{ - panic("Internal error: builtin_dummy called (native function is missing)"); - return 0; /* for the compiler */ + ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c); + + return ah; } @@ -1826,50 +2630,13 @@ s4 builtin_dummy() *******************************************************************************/ #if defined(USE_THREADS) && defined(NATIVE_THREADS) -java_objectheader **builtin_asm_get_exceptionptrptr() +java_objectheader **builtin_asm_get_exceptionptrptr(void) { return builtin_get_exceptionptrptr(); } #endif -methodinfo *builtin_asm_get_threadrootmethod() -{ - return *threadrootmethod; -} - - -inline void* builtin_asm_get_stackframeinfo() -{ -/*log_text("builtin_asm_get_stackframeinfo()");*/ -#if defined(USE_THREADS) && defined(NATIVE_THREADS) - return &THREADINFO->_stackframeinfo; -#else -#if defined(__GNUC__) -#warning FIXME FOR OLD THREAD IMPL (jowenn) -#endif - return &_thread_nativestackframeinfo; /* no threading, at least no native*/ -#endif -} - -stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) { -/* stacktraceelement *el;*/ - size_t s; - s=(end-begin); - /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/ - *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0); -#if 0 - *el=MNEW(stacktraceelement,s+1); /*GC*/ -#endif - memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement)); - (*el)[s].method=0; -#if defined(__GNUC__) -#warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that -#endif - (*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 */ - return *el; -} - /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where @@ -1881,4 +2648,5 @@ stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelem * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */