X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fbuiltin.c;h=544ae21781d730c93435beaa0001b140407fcf63;hb=9f859ad50d3d5d98c185d40b86b2179bc4dc9aeb;hp=1a65b9b07ebfd5e5f89457f91e0a0464d2cbbc4c;hpb=a4f97e30fa4a6f2c5eecad4b8bdae49845832015;p=cacao.git diff --git a/src/vm/builtin.c b/src/vm/builtin.c index 1a65b9b07..544ae2178 100644 --- a/src/vm/builtin.c +++ b/src/vm/builtin.c @@ -1,9 +1,9 @@ /* 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, 2007 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,16 +19,8 @@ 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. - - Contact: cacao@complang.tuwien.ac.at - - Authors: Reinhard Grafl - Andreas Krall - Mark Probst - - Changes: Christian Thalinger + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. Contains C functions for JavaVM Instructions that cannot be translated to machine language directly. Consequently, the @@ -36,16 +28,16 @@ calls instead of machine instructions, using the C calling convention. - $Id: builtin.c 3985 2005-12-22 11:06:29Z twisti $ - */ #include "config.h" #include +#include #include #include +#include #include "vm/types.h" @@ -53,42 +45,61 @@ #include "md-abi.h" #include "fdlibm/fdlibm.h" +#if defined(__CYGWIN__) && defined(Bias) +# undef Bias +#endif -#include "mm/boehm.h" +#include "mm/gc-common.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) -# if defined(NATIVE_THREADS) -# include "threads/native/threads.h" -# else -# include "threads/green/threads.h" -# include "threads/green/locks.h" -# endif + +#include "native/jni.h" +#include "native/llni.h" +#include "native/include/java_lang_String.h" +#include "native/include/java_lang_Throwable.h" + +#include "threads/lock-common.h" +#if defined(ENABLE_THREADS) +#include "threads/native/threads.h" +#else +#include "threads/none/threads.h" #endif #include "toolbox/logging.h" #include "toolbox/util.h" + +#include "vm/array.h" #include "vm/builtin.h" -#include "vm/class.h" +#include "vm/cycles-stats.h" #include "vm/exceptions.h" #include "vm/global.h" #include "vm/initialize.h" -#include "vm/loader.h" -#include "vm/options.h" +#include "vm/primitive.h" #include "vm/stringlocal.h" + #include "vm/jit/asmpart.h" -#include "vm/jit/patcher.h" +#include "vmcore/class.h" +#include "vmcore/linker.h" +#include "vmcore/loader.h" +#include "vmcore/options.h" +#include "vmcore/rt-timing.h" + +#if defined(ENABLE_VMLOG) +#include +#endif + +#if defined(ENABLE_DEBUG_FILTER) +# include "vm/jit/show.h" +#endif /* include builtin tables *****************************************************/ #include "vm/builtintable.inc" +CYCLES_STATS_DECLARE(builtin_new ,100,5) +CYCLES_STATS_DECLARE(builtin_overhead , 80,1) + /* builtintable_init *********************************************************** Parse the descriptors of builtin functions and create the parsed @@ -98,12 +109,9 @@ static bool builtintable_init(void) { - descriptor_pool *descpool; - s4 dumpsize; - utf *descriptor; - s4 entries_internal; - s4 entries_automatic; - s4 i; + descriptor_pool *descpool; + s4 dumpsize; + builtintable_entry *bte; /* mark start of dump memory area */ @@ -121,23 +129,14 @@ static bool builtintable_init(void) 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++) { + for (bte = builtintable_internal; bte->fp != NULL; bte++) { /* create a utf8 string from descriptor */ - descriptor = utf_new_char(builtintable_internal[i].descriptor); + bte->descriptor = utf_new_char(bte->cdescriptor); - if (!descriptor_pool_add(descpool, descriptor, NULL)) { + if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) { /* release dump area */ dump_release(dumpsize); @@ -146,16 +145,22 @@ static bool builtintable_init(void) } } - for (i = 0; i < entries_automatic; i++) { - /* create a utf8 string from descriptor */ + for (bte = builtintable_automatic; bte->fp != NULL; bte++) { + bte->descriptor = utf_new_char(bte->cdescriptor); - descriptor = utf_new_char(builtintable_automatic[i].descriptor); + if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) { + dump_release(dumpsize); + return false; + } + } - if (!descriptor_pool_add(descpool, descriptor, NULL)) { - /* release dump area */ + for (bte = builtintable_function; bte->fp != NULL; bte++) { + bte->classname = utf_new_char(bte->cclassname); + bte->name = utf_new_char(bte->cname); + bte->descriptor = utf_new_char(bte->cdescriptor); + if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) { dump_release(dumpsize); - return false; } } @@ -168,30 +173,31 @@ static bool builtintable_init(void) 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); + /* Now parse all descriptors. NOTE: builtin-functions are treated + like static methods (no `this' pointer). */ - /* 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 (bte = builtintable_internal; bte->fp != NULL; bte++) { + bte->md = + descriptor_pool_parse_method_descriptor(descpool, + bte->descriptor, + ACC_STATIC | ACC_METHOD_BUILTIN, + 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) */ + for (bte = builtintable_automatic; bte->fp != NULL; bte++) { + bte->md = + descriptor_pool_parse_method_descriptor(descpool, + bte->descriptor, + ACC_STATIC | ACC_METHOD_BUILTIN, + NULL); + } - builtintable_automatic[i].md = - descriptor_pool_parse_method_descriptor(descpool, descriptor, - ACC_STATIC, NULL); + for (bte = builtintable_function; bte->fp != NULL; bte++) { + bte->md = + descriptor_pool_parse_method_descriptor(descpool, + bte->descriptor, + ACC_STATIC | ACC_METHOD_BUILTIN, + NULL); } /* release dump area */ @@ -241,7 +247,7 @@ static void builtintable_sort_automatic(void) /* builtin_init **************************************************************** - XXX + Initialize the global table of builtin functions. *******************************************************************************/ @@ -269,11 +275,11 @@ bool builtin_init(void) builtintable_entry *builtintable_get_internal(functionptr fp) { - s4 i; + builtintable_entry *bte; - for (i = 0; builtintable_internal[i].fp != NULL; i++) { - if (builtintable_internal[i].fp == fp) - return &builtintable_internal[i]; + for (bte = builtintable_internal; bte->fp != NULL; bte++) { + if (bte->fp == fp) + return bte; } return NULL; @@ -317,100 +323,102 @@ builtintable_entry *builtintable_get_automatic(s4 opcode) } -/***************************************************************************** - TYPE CHECKS -*****************************************************************************/ - +/* builtintable_replace_function *********************************************** + XXX -/*************** internal function: builtin_isanysubclass ********************* +*******************************************************************************/ - Checks a subclass relation between two classes. Implemented interfaces - are interpreted as super classes. - Return value: 1 ... sub is subclass of super - 0 ... otherwise - -*****************************************************************************/ -s4 builtin_isanysubclass(classinfo *sub, classinfo *super) +#if defined(ENABLE_JIT) +bool builtintable_replace_function(void *iptr_) { - s4 res; - castinfo classvalues; + constant_FMIref *mr; + builtintable_entry *bte; + instruction *iptr; - if (sub == super) - return 1; + iptr = (instruction *) iptr_; /* twisti will kill me ;) */ - if (super->flags & ACC_INTERFACE) { - res = (sub->vftbl->interfacetablelength > super->index) && - (sub->vftbl->interfacetable[-super->index] != NULL); + /* get name and descriptor of the function */ - } else { - asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues); + switch (iptr->opc) { + case ICMD_INVOKESTATIC: + /* The instruction MUST be resolved, otherwise we run into + lazy loading troubles. Anyway, we should/can only replace + very VM-close functions. */ - res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <= - (u4) classvalues.super_diffval; - } + if (INSTRUCTION_IS_UNRESOLVED(iptr)) + return false; - return res; -} + mr = iptr->sx.s23.s3.fmiref; + break; + default: + return false; + } -s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super) -{ - s4 res; - s4 base; - castinfo classvalues; + /* search the function table */ - if (sub == super) - return 1; + for (bte = builtintable_function; bte->fp != NULL; bte++) { + if ((METHODREF_CLASSNAME(mr) == bte->classname) && + (mr->name == bte->name) && + (mr->descriptor == bte->descriptor)) { - asm_getclassvalues_atomic(super, sub, &classvalues); + /* set the values in the instruction */ - if ((base = classvalues.super_baseval) <= 0) { - /* super is an interface */ - res = (sub->interfacetablelength > -base) && - (sub->interfacetable[base] != NULL); - } else { - res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) - <= (u4) classvalues.super_diffval; + iptr->opc = bte->opcode; + iptr->sx.s23.s3.bte = bte; + if (bte->checkexception) + iptr->flags.bits |= INS_FLAG_CHECK; + else + iptr->flags.bits &= ~INS_FLAG_CHECK; + + return true; + } } - return res; + return false; } +#endif /* defined(ENABLE_JIT) */ + + +/***************************************************************************** + TYPE CHECKS +*****************************************************************************/ +/* builtin_instanceof ********************************************************** -/****************** function: builtin_instanceof ***************************** + Checks if an object is an instance of some given class (or subclass + of that class). If class is an interface, checks if the interface + is implemented. - Checks if an object is an instance of some given class (or subclass of - that class). If class is an interface, checks if the interface is - implemented. - Return value: 1 ... obj is an instance of class or implements the interface - 0 ... otherwise or if obj == NULL + Return value: 1 ... o is an instance of class or implements the interface + 0 ... otherwise or if o == NULL -*****************************************************************************/ +*******************************************************************************/ -s4 builtin_instanceof(java_objectheader *obj, classinfo *class) +s4 builtin_instanceof(java_handle_t *o, classinfo *class) { - if (!obj) + if (o == NULL) return 0; - return builtin_isanysubclass(obj->vftbl->class, class); + return class_isanysubclass(o->vftbl->class, class); } -/**************** function: builtin_checkcast ******************************* +/* builtin_checkcast *********************************************************** - The same as builtin_instanceof except that 1 is returned when - obj == NULL + The same as builtin_instanceof except that 1 is returned when o == + NULL. -****************************************************************************/ +*******************************************************************************/ -s4 builtin_checkcast(java_objectheader *obj, classinfo *class) +s4 builtin_checkcast(java_handle_t *o, classinfo *class) { - if (obj == NULL) + if (o == NULL) return 1; - if (builtin_isanysubclass(obj->vftbl->class, class)) + if (class_isanysubclass(o->vftbl->class, class)) return 1; return 0; @@ -448,8 +456,8 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc, (target->elementvftbl->baseval == 1)) return 1; - return builtin_isanysubclass_vftbl(desc->elementvftbl, - target->elementvftbl); + return class_isanysubclass(desc->elementvftbl->class, + target->elementvftbl->class); } if (desc->dimension < target->dimension) @@ -457,8 +465,8 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc, /* {desc has higher dimension than target} */ - return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, - target->elementvftbl); + return class_isanysubclass(pseudo_class_Arraystub, + target->elementvftbl->class); } @@ -475,36 +483,43 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc, *******************************************************************************/ -s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass) +s4 builtin_arraycheckcast(java_handle_t *o, classinfo *targetclass) { arraydescriptor *desc; - if (!o) + if (o == NULL) return 1; - if ((desc = o->vftbl->arraydesc) == NULL) + desc = o->vftbl->arraydesc; + + if (desc == NULL) return 0; return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc); } -s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass) +s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass) { - if (!o) + if (o == NULL) return 0; return builtin_arraycheckcast(o, targetclass); } -/************************** exception functions ******************************* +/* builtin_throw_exception ***************************************************** -******************************************************************************/ + Sets the exceptionptr with the thrown exception and prints some + debugging information. Called from asm_vm_call_method. + +*******************************************************************************/ -java_objectheader *builtin_throw_exception(java_objectheader *xptr) +void *builtin_throw_exception(java_handle_t *xptr) { +#if !defined(NDEBUG) java_lang_Throwable *t; + java_lang_String *s; char *logtext; s4 logtextlen; s4 dumpsize; @@ -512,18 +527,27 @@ java_objectheader *builtin_throw_exception(java_objectheader *xptr) if (opt_verbose) { t = (java_lang_Throwable *) xptr; + /* get detail message */ + if (t) + LLNI_field_get_ref(t, detailMessage, s); + /* calculate message length */ logtextlen = strlen("Builtin exception thrown: ") + strlen("0"); if (t) { logtextlen += - utf_strlen(xptr->vftbl->class->name) + - strlen(": ") + - javastring_strlen(t->detailMessage); - - } else + utf_bytes(xptr->vftbl->class->name); + if (s) { + logtextlen += strlen(": ") + + u2_utflength(LLNI_field_direct(s, value)->data + + LLNI_field_direct(s, offset), + LLNI_field_direct(s,count)); + } + } + else { logtextlen += strlen("(nil)"); + } /* allocate memory */ @@ -534,16 +558,15 @@ java_objectheader *builtin_throw_exception(java_objectheader *xptr) strcpy(logtext, "Builtin exception thrown: "); if (t) { - utf_sprint_classname(logtext + strlen(logtext), - xptr->vftbl->class->name); + utf_cat_classname(logtext, xptr->vftbl->class->name); - if (t->detailMessage) { + if (s) { char *buf; - buf = javastring_tochar((java_objectheader *) t->detailMessage); + buf = javastring_tochar((java_handle_t *) s); strcat(logtext, ": "); strcat(logtext, buf); - MFREE(buf, char, strlen(buf)); + MFREE(buf, char, strlen(buf) + 1); } } else { @@ -556,12 +579,17 @@ java_objectheader *builtin_throw_exception(java_objectheader *xptr) dump_release(dumpsize); } +#endif /* !defined(NDEBUG) */ - *exceptionptr = xptr; + /* actually set the exception */ - return xptr; -} + exceptions_set_exception(xptr); + + /* Return a NULL pointer. This is required for vm_call_method to + check for an exception. This is for convenience. */ + return NULL; +} /* builtin_canstore ************************************************************ @@ -569,20 +597,21 @@ java_objectheader *builtin_throw_exception(java_objectheader *xptr) Checks, if an object can be stored in an array. Return value: 1 ... possible - 0 ... otherwise + 0 ... otherwise (throws an ArrayStoreException) *******************************************************************************/ -s4 builtin_canstore(java_objectarray *oa, java_objectheader *o) +s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o) { arraydescriptor *desc; arraydescriptor *valuedesc; vftbl_t *componentvftbl; vftbl_t *valuevftbl; - s4 base; - castinfo classvalues; + int32_t baseval; + uint32_t diffval; + int result; - if (!o) + if (o == NULL) return 1; /* The following is guaranteed (by verifier checks): @@ -595,54 +624,69 @@ s4 builtin_canstore(java_objectarray *oa, java_objectheader *o) desc = oa->header.objheader.vftbl->arraydesc; componentvftbl = desc->componentvftbl; valuevftbl = o->vftbl; + valuedesc = valuevftbl->arraydesc; if ((desc->dimension - 1) == 0) { - s4 res; - /* {oa is a one-dimensional array} */ /* {oa is an array of references} */ if (valuevftbl == componentvftbl) return 1; - asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues); + LOCK_MONITOR_ENTER(linker_classrenumber_lock); + + baseval = componentvftbl->baseval; - if ((base = classvalues.super_baseval) <= 0) + if (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); - return res; - } + result = ((valuevftbl->interfacetablelength > -baseval) && + (valuevftbl->interfacetable[baseval] != NULL)); + } + else { + diffval = valuevftbl->baseval - componentvftbl->baseval; + result = diffval <= (uint32_t) componentvftbl->diffval; + } - /* {oa has dimension > 1} */ - /* {componentvftbl->arraydesc != NULL} */ + LOCK_MONITOR_EXIT(linker_classrenumber_lock); + } + else if (valuedesc == NULL) { + /* {oa has dimension > 1} */ + /* {componentvftbl->arraydesc != NULL} */ - /* check if o is an array */ + /* check if o is an array */ - if ((valuedesc = valuevftbl->arraydesc) == NULL) return 0; + } + else { + /* {o is an array} */ + + result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc); + } - /* {o is an array} */ + /* if not possible, throw an exception */ - return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc); + if (result == 0) + exceptions_throw_arraystoreexception(); + + /* return result */ + + return result; } /* This is an optimized version where a is guaranteed to be one-dimensional */ -s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o) +s4 builtin_canstore_onedim (java_handle_objectarray_t *a, java_handle_t *o) { arraydescriptor *desc; - vftbl_t *elementvftbl; - vftbl_t *valuevftbl; - s4 res; - int base; - castinfo classvalues; + vftbl_t *elementvftbl; + vftbl_t *valuevftbl; + int32_t baseval; + uint32_t diffval; + int result; - if (!o) return 1; + if (o == NULL) + return 1; /* The following is guaranteed (by verifier checks): * @@ -661,30 +705,37 @@ s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o) if (valuevftbl == elementvftbl) return 1; - asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues); + LOCK_MONITOR_ENTER(linker_classrenumber_lock); - if ((base = classvalues.super_baseval) <= 0) + baseval = elementvftbl->baseval; + + if (baseval <= 0) { /* an array of interface references */ - return (valuevftbl->interfacetablelength > -base && - valuevftbl->interfacetable[base] != NULL); + result = ((valuevftbl->interfacetablelength > -baseval) && + (valuevftbl->interfacetable[baseval] != NULL)); + } + else { + diffval = valuevftbl->baseval - elementvftbl->baseval; + result = diffval <= (uint32_t) elementvftbl->diffval; + } - res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) - <= (unsigned) classvalues.super_diffval; + LOCK_MONITOR_EXIT(linker_classrenumber_lock); - return res; + return result; } /* This is an optimized version where a is guaranteed to be a * one-dimensional array of a class type */ -s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o) +s4 builtin_canstore_onedim_class(java_handle_objectarray_t *a, java_handle_t *o) { - vftbl_t *elementvftbl; - vftbl_t *valuevftbl; - s4 res; - castinfo classvalues; + vftbl_t *elementvftbl; + vftbl_t *valuevftbl; + uint32_t diffval; + int result; - if (!o) return 1; + if (o == NULL) + return 1; /* The following is guaranteed (by verifier checks): * @@ -703,12 +754,14 @@ s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o) if (valuevftbl == elementvftbl) return 1; - asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues); + LOCK_MONITOR_ENTER(linker_classrenumber_lock); + + diffval = valuevftbl->baseval - elementvftbl->baseval; + result = diffval <= (uint32_t) elementvftbl->diffval; - res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) - <= (unsigned) classvalues.super_diffval; + LOCK_MONITOR_EXIT(linker_classrenumber_lock); - return res; + return result; } @@ -721,9 +774,18 @@ s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o) *******************************************************************************/ -java_objectheader *builtin_new(classinfo *c) +java_handle_t *builtin_new(classinfo *c) { - java_objectheader *o; + java_object_t *o; +#if defined(ENABLE_RT_TIMING) + struct timespec time_start, time_end; +#endif +#if defined(ENABLE_CYCLES_STATS) + u8 cycles_start, cycles_end; +#endif + + RT_TIMING_GET_TIME(time_start); + CYCLES_STATS_GET(cycles_start); /* is the class loaded */ @@ -732,9 +794,7 @@ java_objectheader *builtin_new(classinfo *c) /* check if we can instantiate this class */ if (c->flags & ACC_ABSTRACT) { - *exceptionptr = - new_exception_utfmessage(string_java_lang_InstantiationError, - c->name); + exceptions_throw_instantiationerror(c); return NULL; } @@ -745,24 +805,33 @@ java_objectheader *builtin_new(classinfo *c) return NULL; if (!(c->state & CLASS_INITIALIZED)) { +#if !defined(NDEBUG) if (initverbose) log_message_class("Initialize class (from builtin_new): ", c); +#endif if (!initialize_class(c)) return NULL; } - o = heap_allocate(c->instancesize, true, c->finalizer); + o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS, + c->finalizer); if (!o) return NULL; o->vftbl = c->vftbl; -#if defined(USE_THREADS) && defined(NATIVE_THREADS) - initObjectLock(o); +#if defined(ENABLE_THREADS) + lock_init_object_lock(o); #endif + CYCLES_STATS_GET(cycles_end); + RT_TIMING_GET_TIME(time_end); + + CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start); + RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT); + return o; } @@ -776,42 +845,52 @@ java_objectheader *builtin_new(classinfo *c) *******************************************************************************/ -java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass) +java_handle_t *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; + java_array_t *a; +#if defined(ENABLE_RT_TIMING) + struct timespec time_start, time_end; +#endif + + RT_TIMING_GET_TIME(time_start); desc = arrayclass->vftbl->arraydesc; dataoffset = desc->dataoffset; componentsize = desc->componentsize; if (size < 0) { - *exceptionptr = new_negativearraysizeexception(); + exceptions_throw_negativearraysizeexception(); return NULL; } actualsize = dataoffset + size * componentsize; - if (((u4) actualsize) < ((u4) size)) { /* overflow */ - *exceptionptr = new_exception(string_java_lang_OutOfMemoryError); + /* check for overflow */ + + if (((u4) actualsize) < ((u4) size)) { + exceptions_throw_outofmemoryerror(); return NULL; } a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL); - if (!a) + if (a == NULL) return NULL; a->objheader.vftbl = arrayclass->vftbl; -#if defined(USE_THREADS) && defined(NATIVE_THREADS) - initObjectLock(&a->objheader); +#if defined(ENABLE_THREADS) + lock_init_object_lock(&a->objheader); #endif - a->size = size; + LLNI_array_size(a) = size; + + RT_TIMING_GET_TIME(time_end); + RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY); return a; } @@ -826,7 +905,7 @@ java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass) *******************************************************************************/ -java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass) +java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass) { classinfo *arrayclass; @@ -845,7 +924,7 @@ java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass) if (!arrayclass) return NULL; - return (java_objectarray *) builtin_newarray(size, arrayclass); + return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass); } @@ -859,9 +938,9 @@ java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass) *******************************************************************************/ -java_booleanarray *builtin_newarray_boolean(s4 size) +java_handle_booleanarray_t *builtin_newarray_boolean(s4 size) { - return (java_booleanarray *) + return (java_handle_booleanarray_t *) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass); } @@ -876,9 +955,9 @@ java_booleanarray *builtin_newarray_boolean(s4 size) *******************************************************************************/ -java_bytearray *builtin_newarray_byte(s4 size) +java_handle_bytearray_t *builtin_newarray_byte(s4 size) { - return (java_bytearray *) + return (java_handle_bytearray_t *) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass); } @@ -892,9 +971,9 @@ java_bytearray *builtin_newarray_byte(s4 size) *******************************************************************************/ -java_chararray *builtin_newarray_char(s4 size) +java_handle_chararray_t *builtin_newarray_char(s4 size) { - return (java_chararray *) + return (java_handle_chararray_t *) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass); } @@ -908,9 +987,9 @@ java_chararray *builtin_newarray_char(s4 size) *******************************************************************************/ -java_shortarray *builtin_newarray_short(s4 size) +java_handle_shortarray_t *builtin_newarray_short(s4 size) { - return (java_shortarray *) + return (java_handle_shortarray_t *) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass); } @@ -924,9 +1003,9 @@ java_shortarray *builtin_newarray_short(s4 size) *******************************************************************************/ -java_intarray *builtin_newarray_int(s4 size) +java_handle_intarray_t *builtin_newarray_int(s4 size) { - return (java_intarray *) + return (java_handle_intarray_t *) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass); } @@ -940,9 +1019,9 @@ java_intarray *builtin_newarray_int(s4 size) *******************************************************************************/ -java_longarray *builtin_newarray_long(s4 size) +java_handle_longarray_t *builtin_newarray_long(s4 size) { - return (java_longarray *) + return (java_handle_longarray_t *) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass); } @@ -956,9 +1035,9 @@ java_longarray *builtin_newarray_long(s4 size) *******************************************************************************/ -java_floatarray *builtin_newarray_float(s4 size) +java_handle_floatarray_t *builtin_newarray_float(s4 size) { - return (java_floatarray *) + return (java_handle_floatarray_t *) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass); } @@ -972,9 +1051,9 @@ java_floatarray *builtin_newarray_float(s4 size) *******************************************************************************/ -java_doublearray *builtin_newarray_double(s4 size) +java_handle_doublearray_t *builtin_newarray_double(s4 size) { - return (java_doublearray *) + return (java_handle_doublearray_t *) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass); } @@ -986,28 +1065,28 @@ java_doublearray *builtin_newarray_double(s4 size) 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 + n.............number of dimensions to create + arrayclass....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 ******************************************************************************/ -static java_arrayheader *builtin_multianewarray_intern(int n, - classinfo *arrayclass, - long *dims) +static java_handle_t *builtin_multianewarray_intern(int n, + classinfo *arrayclass, + long *dims) { - s4 size; - java_arrayheader *a; - classinfo *componentclass; - s4 i; + s4 size; + java_handle_t *a; + classinfo *componentclass; + s4 i; /* create this dimension */ size = (s4) dims[0]; - a = builtin_newarray(size, arrayclass); + a = builtin_newarray(size, arrayclass); if (!a) return NULL; @@ -1026,7 +1105,7 @@ static java_arrayheader *builtin_multianewarray_intern(int n, /* create the component arrays */ for (i = 0; i < size; i++) { - java_arrayheader *ea = + java_handle_t *ea = #if defined(__MIPS__) && (SIZEOF_VOID_P == 4) /* we save an s4 to a s8 slot, 8-byte aligned */ @@ -1038,7 +1117,7 @@ static java_arrayheader *builtin_multianewarray_intern(int n, if (!ea) return NULL; - ((java_objectarray *) a)->data[i] = (java_objectheader *) ea; + ((java_handle_objectarray_t *) a)->data[i] = (java_object_t *) ea; } return a; @@ -1052,8 +1131,8 @@ static java_arrayheader *builtin_multianewarray_intern(int n, ******************************************************************************/ -java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass, - long *dims) +java_handle_objectarray_t *builtin_multianewarray(int n, classinfo *arrayclass, + long *dims) { s4 i; s4 size; @@ -1069,7 +1148,7 @@ java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass, #endif if (size < 0) { - *exceptionptr = new_negativearraysizeexception(); + exceptions_throw_negativearraysizeexception(); return NULL; } } @@ -1088,28 +1167,42 @@ java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass, *****************************************************************************/ -s4 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 indent) +java_handle_t *builtin_trace_exception(java_handle_t *xptr, + methodinfo *m, + void *pos, + s4 indent) { char *logtext; s4 logtextlen; s4 dumpsize; + codeinfo *code; + +#if defined(ENABLE_DEBUG_FILTER) + if (! show_filters_test_verbosecall_exit(m)) return xptr; +#endif - if (runverbose && indent) +#if defined(ENABLE_VMLOG) + return xptr; +#endif + + if (opt_verbosecall && indent) +#if defined(__S390__) + TRACEJAVACALLINDENT--; +#else methodindent--; +#endif /* calculate message length */ if (xptr) { logtextlen = - strlen("Exception ") + - utf_strlen(xptr->vftbl->class->name); - - } else { + strlen("Exception ") + utf_bytes(xptr->vftbl->class->name); + } + else { logtextlen = strlen("Some Throwable"); } @@ -1117,10 +1210,10 @@ java_objectheader *builtin_trace_exception(java_objectheader *xptr, if (m) { logtextlen += - utf_strlen(m->class->name) + + utf_bytes(m->class->name) + strlen(".") + - utf_strlen(m->name) + - utf_strlen(m->descriptor) + + utf_bytes(m->name) + + utf_bytes(m->descriptor) + strlen("(NOSYNC,NATIVE"); #if SIZEOF_VOID_P == 8 @@ -1133,12 +1226,14 @@ java_objectheader *builtin_trace_exception(java_objectheader *xptr, if (m->class->sourcefile == NULL) logtextlen += strlen(""); else - logtextlen += utf_strlen(m->class->sourcefile); + logtextlen += utf_bytes(m->class->sourcefile); logtextlen += strlen(":65536)"); - } else + } + else { logtextlen += strlen("call_java_method"); + } logtextlen += strlen("0"); @@ -1150,7 +1245,7 @@ java_objectheader *builtin_trace_exception(java_objectheader *xptr, if (xptr) { strcpy(logtext, "Exception "); - utf_strcat_classname(logtext, xptr->vftbl->class->name); + utf_cat_classname(logtext, xptr->vftbl->class->name); } else { strcpy(logtext, "Some Throwable"); @@ -1159,10 +1254,10 @@ java_objectheader *builtin_trace_exception(java_objectheader *xptr, strcat(logtext, " thrown in "); if (m) { - utf_strcat_classname(logtext, m->class->name); + utf_cat_classname(logtext, m->class->name); strcat(logtext, "."); - utf_strcat(logtext, m->name); - utf_strcat(logtext, m->descriptor); + utf_cat(logtext, m->name); + utf_cat(logtext, m->descriptor); if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, "(SYNC"); @@ -1172,31 +1267,38 @@ java_objectheader *builtin_trace_exception(java_objectheader *xptr, if (m->flags & ACC_NATIVE) { strcat(logtext, ",NATIVE"); + code = m->code; + #if SIZEOF_VOID_P == 8 sprintf(logtext + strlen(logtext), ")(0x%016lx) at position 0x%016lx", - (ptrint) m->entrypoint, (ptrint) pos); + (ptrint) code->entrypoint, (ptrint) pos); #else sprintf(logtext + strlen(logtext), ")(0x%08x) at position 0x%08x", - (ptrint) m->entrypoint, (ptrint) pos); + (ptrint) code->entrypoint, (ptrint) pos); #endif } 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) m->entrypoint, (ptrint) pos); + (ptrint) code->entrypoint, (ptrint) pos); #else sprintf(logtext + strlen(logtext), ")(0x%08x) at position 0x%08x (", - (ptrint) m->entrypoint, (ptrint) pos); + (ptrint) code->entrypoint, (ptrint) pos); #endif if (m->class->sourcefile == NULL) strcat(logtext, ""); else - utf_strcat(logtext, m->class->sourcefile); + utf_cat(logtext, m->class->sourcefile); sprintf(logtext + strlen(logtext), ":%d)", 0); } @@ -1210,35 +1312,151 @@ java_objectheader *builtin_trace_exception(java_objectheader *xptr, dump_release(dumpsize); - /* print stacktrace for exception */ + return xptr; +} +#endif /* !defined(NDEBUG) */ + + +/* builtin_print_argument ****************************************************** + + Prints arguments and return values for the call trace. + +*******************************************************************************/ + +#if !defined(NDEBUG) +static char *builtin_print_argument(char *logtext, s4 *logtextlen, + typedesc *paramtype, s8 value) +{ + imm_union imu; + java_handle_t *o; + classinfo *c; + utf *u; + u4 len; + + switch (paramtype->type) { + case TYPE_INT: + imu.i = (s4) value; + sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i); + break; + + case TYPE_LNG: + imu.l = value; +#if SIZEOF_VOID_P == 4 + sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l); +#else + sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l); +#endif + break; + + case TYPE_FLT: +#if defined(__S390__) + imu.l = value; + /* The below won't work on S390 */ +#else + imu.i = (s4) value; +#endif + sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i); + break; + + case TYPE_DBL: + imu.l = value; +#if SIZEOF_VOID_P == 4 + sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l); +#else + sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l); +#endif + break; + + case TYPE_ADR: +#if SIZEOF_VOID_P == 4 + sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value); +#else + sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value); +#endif + + /* cast to java.lang.Object */ + + o = (java_handle_t *) (ptrint) value; + + /* check return argument for java.lang.Class or java.lang.String */ + + if (o != NULL) { + if (o->vftbl->class == class_java_lang_String) { + /* get java.lang.String object and the length of the + string */ + + u = javastring_toutf(o, false); + + len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")"); + + /* realloc memory for string length */ + + logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len); + *logtextlen += len; + + /* convert to utf8 string and strcat it to the logtext */ + + strcat(logtext, " (String = \""); + utf_cat(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 *) o; + + 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_bytes(u) + strlen("\")"); + + /* realloc memory for string length */ + + logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len); + *logtextlen += len; + + /* strcat to the logtext */ - if (opt_verboseexception) { - exceptions_print_exception(xptr); - stacktrace_print_trace(xptr); + strcat(logtext, " (Class = \""); + utf_cat_classname(logtext, u); + strcat(logtext, "\")"); + } + } } - return xptr; + return logtext; } +#endif /* !defined(NDEBUG) */ +/* builtin_verbosecall_enter *************************************************** -/* builtin_trace_args ********************************************************** - - XXX + Print method call with arguments for -verbose:call. *******************************************************************************/ +#if !defined(NDEBUG) + #ifdef TRACE_ARGS_NUM -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 /* TRACE_ARGS_NUM >= 6 */ -#if TRACE_ARGS_NUM == 8 - s8 a6, s8 a7, -#endif /* TRACE_ARGS_NUM == 8 */ - methodinfo *m) +void builtin_verbosecall_enter(s8 a0, s8 a1, +# if TRACE_ARGS_NUM >= 4 + s8 a2, s8 a3, +# endif +# if TRACE_ARGS_NUM >= 6 + s8 a4, s8 a5, +# endif +# if TRACE_ARGS_NUM == 8 + s8 a6, s8 a7, +# endif + methodinfo *m) { methoddesc *md; char *logtext; @@ -1247,21 +1465,52 @@ void builtin_trace_args(s8 a0, s8 a1, s4 i; s4 pos; +#if defined(ENABLE_DEBUG_FILTER) + if (! show_filters_test_verbosecall_enter(m)) return; +#endif + +#if defined(ENABLE_VMLOG) + vmlog_cacao_enter_method(m); + return; +#endif + md = m->parseddesc; /* calculate message length */ logtextlen = - 6 + methodindent + strlen("called: ") + - utf_strlen(m->class->name) + + strlen("4294967295 ") + + strlen("-2147483647-") + /* INT_MAX should be sufficient */ + methodindent + + strlen("called: ") + + utf_bytes(m->class->name) + strlen(".") + - utf_strlen(m->name) + - utf_strlen(m->descriptor) + - strlen(" SYNCHRONIZED") + strlen("(") + strlen(")"); + utf_bytes(m->name) + + utf_bytes(m->descriptor); + + /* Actually it's not possible to have all flags printed, but: + safety first! */ + + logtextlen += + strlen(" PUBLIC") + + strlen(" PRIVATE") + + strlen(" PROTECTED") + + strlen(" STATIC") + + strlen(" FINAL") + + strlen(" SYNCHRONIZED") + + strlen(" VOLATILE") + + strlen(" TRANSIENT") + + strlen(" NATIVE") + + strlen(" INTERFACE") + + strlen(" ABSTRACT"); /* add maximal argument length */ - logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)"); + logtextlen += + strlen("(") + + strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM + + strlen("...(255)") + + strlen(")"); /* allocate memory */ @@ -1269,7 +1518,11 @@ void builtin_trace_args(s8 a0, s8 a1, logtext = DMNEW(char, logtextlen); - sprintf(logtext,"-%d-",methodindent); + callcount++; + + sprintf(logtext, "%10d ", callcount); + sprintf(logtext + strlen(logtext), "-%d-", methodindent); + pos = strlen(logtext); for (i = 0; i < methodindent; i++) @@ -1277,10 +1530,10 @@ void builtin_trace_args(s8 a0, s8 a1, strcpy(logtext + pos, "called: "); - utf_strcat_classname(logtext, m->class->name); + utf_cat_classname(logtext, m->class->name); strcat(logtext, "."); - utf_strcat(logtext, m->name); - utf_strcat(logtext, m->descriptor); + utf_cat(logtext, m->name); + utf_cat(logtext, m->descriptor); if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC"); if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE"); @@ -1296,175 +1549,72 @@ void builtin_trace_args(s8 a0, s8 a1, 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 (md->paramcount >= 1) { + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[0], a0); + } -#if SIZEOF_VOID_P == 4 - case 1: - sprintf(logtext + strlen(logtext), - "0x%llx", - a0); - break; + if (md->paramcount >= 2) { + strcat(logtext, ", "); - case 2: - sprintf(logtext + strlen(logtext), - "0x%llx, 0x%llx", - a0, a1); - break; + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[1], a1); + } #if TRACE_ARGS_NUM >= 4 - case 3: - sprintf(logtext + strlen(logtext), - "0x%llx, 0x%llx, 0x%llx", - a0, a1, a2); - break; + if (md->paramcount >= 3) { + strcat(logtext, ", "); + + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[2], a2); + } - case 4: - sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx" - , a0, a1, a2); - sprintf(logtext + strlen(logtext), ", 0x%llx", a3); + if (md->paramcount >= 4) { + strcat(logtext, ", "); - break; -#endif /* TRACE_ARGS_NUM >= 4 */ + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[3], a3); + } +#endif #if TRACE_ARGS_NUM >= 6 - case 5: - sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx" - , a0, a1, a2); - sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4); - break; + if (md->paramcount >= 5) { + strcat(logtext, ", "); + + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[4], a4); + } + if (md->paramcount >= 6) { + strcat(logtext, ", "); - case 6: - 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 */ + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[5], a5); + } +#endif #if TRACE_ARGS_NUM == 8 - case 7: - 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; + if (md->paramcount >= 7) { + strcat(logtext, ", "); - case 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", a6, a7); - break; -#endif /* TRACE_ARGS_NUM == 8 */ + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[6], a6); + } - default: -#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); + if (md->paramcount >= 8) { + strcat(logtext, ", "); + + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[7], a7); + } #endif - break; -#else /* SIZEOF_VOID_P == 4 */ + if (md->paramcount > 8) { + sprintf(logtext + strlen(logtext), ", ...(%d)", + md->paramcount - TRACE_ARGS_NUM); + } - case 1: - sprintf(logtext + strlen(logtext), - "0x%lx", - a0); - break; - - case 2: - sprintf(logtext + strlen(logtext), - "0x%lx, 0x%lx", - a0, a1); - break; - - case 3: - sprintf(logtext + strlen(logtext), - "0x%lx, 0x%lx, 0x%lx", a0, a1, a2); - break; - - case 4: - 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), - "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx", - a0, a1, a2, a3, a4); - break; - - case 6: - 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), - "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), - "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), - "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), - "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), - "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 /* SIZEOF_VOID_P == 4 */ - } - - strcat(logtext, ")"); + strcat(logtext, ")"); log_text(logtext); @@ -1473,43 +1623,51 @@ void builtin_trace_args(s8 a0, s8 a1, dump_release(dumpsize); methodindent++; + } #endif +#endif /* !defined(NDEBUG) */ -/* builtin_displaymethodstop *************************************************** +/* builtin_verbosecall_exit **************************************************** - XXX + Print method exit for -verbose:call. *******************************************************************************/ -void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f) +#if !defined(NDEBUG) +void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m) { - 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; + methoddesc *md; + char *logtext; + s4 logtextlen; + s4 dumpsize; + s4 i; + s4 pos; + imm_union val; + +#if defined(ENABLE_DEBUG_FILTER) + if (! show_filters_test_verbosecall_exit(m)) return; +#endif + +#if defined(ENABLE_VMLOG) + vmlog_cacao_leave_method(m); + return; +#endif md = m->parseddesc; /* calculate message length */ logtextlen = + strlen("4294967295 ") + strlen("-2147483647-") + /* INT_MAX should be sufficient */ methodindent + strlen("finished: ") + - utf_strlen(m->class->name) + + utf_bytes(m->class->name) + strlen(".") + - utf_strlen(m->name) + - utf_strlen(m->descriptor) + + utf_bytes(m->name) + + utf_bytes(m->descriptor) + strlen(" SYNCHRONIZED") + strlen("(") + strlen(")"); /* add maximal argument length */ @@ -1531,7 +1689,8 @@ void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f) /* generate the message */ - sprintf(logtext, "-%d-", methodindent); + sprintf(logtext, " "); + sprintf(logtext + strlen(logtext), "-%d-", methodindent); pos = strlen(logtext); @@ -1539,98 +1698,32 @@ void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f) logtext[pos++] = '\t'; strcpy(logtext + pos, "finished: "); - utf_strcat_classname(logtext, m->class->name); + utf_cat_classname(logtext, m->class->name); strcat(logtext, "."); - utf_strcat(logtext, m->name); - utf_strcat(logtext, m->descriptor); - - switch (md->returntype.type) { - case TYPE_INT: - sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l); - break; - - case TYPE_LNG: -#if SIZEOF_VOID_P == 4 - sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l); -#else - sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l); -#endif - break; - - 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 *) 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 *) 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 *) 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, "\""); - } + utf_cat(logtext, m->name); + utf_cat(logtext, m->descriptor); + + if (!IS_VOID_TYPE(md->returntype.type)) { + strcat(logtext, "->"); + + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_LNG: + case TYPE_ADR: + val.l = l; + break; + + case TYPE_FLT: + val.f = f; + break; + + case TYPE_DBL: + val.d = d; + break; } - break; - case TYPE_FLT: - imu.f = f; - sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i); - break; - - 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; + logtext = + builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l); } log_text(logtext); @@ -1638,157 +1731,22 @@ void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f) /* release memory */ dump_release(dumpsize); -} - - -/**************************************************************************** - SYNCHRONIZATION FUNCTIONS -*****************************************************************************/ - -#if defined(USE_THREADS) && !defined(NATIVE_THREADS) -/* - * Lock the mutex of an object. - */ -void internal_lock_mutex_for_object(java_objectheader *object) -{ - mutexHashEntry *entry; - int hashValue; - - assert(object != 0); - - hashValue = MUTEX_HASH_VALUE(object); - entry = &mutexHashTable[hashValue]; - - if (entry->object != 0) { - if (entry->mutex.count == 0 && entry->conditionCount == 0) { - entry->object = 0; - entry->mutex.holder = 0; - entry->mutex.count = 0; - entry->mutex.muxWaiters = 0; - - } else { - while (entry->next != 0 && entry->object != object) - entry = entry->next; - - if (entry->object != object) { - entry->next = firstFreeOverflowEntry; - firstFreeOverflowEntry = firstFreeOverflowEntry->next; - - entry = entry->next; - entry->object = 0; - entry->next = 0; - assert(entry->conditionCount == 0); - } - } - - } else { - entry->mutex.holder = 0; - entry->mutex.count = 0; - entry->mutex.muxWaiters = 0; - } - - if (entry->object == 0) - entry->object = object; - - internal_lock_mutex(&entry->mutex); -} -#endif - - -#if defined(USE_THREADS) && !defined(NATIVE_THREADS) -/* - * Unlocks the mutex of an object. - */ -void internal_unlock_mutex_for_object (java_objectheader *object) -{ - int hashValue; - mutexHashEntry *entry; - - hashValue = MUTEX_HASH_VALUE(object); - entry = &mutexHashTable[hashValue]; - - if (entry->object == object) { - internal_unlock_mutex(&entry->mutex); - - } else { - while (entry->next != 0 && entry->next->object != object) - entry = entry->next; - - assert(entry->next != 0); - - internal_unlock_mutex(&entry->next->mutex); - - if (entry->next->mutex.count == 0 && entry->conditionCount == 0) { - mutexHashEntry *unlinked = entry->next; - - entry->next = unlinked->next; - unlinked->next = firstFreeOverflowEntry; - firstFreeOverflowEntry = unlinked; - } - } -} -#endif - - -#if defined(USE_THREADS) -void builtin_monitorenter(java_objectheader *o) -{ -#if !defined(NATIVE_THREADS) - int hashValue; - - ++blockInts; - hashValue = MUTEX_HASH_VALUE(o); - if (mutexHashTable[hashValue].object == o - && mutexHashTable[hashValue].mutex.holder == currentThread) - ++mutexHashTable[hashValue].mutex.count; - else - internal_lock_mutex_for_object(o); - - --blockInts; -#else - monitorEnter((threadobject *) THREADOBJECT, o); -#endif -} -#endif - - -#if defined(USE_THREADS) -/* - * Locks the class object - needed for static synchronized methods. - */ -void builtin_staticmonitorenter(classinfo *c) -{ - builtin_monitorenter(&c->object.header); } -#endif +#endif /* !defined(NDEBUG) */ -#if defined(USE_THREADS) -void builtin_monitorexit(java_objectheader *o) +#if defined(ENABLE_CYCLES_STATS) +void builtin_print_cycles_stats(FILE *file) { -#if !defined(NATIVE_THREADS) - int hashValue; + fprintf(file,"builtin cylce count statistics:\n"); - ++blockInts; + CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file); + CYCLES_STATS_PRINT(builtin_new ,file); - hashValue = MUTEX_HASH_VALUE(o); - if (mutexHashTable[hashValue].object == o) { - if (mutexHashTable[hashValue].mutex.count == 1 - && mutexHashTable[hashValue].mutex.muxWaiters != 0) - internal_unlock_mutex_for_object(o); - else - --mutexHashTable[hashValue].mutex.count; - - } else - internal_unlock_mutex_for_object(o); - - --blockInts; -#else - monitorExit((threadobject *) THREADOBJECT, o); -#endif + fprintf(file,"\n"); } -#endif +#endif /* defined(ENABLE_CYCLES_STATS) */ /***************************************************************************** @@ -1804,17 +1762,35 @@ void builtin_monitorexit(java_objectheader *o) ******************************************************************************/ -s4 builtin_idiv(s4 a, s4 b) { return a / b; } -s4 builtin_irem(s4 a, s4 b) { return a % b; } +#if !SUPPORT_DIVISION || defined(DISABLE_GC) +s4 builtin_idiv(s4 a, s4 b) +{ + s4 c; + + c = a / b; + return c; +} -/************** Functions for long arithmetics ******************************* +s4 builtin_irem(s4 a, s4 b) +{ + s4 c; - On systems where 64 bit Integers are not supported by the CPU, these - functions are needed. + c = a % b; + + return c; +} +#endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */ + + +/* functions for long arithmetics ********************************************** + + 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; @@ -1828,7 +1804,7 @@ s8 builtin_ladd(s8 a, s8 b) return c; } -s8 builtin_lsub(s8 a, s8 b) +s8 builtin_lsub(s8 a, s8 b) { s8 c; @@ -1841,7 +1817,23 @@ s8 builtin_lsub(s8 a, s8 b) return c; } -s8 builtin_lmul(s8 a, s8 b) +s8 builtin_lneg(s8 a) +{ + s8 c; + +#if U8_AVAILABLE + c = -a; +#else + 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; @@ -1853,8 +1845,11 @@ s8 builtin_lmul(s8 a, s8 b) return c; } +#endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */ + -s8 builtin_ldiv(s8 a, s8 b) +#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC) +s8 builtin_ldiv(s8 a, s8 b) { s8 c; @@ -1867,7 +1862,7 @@ s8 builtin_ldiv(s8 a, s8 b) return c; } -s8 builtin_lrem(s8 a, s8 b) +s8 builtin_lrem(s8 a, s8 b) { s8 c; @@ -1879,8 +1874,11 @@ s8 builtin_lrem(s8 a, s8 b) return c; } +#endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */ + -s8 builtin_lshl(s8 a, s4 b) +#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) +s8 builtin_lshl(s8 a, s4 b) { s8 c; @@ -1893,7 +1891,7 @@ s8 builtin_lshl(s8 a, s4 b) return c; } -s8 builtin_lshr(s8 a, s4 b) +s8 builtin_lshr(s8 a, s4 b) { s8 c; @@ -1906,7 +1904,7 @@ s8 builtin_lshr(s8 a, s4 b) return c; } -s8 builtin_lushr(s8 a, s4 b) +s8 builtin_lushr(s8 a, s4 b) { s8 c; @@ -1918,8 +1916,11 @@ s8 builtin_lushr(s8 a, s4 b) return c; } +#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */ -s8 builtin_land(s8 a, s8 b) + +#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) +s8 builtin_land(s8 a, s8 b) { s8 c; @@ -1932,7 +1933,7 @@ s8 builtin_land(s8 a, s8 b) return c; } -s8 builtin_lor(s8 a, s8 b) +s8 builtin_lor(s8 a, s8 b) { s8 c; @@ -1957,36 +1958,28 @@ s8 builtin_lxor(s8 a, s8 b) return c; } +#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */ -s8 builtin_lneg(s8 a) -{ - s8 c; +#if !(SUPPORT_LONG && SUPPORT_LONG_CMP) +s4 builtin_lcmp(s8 a, s8 b) +{ #if U8_AVAILABLE - c = -a; -#else - c = builtin_i2l(0); -#endif + if (a < b) + return -1; - return c; -} + if (a > b) + return 1; -s4 builtin_lcmp(s8 a, s8 b) -{ -#if U8_AVAILABLE - if (a < b) return -1; - if (a > b) return 1; return 0; #else return 0; #endif } +#endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */ - - - -/*********** Functions for floating point operations *************************/ +/* functions for unsupported floating instructions ****************************/ /* used to convert FLT_xxx defines into float values */ @@ -2010,6 +2003,7 @@ static inline float longBitsToDouble(s8 l) } +#if !SUPPORT_FLOAT float builtin_fadd(float a, float b) { if (isnanf(a)) return intBitsToFloat(FLT_NAN); @@ -2123,12 +2117,6 @@ float builtin_fdiv(float a, float b) } -float builtin_frem(float a, float b) -{ - return fmodf(a, b); -} - - float builtin_fneg(float a) { if (isnanf(a)) return a; @@ -2137,18 +2125,29 @@ float builtin_fneg(float a) else return copysignf(a, -copysignf(1.0, a)); } } +#endif /* !SUPPORT_FLOAT */ +#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) s4 builtin_fcmpl(float a, float b) { - if (isnanf(a)) return -1; - if (isnanf(b)) return -1; + if (isnanf(a)) + return -1; + + if (isnanf(b)) + return -1; + if (!finitef(a) || !finitef(b)) { a = finitef(a) ? 0 : copysignf(1.0, a); b = finitef(b) ? 0 : copysignf(1.0, b); } - if (a > b) return 1; - if (a == b) return 0; + + if (a > b) + return 1; + + if (a == b) + return 0; + return -1; } @@ -2165,11 +2164,18 @@ s4 builtin_fcmpg(float a, float b) if (a == b) return 0; return -1; } +#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || 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); @@ -2278,11 +2284,6 @@ double builtin_ddiv(double a, double b) } -double builtin_drem(double a, double b) -{ - return fmod(a, b); -} - /* builtin_dneg **************************************************************** Implemented as described in VM Spec. @@ -2312,38 +2313,66 @@ double builtin_dneg(double a) } } } +#endif /* !SUPPORT_DOUBLE */ +#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) s4 builtin_dcmpl(double a, double b) { - if (isnan(a)) return -1; - if (isnan(b)) return -1; + if (isnan(a)) + return -1; + + if (isnan(b)) + return -1; + if (!finite(a) || !finite(b)) { a = finite(a) ? 0 : copysign(1.0, a); b = finite(b) ? 0 : copysign(1.0, b); } - if (a > b) return 1; - if (a == b) return 0; + + if (a > b) + return 1; + + if (a == b) + return 0; + return -1; } s4 builtin_dcmpg(double a, double b) { - if (isnan(a)) return 1; - if (isnan(b)) return 1; + if (isnan(a)) + return 1; + + if (isnan(b)) + return 1; + if (!finite(a) || !finite(b)) { a = finite(a) ? 0 : copysign(1.0, a); b = finite(b) ? 0 : copysign(1.0, b); } - if (a > b) return 1; - if (a == b) return 0; + + if (a > b) + return 1; + + if (a == b) + return 0; + return -1; } +#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || 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 @@ -2356,31 +2385,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 @@ -2390,8 +2424,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 @@ -2401,8 +2437,10 @@ double builtin_l2d(s8 a) return 0.0; #endif } +#endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */ +#if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) s4 builtin_f2i(float a) { s4 i; @@ -2427,8 +2465,10 @@ s4 builtin_f2i(float a) return 2147483647; return (-2147483648); */ } +#endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */ +#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC) s8 builtin_f2l(float a) { s8 l; @@ -2453,20 +2493,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) || defined(DISABLE_GC) s4 builtin_d2i(double a) { double d; @@ -2485,8 +2515,10 @@ s4 builtin_d2i(double a) return 2147483647; return (-2147483647-1); } +#endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */ +#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC) s8 builtin_d2l(double a) { double d; @@ -2505,8 +2537,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)) @@ -2518,38 +2563,208 @@ float builtin_d2f(double a) return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a)); } } +#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */ + + +/* builtin_arraycopy *********************************************************** + + Builtin for java.lang.System.arraycopy. + + ATTENTION: This builtin function returns a boolean value to signal + the ICMD_BUILTIN if there was an exception. + +*******************************************************************************/ + +bool builtin_arraycopy(java_handle_t *src, s4 srcStart, + java_handle_t *dest, s4 destStart, s4 len) +{ + arraydescriptor *sdesc; + arraydescriptor *ddesc; + s4 i; + + if ((src == NULL) || (dest == NULL)) { + exceptions_throw_nullpointerexception(); + return false; + } + + sdesc = LLNI_vftbl_direct(src)->arraydesc; + ddesc = LLNI_vftbl_direct(dest)->arraydesc; + + if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) { + exceptions_throw_arraystoreexception(); + return false; + } + + /* we try to throw exception with the same message as SUN does */ + + if ((len < 0) || (srcStart < 0) || (destStart < 0) || + (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) || + (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) { + exceptions_throw_arrayindexoutofboundsexception(); + return false; + } + + if (sdesc->componentvftbl == ddesc->componentvftbl) { + /* We copy primitive values or references of exactly the same type */ + + s4 dataoffset = sdesc->dataoffset; + s4 componentsize = sdesc->componentsize; + + memmove(((u1 *) dest) + dataoffset + componentsize * destStart, + ((u1 *) src) + dataoffset + componentsize * srcStart, + (size_t) len * componentsize); + } + else { + /* We copy references of different type */ + + java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src; + java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest; + + if (destStart <= srcStart) { + for (i = 0; i < len; i++) { + java_handle_t *o = oas->data[srcStart + i]; + + if (!builtin_canstore(oad, o)) + return false; + + oad->data[destStart + i] = o; + } + } + else { + /* XXX this does not completely obey the specification! + If an exception is thrown only the elements above the + current index have been copied. The specification + requires that only the elements *below* the current + index have been copied before the throw. */ + + for (i = len - 1; i >= 0; i--) { + java_handle_t *o = oas->data[srcStart + i]; + + if (!builtin_canstore(oad, o)) + return false; + + oad->data[destStart + i] = o; + } + } + } + + return true; +} -/* builtin_clone_array ********************************************************* +/* builtin_nanotime ************************************************************ - Wrapper function for cloning arrays. + Return the current time in nanoseconds. *******************************************************************************/ -java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o) +s8 builtin_nanotime(void) { - java_arrayheader *ah; - java_lang_Cloneable *c; + struct timeval tv; + s8 usecs; - c = (java_lang_Cloneable *) o; + if (gettimeofday(&tv, NULL) == -1) + vm_abort("gettimeofday failed: %s", strerror(errno)); - ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c); + usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec; - return ah; + return usecs * 1000; } -/* builtin_asm_get_exceptionptrptr ********************************************* +/* builtin_currenttimemillis *************************************************** - this is a wrapper for calls from asmpart + Return the current time in milliseconds. *******************************************************************************/ -#if defined(USE_THREADS) && defined(NATIVE_THREADS) -java_objectheader **builtin_asm_get_exceptionptrptr(void) +s8 builtin_currenttimemillis(void) { - return builtin_get_exceptionptrptr(); + s8 msecs; + + msecs = builtin_nanotime() / 1000 / 1000; + + return msecs; } + + +/* builtin_clone *************************************************************** + + Function for cloning objects or arrays. + +*******************************************************************************/ + +java_handle_t *builtin_clone(void *env, java_handle_t *o) +{ + arraydescriptor *ad; + java_handle_t *ah; + u4 size; + classinfo *c; + java_handle_t *co; /* cloned object header */ + + /* get the array descriptor */ + + ad = o->vftbl->arraydesc; + + /* we are cloning an array */ + + if (ad != NULL) { + ah = (java_handle_t *) o; + + size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah); + + co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL); + + if (co == NULL) + return NULL; + + MCOPY(co, o, u1, size); + +#if defined(ENABLE_GC_CACAO) + heap_init_objectheader(co, size); +#endif + +#if defined(ENABLE_THREADS) + lock_init_object_lock(co); +#endif + + return co; + } + + /* we are cloning a non-array */ + + if (!builtin_instanceof(o, class_java_lang_Cloneable)) { + exceptions_throw_clonenotsupportedexception(); + return NULL; + } + + /* get the class of the object */ + + c = o->vftbl->class; + + /* create new object */ + + co = builtin_new(c); + + if (co == NULL) + return NULL; + + MCOPY(co, o, u1, c->instancesize); + +#if defined(ENABLE_GC_CACAO) + heap_init_objectheader(co, c->instancesize); +#endif + +#if defined(ENABLE_THREADS) + lock_init_object_lock(co); +#endif + + return co; +} + +#if defined(ENABLE_VMLOG) +#define NDEBUG +#include #endif @@ -2564,4 +2779,5 @@ java_objectheader **builtin_asm_get_exceptionptrptr(void) * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */