X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fbuiltin.c;h=6ef51c9c07c7e25a9fb4e155f0f67ff332679517;hb=3e1554d4079482122cd359f4b90f648de15fb43f;hp=476db73b9162c322609246f36d43e705d4e26109;hpb=f7f39916196f2819ec4e8101d10bfa59f71c536d;p=cacao.git diff --git a/src/vm/builtin.c b/src/vm/builtin.c index 476db73b9..4a435205c 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,581 +28,645 @@ calls instead of machine instructions, using the C calling convention. - $Id: builtin.c 2358 2005-04-22 22:01:51Z jowenn $ - */ +#include "config.h" + #include -#include +#include #include #include +#include + +#include "vm/types.h" -#include "config.h" #include "arch.h" -#include "types.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_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 "md-abi.h" + +#include "fdlibm/fdlibm.h" +#if defined(__CYGWIN__) && defined(Bias) +# undef Bias #endif +#include "mm/gc-common.h" +#include "mm/memory.h" + +#include "native/jni.h" +#include "native/llni.h" + +#include "threads/lock-common.h" +#include "threads/threads-common.h" + #include "toolbox/logging.h" +#include "toolbox/util.h" + +#include "vm/array.h" #include "vm/builtin.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/tables.h" + #include "vm/jit/asmpart.h" +#include "vm/jit/trace.h" +#include "vmcore/class.h" +#include "vmcore/linker.h" +#include "vmcore/loader.h" +#include "vmcore/options.h" +#include "vmcore/rt-timing.h" -#undef DEBUG /*define DEBUG 1*/ +#if defined(ENABLE_VMLOG) +#include +#endif -THREADSPECIFIC methodinfo* _threadrootmethod = NULL; -THREADSPECIFIC void *_thread_nativestackframeinfo = NULL; +#if defined(ENABLE_DEBUG_FILTER) +# include "vm/jit/show.h" +#endif +/* include builtin tables *****************************************************/ -#if defined(USEBUILTINTABLE) +#include "vm/builtintable.inc" -#if 0 -stdopdescriptor builtintable[] = { - { ICMD_LCMP, TYPE_LONG, TYPE_LONG, TYPE_INT, ICMD_BUILTIN2, - (functionptr) builtin_lcmp , SUPPORT_LONG && SUPPORT_LONG_CMP, false }, - { ICMD_LAND, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2, - (functionptr) builtin_land , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false }, - { ICMD_LOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2, - (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false }, - { ICMD_LXOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2, - (functionptr) builtin_lxor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false }, - { ICMD_LSHL, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2, - (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false }, - { ICMD_LSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2, - (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false }, - { ICMD_LUSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2, - (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false }, - { ICMD_LADD, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2, - (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false }, - { ICMD_LSUB, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2, - (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false }, - { ICMD_LNEG, TYPE_LONG, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1, - (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, true }, - { ICMD_LMUL, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2, - (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MUL, false }, - { ICMD_I2F, TYPE_INT, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1, - (functionptr) builtin_i2f, SUPPORT_FLOAT && SUPPORT_IFCVT, true }, - { ICMD_I2D, TYPE_INT, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1, - (functionptr) builtin_i2d, SUPPORT_DOUBLE && SUPPORT_IFCVT, true }, - { ICMD_L2F, TYPE_LONG, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1, - (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true }, - { ICMD_L2D, TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1, - (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true }, - { ICMD_F2L, TYPE_FLOAT, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1, - (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT, true }, - { ICMD_D2L, TYPE_DOUBLE, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1, - (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT, true }, - { ICMD_F2I, TYPE_FLOAT, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1, - (functionptr) builtin_f2i, SUPPORT_FLOAT && SUPPORT_FICVT, true }, - { ICMD_D2I, TYPE_DOUBLE, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1, - (functionptr) builtin_d2i, SUPPORT_DOUBLE && SUPPORT_FICVT, true }, - { 255, 0, 0, 0, 0, NULL, true, false }, -}; -#endif +CYCLES_STATS_DECLARE(builtin_new ,100,5) +CYCLES_STATS_DECLARE(builtin_overhead , 80,1) -static int builtintablelen; +/* builtintable_init *********************************************************** -#endif /* USEBUILTINTABLE */ + Parse the descriptors of builtin functions and create the parsed + descriptors. +*******************************************************************************/ -/***************************************************************************** - TABLE OF BUILTIN FUNCTIONS +static bool builtintable_init(void) +{ + descriptor_pool *descpool; + s4 dumpsize; + builtintable_entry *bte; + methodinfo *m; - This table lists the builtin functions which are used inside - BUILTIN* opcodes. + /* mark start of dump memory area */ - The first part of the table (up to the 255-marker) lists the - opcodes which are automatically replaced in stack.c. + dumpsize = dump_size(); - The second part lists the builtin functions which are "manually" - used for BUILTIN* opcodes in parse.c and stack.c. + /* create a new descriptor pool */ -*****************************************************************************/ + descpool = descriptor_pool_new(class_java_lang_Object); -builtin_descriptor builtin_desc[] = { -#if defined(USEBUILTINTABLE) - {ICMD_LCMP , BUILTIN_lcmp ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_INT , - SUPPORT_LONG && SUPPORT_LONG_CMP,false,"lcmp"}, - - {ICMD_LAND , BUILTIN_land ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"land"}, - {ICMD_LOR , BUILTIN_lor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lor"}, - {ICMD_LXOR , BUILTIN_lxor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lxor"}, - - {ICMD_LSHL , BUILTIN_lshl ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshl"}, - {ICMD_LSHR , BUILTIN_lshr ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshr"}, - {ICMD_LUSHR, BUILTIN_lushr,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lushr"}, - - {ICMD_LADD , BUILTIN_ladd ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_ADD,false,"ladd"}, - {ICMD_LSUB , BUILTIN_lsub ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lsub"}, - {ICMD_LNEG , BUILTIN_lneg ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lneg"}, - {ICMD_LMUL , BUILTIN_lmul ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG , - SUPPORT_LONG && SUPPORT_LONG_MUL,false,"lmul"}, - - {ICMD_I2F , BUILTIN_i2f ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT , - SUPPORT_FLOAT && SUPPORT_IFCVT,true ,"i2f"}, - {ICMD_I2D , BUILTIN_i2d ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE, - SUPPORT_DOUBLE && SUPPORT_IFCVT,true ,"i2d"}, - {ICMD_L2F , BUILTIN_l2f ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT , - SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT,true ,"l2f"}, - {ICMD_L2D , BUILTIN_l2d ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE, - SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT,true ,"l2d"}, - {ICMD_F2L , BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG , - SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"f2l"}, - {ICMD_D2L , BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG , - SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"d2l"}, - {ICMD_F2I , BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT , - SUPPORT_FLOAT && SUPPORT_FICVT,true ,"f2i"}, - {ICMD_D2I , BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT , - SUPPORT_DOUBLE && SUPPORT_FICVT,true ,"d2i"}, - - { ICMD_FADD , BUILTIN_fadd , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fadd" }, - { ICMD_FSUB , BUILTIN_fsub , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fsub" }, - { ICMD_FMUL , BUILTIN_fmul , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fmul" }, - { ICMD_FDIV , BUILTIN_fdiv , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fdiv" }, - { ICMD_FNEG , BUILTIN_fneg , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fneg" }, - { ICMD_FCMPL, BUILTIN_fcmpl , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpl" }, - { ICMD_FCMPG, BUILTIN_fcmpg , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpg" }, - - { ICMD_DADD , BUILTIN_dadd , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dadd" }, - { ICMD_DSUB , BUILTIN_dsub , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dsub" }, - { ICMD_DMUL , BUILTIN_dmul , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dmul" }, - { ICMD_DDIV , BUILTIN_ddiv , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "ddiv" }, - { ICMD_DNEG , BUILTIN_dneg , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dneg" }, - { ICMD_DCMPL, BUILTIN_dcmpl , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpl" }, - { ICMD_DCMPG, BUILTIN_dcmpg , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpg" }, - - { ICMD_F2D, BUILTIN_f2d , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "f2d" }, - { ICMD_D2F, BUILTIN_d2f , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "d2f" }, -#endif + /* add some entries we need */ - /* this record marks the end of the automatically replaced opcodes */ - {255,NULL,0,0,0,0,0,0,0,""}, + if (!descriptor_pool_add_class(descpool, utf_java_lang_Object)) + return false; - /* the following functions are not replaced automatically */ - -#if defined(__ALPHA__) - {255, BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"f2l"}, - {255, BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"d2l"}, - {255, BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"f2i"}, - {255, BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"d2i"}, -#endif + if (!descriptor_pool_add_class(descpool, utf_java_lang_Class)) + return false; - {255,BUILTIN_instanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"instanceof"}, - {255,BUILTIN_arrayinstanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"arrayinstanceof"}, - {255,BUILTIN_checkarraycast ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,0,0,"checkarraycast"}, - {255,BUILTIN_aastore ,ICMD_BUILTIN3,TYPE_ADR ,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,0,0,"aastore"}, - {255,BUILTIN_new ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"new"}, - {255,BUILTIN_newarray ,ICMD_BUILTIN2,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray"}, - {255,BUILTIN_newarray_boolean,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_boolean"}, - {255,BUILTIN_newarray_char ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_char"}, - {255,BUILTIN_newarray_float ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_float"}, - {255,BUILTIN_newarray_double ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_double"}, - {255,BUILTIN_newarray_byte ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_byte"}, - {255,BUILTIN_newarray_short ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_short"}, - {255,BUILTIN_newarray_int ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_int"}, - {255,BUILTIN_newarray_long ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_long"}, -#if defined(USE_THREADS) - {255,BUILTIN_monitorenter ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorenter"}, - {255,BUILTIN_monitorexit ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorexit"}, -#endif -#if !SUPPORT_DIVISION - {255,BUILTIN_idiv ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"idiv"}, - {255,BUILTIN_irem ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"irem"}, -#endif -#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) - {255,BUILTIN_ldiv ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"ldiv"}, - {255,BUILTIN_lrem ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"lrem"}, -#endif - {255,BUILTIN_frem ,ICMD_BUILTIN2,TYPE_FLOAT ,TYPE_FLOAT ,TYPE_VOID ,TYPE_FLOAT ,0,0,"frem"}, - {255,BUILTIN_drem ,ICMD_BUILTIN2,TYPE_DOUBLE,TYPE_DOUBLE,TYPE_VOID ,TYPE_DOUBLE,0,0,"drem"}, + /* first add all descriptors to the pool */ + for (bte = builtintable_internal; bte->fp != NULL; bte++) { + bte->name = utf_new_char(bte->cname); + bte->descriptor = utf_new_char(bte->cdescriptor); -#if defined(__X86_64__) || defined(__I386__) - /* assembler code patching functions */ + if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) { + /* release dump area */ - { 255, asm_wrapper_patcher_BUILTIN_new , ICMD_BUILTIN1, TYPE_ADR , TYPE_VOID , TYPE_VOID , TYPE_ADR , 0, 0, "new (calling asm_wrapper_patcher_builtin_new)" }, -#endif -#if defined(__X86_64__) - { 255, asm_wrapper_patcher_BUILTIN_newarray , ICMD_BUILTIN1, TYPE_ADR , TYPE_VOID , TYPE_VOID , TYPE_ADR , 0, 0, "newarray (calling asm_wrapper_patcher_builtin_newarray)" }, - { 255, asm_wrapper_patcher_BUILTIN_checkarraycast , ICMD_BUILTIN2, TYPE_ADR , TYPE_ADR , TYPE_VOID , TYPE_VOID , 0, 0, "checkarraycast (calling asm_wrapper_patcher_builtin_checkarraycast)" }, - { 255, asm_wrapper_patcher_BUILTIN_arrayinstanceof, ICMD_BUILTIN2, TYPE_ADR , TYPE_ADR , TYPE_VOID , TYPE_INT , 0, 0, "arrayinstanceof (calling asm_wrapper_patcher_builtin_arrayinstanceof)" }, -#endif + dump_release(dumpsize); + + return false; + } + } + + for (bte = builtintable_automatic; bte->fp != NULL; bte++) { + bte->descriptor = utf_new_char(bte->cdescriptor); + + if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) { + dump_release(dumpsize); + return false; + } + } + + 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; + } + } + + /* 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. NOTE: builtin-functions are treated + like static methods (no `this' pointer). */ + + for (bte = builtintable_internal; bte->fp != NULL; bte++) { + bte->md = + descriptor_pool_parse_method_descriptor(descpool, + bte->descriptor, + ACC_STATIC | ACC_METHOD_BUILTIN, + NULL); + + /* generate a builtin stub if we need one */ + + if (bte->flags & BUILTINTABLE_FLAG_STUB) { + m = method_new_builtin(bte); + codegen_generate_stub_builtin(m, bte); + } + } + + for (bte = builtintable_automatic; bte->fp != NULL; bte++) { + bte->md = + descriptor_pool_parse_method_descriptor(descpool, + bte->descriptor, + ACC_STATIC | ACC_METHOD_BUILTIN, + NULL); + + /* no stubs should be needed for this table */ + + assert(!bte->flags & BUILTINTABLE_FLAG_STUB); + } + + for (bte = builtintable_function; bte->fp != NULL; bte++) { + bte->md = + descriptor_pool_parse_method_descriptor(descpool, + bte->descriptor, + ACC_STATIC | ACC_METHOD_BUILTIN, + NULL); + + /* generate a builtin stub if we need one */ + if (bte->flags & BUILTINTABLE_FLAG_STUB) { + m = method_new_builtin(bte); + codegen_generate_stub_builtin(m, bte); + } + } + + /* release dump area */ + + dump_release(dumpsize); + + return true; +} - /* this record marks the end of the list */ - { 0, NULL, 0, 0, 0, 0, 0, 0, 0, "" } -}; +/* builtintable_comparator ***************************************************** + qsort comparator for the automatic builtin table. -#if defined(USEBUILTINTABLE) +*******************************************************************************/ -static int stdopcompare(const void *a, const void *b) +static int builtintable_comparator(const void *a, const void *b) { - builtin_descriptor *o1 = (builtin_descriptor *) a; - builtin_descriptor *o2 = (builtin_descriptor *) b; - if (!o1->supported && o2->supported) - return -1; - if (o1->supported && !o2->supported) - return 1; - return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode); + builtintable_entry *bte1; + builtintable_entry *bte2; + + bte1 = (builtintable_entry *) a; + bte2 = (builtintable_entry *) b; + + return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode); } -void sort_builtintable(void) +/* builtintable_sort_automatic ************************************************* + + Sorts the automatic builtin table. + +*******************************************************************************/ + +static void builtintable_sort_automatic(void) { - int len; + s4 entries; + + /* calculate table size statically (`- 1' comment see builtintable.inc) */ - len = 0; - while (builtin_desc[len].opcode != 255) len++; - qsort(builtin_desc, len, sizeof(builtin_descriptor), stdopcompare); + entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1; - for (--len; len>=0 && builtin_desc[len].supported; len--); - builtintablelen = ++len; + qsort(builtintable_automatic, entries, sizeof(builtintable_entry), + builtintable_comparator); } -builtin_descriptor *find_builtin(int icmd) +/* builtin_init **************************************************************** + + Initialize the global table of builtin functions. + +*******************************************************************************/ + +bool builtin_init(void) { - builtin_descriptor *first = builtin_desc; - builtin_descriptor *last = builtin_desc + builtintablelen; - int len = last - first; - int half; - builtin_descriptor *middle; + /* initialize the builtin tables */ - while (len > 0) { - half = len / 2; - middle = first + half; - if (middle->opcode < icmd) { - first = middle + 1; - len -= half + 1; - } else - len = half; - } - return first != last ? first : NULL; + if (!builtintable_init()) + return false; + + /* sort builtin tables */ + + builtintable_sort_automatic(); + + return true; } -#endif /* defined(USEBUILTINTABLE) */ +/* 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) +{ + builtintable_entry *bte; + + for (bte = builtintable_internal; bte->fp != NULL; bte++) { + if (bte->fp == fp) + return bte; + } + + return NULL; +} -/***************************************************************************** - TYPE CHECKS -*****************************************************************************/ +/* builtintable_get_automatic ************************************************** + Finds an entry in the builtintable for functions which are replaced + automatically and returns the a pointer to the structure. -/*************** 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) +builtintable_entry *builtintable_get_automatic(s4 opcode) { - s4 res; - castinfo classvalues; + builtintable_entry *first; + builtintable_entry *last; + builtintable_entry *middle; + s4 half; + s4 entries; - if (sub == super) - return 1; + /* calculate table size statically (`- 1' comment see builtintable.inc) */ - if (super->flags & ACC_INTERFACE) - return (sub->vftbl->interfacetablelength > super->index) && - (sub->vftbl->interfacetable[-super->index] != NULL); + entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1; - asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues); + first = builtintable_automatic; + last = builtintable_automatic + entries; - res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <= - (u4) classvalues.super_diffval; + while (entries > 0) { + half = entries / 2; + middle = first + half; + + if (middle->opcode < opcode) { + first = middle + 1; + entries -= half + 1; + } + else + entries = half; + } - return res; + return (first != last ? first : NULL); } -s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super) +/* builtintable_replace_function *********************************************** + + XXX + +*******************************************************************************/ + +#if defined(ENABLE_JIT) +bool builtintable_replace_function(void *iptr_) { - s4 res; - s4 base; - castinfo classvalues; + constant_FMIref *mr; + builtintable_entry *bte; + instruction *iptr; - if (sub == super) - return 1; + iptr = (instruction *) iptr_; /* twisti will kill me ;) */ - asm_getclassvalues_atomic(super, sub, &classvalues); + /* get name and descriptor of the function */ - 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; + 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. */ + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) + return false; + + mr = iptr->sx.s23.s3.fmiref; + break; + + default: + return false; + } + + /* search the function table */ + + for (bte = builtintable_function; bte->fp != NULL; bte++) { + if ((METHODREF_CLASSNAME(mr) == bte->classname) && + (mr->name == bte->name) && + (mr->descriptor == bte->descriptor)) { + + /* set the values in the instruction */ + + iptr->opc = bte->opcode; + iptr->sx.s23.s3.bte = bte; + + if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION) + 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 -*****************************************************************************/ +*******************************************************************************/ -/* XXX should use vftbl */ -s4 builtin_instanceof(java_objectheader *obj, classinfo *class) +s4 builtin_instanceof(java_handle_t *o, classinfo *class) { -#ifdef DEBUG - log_text ("builtin_instanceof called"); -#endif - if (!obj) + classinfo *c; + + if (o == NULL) return 0; - return builtin_isanysubclass(obj->vftbl->class, class); + LLNI_class_get(o, c); + + return class_isanysubclass(c, 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. -****************************************************************************/ +*******************************************************************************/ -/* XXX should use vftbl */ -s4 builtin_checkcast(java_objectheader *obj, classinfo *class) +s4 builtin_checkcast(java_handle_t *o, classinfo *class) { -#ifdef DEBUG - log_text("builtin_checkcast called"); -#endif + classinfo *c; - if (obj == NULL) - return 1; - if (builtin_isanysubclass(obj->vftbl->class, class)) + if (o == NULL) return 1; -#if DEBUG - printf("#### checkcast failed "); - utf_display(obj->vftbl->class->name); - printf(" -> "); - utf_display(class->name); - printf("\n"); -#endif + LLNI_class_get(o, c); + + if (class_isanysubclass(c, class)) + return 1; return 0; } -/*********** internal function: builtin_descriptorscompatible ****************** +/* builtin_descriptorscompatible *********************************************** + + Checks if two array type descriptors are assignment compatible - Checks if two array type descriptors are assignment compatible - Return value: 1 ... target = desc is possible - 0 ... otherwise + 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 class_isanysubclass(desc->elementvftbl->class, + target->elementvftbl->class); } - 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 class_isanysubclass(pseudo_class_Arraystub, + target->elementvftbl->class); } -/******************** 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_handle_t *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 == NULL) + return 1; + + desc = LLNI_vftbl_direct(o)->arraydesc; + + if (desc == NULL) + return 0; + + return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc); } -s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target) +s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass) { - if (!obj) return 1; - return builtin_checkarraycast(obj, target); + 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_object_t *xptr) { - if (opt_verbose) { - char logtext[MAXLOGTEXT]; - sprintf(logtext, "Builtin exception thrown: "); +#if !defined(NDEBUG) + /* print exception trace */ - if (xptr) { - java_lang_Throwable *t = (java_lang_Throwable *) xptr; + if (opt_TraceExceptions) + trace_exception_builtin(xptr); +#endif /* !defined(NDEBUG) */ - utf_sprint_classname(logtext + strlen(logtext), - xptr->vftbl->class->name); + /* actually set the exception */ - if (t->detailMessage) { - char *buf; + exceptions_set_exception(xptr); - buf = javastring_tochar((java_objectheader *) t->detailMessage); - sprintf(logtext + strlen(logtext), ": %s", buf); - MFREE(buf, char, strlen(buf)); - } + /* Return a NULL pointer. This is required for vm_call_method to + check for an exception. This is for convenience. */ - } else { - sprintf(logtext + strlen(logtext), "Error: "); - } + return NULL; +} - log_text(logtext); - } - *exceptionptr = xptr; +/* builtin_canstore ************************************************************ - return xptr; -} + Checks, if an object can be stored in an array. + + Return value: 1 ... possible + 0 ... otherwise (throws an ArrayStoreException) +*******************************************************************************/ + +s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o) +{ + int result; + LLNI_CRITICAL_START; -/******************* function: builtin_canstore ******************************* + result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o)); - Checks, if an object can be stored in an array. - Return value: 1 ... possible - 0 ... otherwise + LLNI_CRITICAL_END; + + /* if not possible, throw an exception */ + + if (result == 0) + exceptions_throw_arraystoreexception(); + + return result; +} -******************************************************************************/ -s4 builtin_canstore (java_objectarray *a, java_objectheader *o) +s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *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; + int32_t baseval; + uint32_t diffval; + int result; + + if (o == NULL) + 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; - - if ((dim_m1 = desc->dimension - 1) == 0) { - s4 res; - - /* {a is a one-dimensional array} */ - /* {a is an array of references} */ + desc = oa->header.objheader.vftbl->arraydesc; + componentvftbl = desc->componentvftbl; + valuevftbl = o->vftbl; + valuedesc = valuevftbl->arraydesc; + + if ((desc->dimension - 1) == 0) { + /* {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); - if ((base = classvalues.super_baseval) <= 0) + baseval = componentvftbl->baseval; + + 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; - } - /* {a has dimension > 1} */ - /* {componentvftbl->arraydesc != NULL} */ + result = ((valuevftbl->interfacetablelength > -baseval) && + (valuevftbl->interfacetable[baseval] != NULL)); + } + else { + diffval = valuevftbl->baseval - componentvftbl->baseval; + result = diffval <= (uint32_t) componentvftbl->diffval; + } + + 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; - /* {o is an array} */ + } + else { + /* {o is an array} */ + + result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc); + } + + /* return result */ - return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc); + 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_objectarray_t *a, java_object_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): * @@ -629,30 +685,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); + + baseval = elementvftbl->baseval; - if ((base = classvalues.super_baseval) <= 0) + 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_objectarray_t *a, java_object_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): * @@ -671,12 +734,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); - res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) - <= (unsigned) classvalues.super_diffval; + diffval = valuevftbl->baseval - elementvftbl->baseval; + result = diffval <= (uint32_t) elementvftbl->diffval; - return res; + LOCK_MONITOR_EXIT(linker_classrenumber_lock); + + return result; } @@ -686,96 +751,187 @@ s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o) Return value: pointer to the object or NULL if no memory is available - + *******************************************************************************/ -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 */ - /*utf_fprint(stderr,c->name);fprintf(stderr,"\n");*/ - assert(c->loaded); + + assert(c->state & CLASS_LOADED); + + /* check if we can instantiate this class */ + + if (c->flags & ACC_ABSTRACT) { + exceptions_throw_instantiationerror(c); + return NULL; + } /* is the class linked */ - if (!c->linked) + + 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 (!initialize_class(c)) return NULL; } - o = heap_allocate(c->instancesize, true, c->finalizer); + o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS, + c->finalizer, true); if (!o) return NULL; - MSET(o, 0, u1, c->instancesize); - 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; } -/* builtin_newarray ************************************************************ - - Creates an array with the given vftbl on the heap. +/* builtin_fast_new ************************************************************ - Return value: pointer to the array or NULL if no memory is available + Creates a new instance of class c on the heap. - CAUTION: The given vftbl must be the vftbl of the *array* class, - not of the element class. + Return value: pointer to the object or NULL if no fast return + is possible for any reason. *******************************************************************************/ -java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl) +java_object_t *builtin_fast_new(classinfo *c) { - java_arrayheader *a; - arraydescriptor *desc; - s4 dataoffset; - s4 componentsize; - s4 actualsize; + 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 - desc = arrayvftbl->arraydesc; - dataoffset = desc->dataoffset; - componentsize = desc->componentsize; + RT_TIMING_GET_TIME(time_start); + CYCLES_STATS_GET(cycles_start); - if (size < 0) { - *exceptionptr = new_negativearraysizeexception(); - return NULL; - } + /* is the class loaded */ - actualsize = dataoffset + size * componentsize; + assert(c->state & CLASS_LOADED); + + /* check if we can instantiate this class */ - if (((u4) actualsize) < ((u4) size)) { /* overflow */ - *exceptionptr = new_exception(string_java_lang_OutOfMemoryError); + if (c->flags & ACC_ABSTRACT) return NULL; - } - a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL); + /* is the class linked */ - if (!a) + if (!(c->state & CLASS_LINKED)) return NULL; - MSET(a, 0, u1, actualsize); - - a->objheader.vftbl = arrayvftbl; + if (!(c->state & CLASS_INITIALIZED)) + return NULL; -#if defined(USE_THREADS) && defined(NATIVE_THREADS) - initObjectLock(&a->objheader); -#endif + o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS, + c->finalizer, false); - a->size = size; + if (!o) + return NULL; + + o->vftbl = c->vftbl; + +#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; +} + + +/* builtin_newarray ************************************************************ + + 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 + +*******************************************************************************/ + +java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass) +{ + 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) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + actualsize = dataoffset + size * componentsize; + + /* check for overflow */ + + if (((u4) actualsize) < ((u4) size)) { + exceptions_throw_outofmemoryerror(); + return NULL; + } + + a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true); + + if (a == NULL) + return NULL; + + a->objheader.vftbl = arrayclass->vftbl; + +#if defined(ENABLE_THREADS) + lock_init_object_lock(&a->objheader); +#endif + + 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; } @@ -790,183 +946,188 @@ java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl) *******************************************************************************/ -java_objectarray *builtin_anewarray(s4 size, classinfo *component) +java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass) { - classinfo *c; + classinfo *arrayclass; /* is class loaded */ - assert(component->loaded); + + assert(componentclass->state & CLASS_LOADED); /* is class linked */ - if (!component->linked) - if (!link_class(component)) + + if (!(componentclass->state & CLASS_LINKED)) + if (!link_class(componentclass)) return NULL; - c = class_array_of(component, true); + arrayclass = class_array_of(componentclass, true); - if (!c) + if (!arrayclass) return NULL; - return (java_objectarray *) builtin_newarray(size, c->vftbl); + return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass); } -/* builtin_newarray_int ******************************************************** - - Creates an array of 32 bit Integers on the heap. +/* builtin_newarray_boolean **************************************************** + 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_handle_booleanarray_t *builtin_newarray_boolean(s4 size) { - return (java_intarray *) - builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl); + return (java_handle_booleanarray_t *) + builtin_newarray(size, + primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass); } -/* 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 *******************************************************************************/ -java_longarray *builtin_newarray_long(s4 size) +java_handle_bytearray_t *builtin_newarray_byte(s4 size) { - return (java_longarray *) - builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl); + return (java_handle_bytearray_t *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass); } -/* 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 *******************************************************************************/ -java_floatarray *builtin_newarray_float(s4 size) +java_handle_chararray_t *builtin_newarray_char(s4 size) { - return (java_floatarray *) - builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl); + return (java_handle_chararray_t *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass); } -/* 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 *******************************************************************************/ -java_doublearray *builtin_newarray_double(s4 size) +java_handle_shortarray_t *builtin_newarray_short(s4 size) { - return (java_doublearray *) - builtin_newarray(size, - primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl); + return (java_handle_shortarray_t *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass); } -/* 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 *******************************************************************************/ -java_bytearray *builtin_newarray_byte(s4 size) +java_handle_intarray_t *builtin_newarray_int(s4 size) { - return (java_bytearray *) - builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl); + return (java_handle_intarray_t *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass); } -/* 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 *******************************************************************************/ -java_chararray *builtin_newarray_char(s4 size) +java_handle_longarray_t *builtin_newarray_long(s4 size) { - return (java_chararray *) - builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl); + return (java_handle_longarray_t *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass); } -/* 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 *******************************************************************************/ -java_shortarray *builtin_newarray_short(s4 size) +java_handle_floatarray_t *builtin_newarray_float(s4 size) { - return (java_shortarray *) - builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl); + return (java_handle_floatarray_t *) + builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass); } -/* builtin_newarray_boolean **************************************************** +/* builtin_newarray_double ***************************************************** + + Creates an array of 64 bit IEEE floats on the heap. - 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_booleanarray *builtin_newarray_boolean(s4 size) +java_handle_doublearray_t *builtin_newarray_double(s4 size) { - return (java_booleanarray *) + return (java_handle_doublearray_t *) builtin_newarray(size, - primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl); + primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass); } -/* builtin_multianewarray ****************************************************** +/* builtin_multianewarray_intern *********************************************** 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 + 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 ******************************************************************************/ -java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims) +static java_handle_t *builtin_multianewarray_intern(int n, + classinfo *arrayclass, + long *dims) { - s4 size, i; - java_arrayheader *a; - vftbl_t *componentvftbl; + s4 size; + java_handle_t *a; + classinfo *componentclass; + s4 i; /* create this dimension */ size = (s4) dims[0]; - a = builtin_newarray(size, arrayvftbl); + a = builtin_newarray(size, arrayclass); if (!a) return NULL; @@ -976,30 +1137,70 @@ java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims) if (!--n) return a; - /* get the vftbl of the components to create */ + /* get the class of the components to create */ - componentvftbl = arrayvftbl->arraydesc->componentvftbl; + 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_multianewarray(n, componentvftbl, dims + 1); + java_handle_t *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; - - ((java_objectarray *) a)->data[i] = (java_objectheader *) ea; + + LLNI_objectarray_element_set((java_handle_objectarray_t *) a, i, ea); } return a; } +/* builtin_multianewarray ****************************************************** + + Wrapper for builtin_multianewarray_intern which checks all + dimensions before we start allocating. + +******************************************************************************/ + +java_handle_objectarray_t *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 (java_handle_objectarray_t *) + builtin_multianewarray_intern(n, arrayclass, dims); +} + + /***************************************************************************** METHOD LOGGING @@ -1008,468 +1209,443 @@ java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims) *****************************************************************************/ -u4 methodindent = 0; +/* builtin_print_argument ****************************************************** -java_objectheader *builtin_trace_exception(java_objectheader *xptr, - methodinfo *m, - void *pos, - s4 line, - s4 noindent) + 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) { - char logtext[MAXLOGTEXT]; - - if (!noindent) { - if (methodindent) - methodindent--; - else - log_text("WARNING: unmatched methodindent--"); - } - if (opt_verbose || runverbose || verboseexception) { - if (xptr) { - sprintf(logtext,"Exception "); - utf_sprint_classname(logtext+strlen(logtext), xptr->vftbl->class->name); + imm_union imu; + java_object_t *o; + classinfo *c; + utf *u; + u4 len; - } else { - sprintf(logtext,"Some Throwable"); - } - sprintf(logtext+strlen(logtext), " thrown in "); + switch (paramtype->type) { + case TYPE_INT: + imu.i = (s4) value; + sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i); + break; - if (m) { - utf_sprint_classname(logtext+strlen(logtext), m->class->name); - sprintf(logtext+strlen(logtext), "."); - utf_sprint(logtext+strlen(logtext), m->name); - if (m->flags & ACC_SYNCHRONIZED) { - sprintf(logtext+strlen(logtext), "(SYNC"); + 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; - } else{ - sprintf(logtext+strlen(logtext), "(NOSYNC"); - } + 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; - if (m->flags & ACC_NATIVE) { - sprintf(logtext+strlen(logtext), ",NATIVE"); -#if POINTERSIZE == 8 - sprintf(logtext+strlen(logtext), ")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos); + 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), ")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos); + sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l); #endif + break; - } else { -#if POINTERSIZE == 8 - sprintf(logtext+strlen(logtext), ")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos); + case TYPE_ADR: +#if SIZEOF_VOID_P == 4 + sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value); #else - sprintf(logtext+strlen(logtext), ")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos); + sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value); #endif - if (m->class->sourcefile == NULL) { - sprintf(logtext+strlen(logtext), ""); - } else { - utf_sprint(logtext+strlen(logtext), m->class->sourcefile); - } - sprintf(logtext+strlen(logtext), ":%d)\n", line); + /* cast to java.lang.Object */ + + o = (java_object_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 */ - } else - sprintf(logtext+strlen(logtext), "call_java_method\n"); + logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len); + *logtextlen += len; - log_text(logtext); + /* strcat to the logtext */ + + strcat(logtext, " (Class = \""); + utf_cat_classname(logtext, u); + strcat(logtext, "\")"); + } + } } - return xptr; + return logtext; } +#endif /* !defined(NDEBUG) */ +/* builtin_verbosecall_enter *************************************************** + + Print method call with arguments for -verbose:call. + +*******************************************************************************/ + +#if !defined(NDEBUG) #ifdef TRACE_ARGS_NUM -void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, -#if TRACE_ARGS_NUM >= 6 - s8 a4, s8 a5, +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; + s4 logtextlen; + s4 dumpsize; + s4 i; + s4 pos; + int methodindent; + int callcount; + +#if defined(ENABLE_DEBUG_FILTER) + if (! show_filters_test_verbosecall_enter(m)) return; #endif -#if TRACE_ARGS_NUM == 8 - s8 a6, s8 a7, + +#if defined(ENABLE_VMLOG) + vmlog_cacao_enter_method(m); + return; #endif - methodinfo *m) -{ - s4 i; - char logtext[MAXLOGTEXT]; - for (i = 0; i < methodindent; i++) - logtext[i] = '\t'; - if (methodindent == 0) - sprintf(logtext + methodindent, "1st_call: "); - else - 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(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"); - - sprintf(logtext + strlen(logtext), "("); + md = m->parseddesc; - switch (m->paramcount) { - case 0: - break; + methodindent = TRACEJAVACALLINDENT; -#if defined(__I386__) || defined(__POWERPC__) - case 1: - sprintf(logtext+strlen(logtext), "%llx", a0); - break; + /* calculate message length */ - case 2: - sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1); - break; + logtextlen = + strlen("4294967295 ") + + strlen("-2147483647-") + /* INT_MAX should be sufficient */ + methodindent + + strlen("called: ") + + utf_bytes(m->class->name) + + strlen(".") + + utf_bytes(m->name) + + utf_bytes(m->descriptor); - case 3: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2); - break; + /* Actually it's not possible to have all flags printed, but: + safety first! */ - case 4: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx", - a0, a1, a2, a3); - break; + logtextlen += + strlen(" PUBLIC") + + strlen(" PRIVATE") + + strlen(" PROTECTED") + + strlen(" STATIC") + + strlen(" FINAL") + + strlen(" SYNCHRONIZED") + + strlen(" VOLATILE") + + strlen(" TRANSIENT") + + strlen(" NATIVE") + + strlen(" INTERFACE") + + strlen(" ABSTRACT"); -#if TRACE_ARGS_NUM >= 6 - case 5: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx", - a0, a1, a2, a3, a4); - break; + /* add maximal argument length */ - case 6: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx", - a0, a1, a2, a3, a4, a5); - break; -#endif /* TRACE_ARGS_NUM >= 6 */ + logtextlen += + strlen("(") + + strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM + + strlen("...(255)") + + strlen(")"); -#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); - break; + /* allocate memory */ - case 8: - sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx", - a0, a1, a2, a3, a4, a5, a6, a7); - break; + dumpsize = dump_size(); - 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); - break; -#endif /* TRACE_ARGS_NUM == 8 */ -#else /* defined(__I386__) || defined(__POWERPC__) */ - case 1: - sprintf(logtext+strlen(logtext), "%lx", a0); - break; + logtext = DMNEW(char, logtextlen); - case 2: - sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1); - break; + callcount = ++TRACEJAVACALLCOUNT; - case 3: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2); - break; + sprintf(logtext, "%10d ", callcount); + sprintf(logtext + strlen(logtext), "-%d-", methodindent); - case 4: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx", - a0, a1, a2, a3); - break; + pos = strlen(logtext); -#if TRACE_ARGS_NUM >= 6 - case 5: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx", - a0, a1, a2, a3, a4); - break; + for (i = 0; i < methodindent; i++) + logtext[pos++] = '\t'; + + strcpy(logtext + pos, "called: "); + + utf_cat_classname(logtext, m->class->name); + strcat(logtext, "."); + 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"); + 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, "("); + + if (md->paramcount >= 1) { + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[0], a0); + } - case 6: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx", - a0, a1, a2, a3, a4, a5); - break; -#endif /* TRACE_ARGS_NUM >= 6 */ + if (md->paramcount >= 2) { + strcat(logtext, ", "); -#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); - break; + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[1], a1); + } - case 8: - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx", - a0, a1, a2, a3, a4, a5, a6, a7); - break; -#endif /* TRACE_ARGS_NUM == 8 */ +#if TRACE_ARGS_NUM >= 4 + if (md->paramcount >= 3) { + strcat(logtext, ", "); - default: -#if TRACE_ARGS_NUM == 4 - sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)", - a0, a1, a2, a3, m->paramcount - 4); + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[2], a2); + } -#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); + if (md->paramcount >= 4) { + strcat(logtext, ", "); -#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); + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[3], a3); + } #endif - break; -#endif /* defined(__I386__) || defined(__POWERPC__) */ + +#if TRACE_ARGS_NUM >= 6 + if (md->paramcount >= 5) { + strcat(logtext, ", "); + + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[4], a4); } - sprintf(logtext + strlen(logtext), ")"); - log_text(logtext); + if (md->paramcount >= 6) { + strcat(logtext, ", "); - methodindent++; -} + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[5], a5); + } #endif +#if TRACE_ARGS_NUM == 8 + if (md->paramcount >= 7) { + strcat(logtext, ", "); -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"); + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[6], a6); + } - log_text(logtext); - methodindent++; -} + if (md->paramcount >= 8) { + strcat(logtext, ", "); + logtext = builtin_print_argument(logtext, &logtextlen, + &md->paramtypes[7], a7); + } +#endif -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'; - if (methodindent) - methodindent--; - else - log_text("WARNING: unmatched methodindent--"); + if (md->paramcount > 8) { + sprintf(logtext + strlen(logtext), ", ...(%d)", + md->paramcount - TRACE_ARGS_NUM); + } - 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(logtext + strlen(logtext), m->descriptor); + strcat(logtext, ")"); - switch (m->returntype) { - case TYPE_INT: - sprintf(logtext + strlen(logtext), "->%d", (s4) l); - break; + log_text(logtext); - case TYPE_LONG: -#if defined(__I386__) || defined(__POWERPC__) - sprintf(logtext + strlen(logtext), "->%lld", (s8) l); -#else - sprintf(logtext + strlen(logtext), "->%ld", (s8) l); -#endif - break; + /* release memory */ - 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 - break; + dump_release(dumpsize); - case TYPE_FLOAT: - sprintf(logtext + strlen(logtext), "->%g", f); - break; + TRACEJAVACALLINDENT++; - case TYPE_DOUBLE: - sprintf(logtext + strlen(logtext), "->%g", d); - break; - } - log_text(logtext); } +#endif +#endif /* !defined(NDEBUG) */ -/**************************************************************************** - SYNCHRONIZATION FUNCTIONS -*****************************************************************************/ +/* builtin_verbosecall_exit **************************************************** -#if defined(USE_THREADS) && !defined(NATIVE_THREADS) -/* - * Lock the mutex of an object. - */ -void internal_lock_mutex_for_object(java_objectheader *object) + Print method exit for -verbose:call. + +*******************************************************************************/ + +#if !defined(NDEBUG) +void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m) { - mutexHashEntry *entry; - int hashValue; + methoddesc *md; + char *logtext; + s4 logtextlen; + s4 dumpsize; + s4 i; + s4 pos; + imm_union val; + int methodindent; - assert(object != 0); +#if defined(ENABLE_DEBUG_FILTER) + if (! show_filters_test_verbosecall_exit(m)) return; +#endif - hashValue = MUTEX_HASH_VALUE(object); - entry = &mutexHashTable[hashValue]; +#if defined(ENABLE_VMLOG) + vmlog_cacao_leave_method(m); + return; +#endif - 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; + md = m->parseddesc; - } else { - while (entry->next != 0 && entry->object != object) - entry = entry->next; + /* outdent the log message */ - if (entry->object != object) { - entry->next = firstFreeOverflowEntry; - firstFreeOverflowEntry = firstFreeOverflowEntry->next; + if (TRACEJAVACALLINDENT) + TRACEJAVACALLINDENT--; + else + log_text("WARNING: unmatched methodindent--"); - entry = entry->next; - entry->object = 0; - entry->next = 0; - assert(entry->conditionCount == 0); - } - } + methodindent = TRACEJAVACALLINDENT; - } else { - entry->mutex.holder = 0; - entry->mutex.count = 0; - entry->mutex.muxWaiters = 0; - } + /* calculate message length */ - if (entry->object == 0) - entry->object = object; - - internal_lock_mutex(&entry->mutex); -} -#endif + logtextlen = + strlen("4294967295 ") + + strlen("-2147483647-") + /* INT_MAX should be sufficient */ + methodindent + + strlen("finished: ") + + utf_bytes(m->class->name) + + strlen(".") + + utf_bytes(m->name) + + utf_bytes(m->descriptor) + + strlen(" SYNCHRONIZED") + strlen("(") + strlen(")"); + /* add maximal argument length */ -#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; + logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)"); - hashValue = MUTEX_HASH_VALUE(object); - entry = &mutexHashTable[hashValue]; + /* allocate memory */ - if (entry->object == object) { - internal_unlock_mutex(&entry->mutex); + dumpsize = dump_size(); - } else { - while (entry->next != 0 && entry->next->object != object) - entry = entry->next; + logtext = DMNEW(char, logtextlen); - assert(entry->next != 0); + /* generate the message */ - internal_unlock_mutex(&entry->next->mutex); + sprintf(logtext, " "); + sprintf(logtext + strlen(logtext), "-%d-", methodindent); - if (entry->next->mutex.count == 0 && entry->conditionCount == 0) { - mutexHashEntry *unlinked = entry->next; + pos = strlen(logtext); - entry->next = unlinked->next; - unlinked->next = firstFreeOverflowEntry; - firstFreeOverflowEntry = unlinked; + for (i = 0; i < methodindent; i++) + logtext[pos++] = '\t'; + + strcpy(logtext + pos, "finished: "); + utf_cat_classname(logtext, m->class->name); + 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; } - } -} -#endif + logtext = + builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l); + } -#if defined(USE_THREADS) -void builtin_monitorenter(java_objectheader *o) -{ -#if !defined(NATIVE_THREADS) - int hashValue; + log_text(logtext); - ++blockInts; + /* release memory */ - 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); + dump_release(dumpsize); - --blockInts; -#else - monitorEnter((threadobject *) THREADOBJECT, o); -#endif } -#endif +#endif /* !defined(NDEBUG) */ -#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) +#if defined(ENABLE_CYCLES_STATS) +void builtin_print_cycles_stats(FILE *file) { - use_class_as_object(c); - builtin_monitorenter(&c->header); -} -#endif + fprintf(file,"builtin cylce count statistics:\n"); + CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file); + CYCLES_STATS_PRINT(builtin_new ,file); -#if defined(USE_THREADS) -void *builtin_monitorexit(java_objectheader *o) -{ -#if !defined(NATIVE_THREADS) - int hashValue; - - ++blockInts; - - 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; - return o; -#else - monitorExit((threadobject *) THREADOBJECT, o); - return o; -#endif + fprintf(file,"\n"); } -#endif +#endif /* defined(ENABLE_CYCLES_STATS) */ /***************************************************************************** @@ -1485,143 +1661,248 @@ 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; -/************** Functions for long arithmetics ******************************* + return c; +} - On systems where 64 bit Integers are not supported by the CPU, these - functions are needed. +s4 builtin_irem(s4 a, s4 b) +{ + s4 c; -******************************************************************************/ + 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; + #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) || defined (DISABLE_GC) +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); @@ -1674,25 +1955,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); + } + } } @@ -1704,18 +2024,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; } @@ -1732,11 +2063,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); @@ -1784,92 +2122,156 @@ 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 || !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 @@ -1882,31 +2284,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 @@ -1916,8 +2323,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 @@ -1927,12 +2336,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) || defined(DISABLE_GC) s4 builtin_f2i(float a) { + s4 i; - return builtin_d2i((double) a); + i = builtin_d2i((double) a); + + return i; /* float f; @@ -1950,12 +2364,17 @@ 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; - return builtin_d2l((double) a); + l = builtin_d2l((double) a); + + return l; /* float f; @@ -1973,20 +2392,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; @@ -2005,8 +2414,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; @@ -2025,7 +2436,20 @@ 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) { @@ -2038,96 +2462,210 @@ 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 */ +/* builtin_arraycopy *********************************************************** + + Builtin for java.lang.System.arraycopy. -inline float intBitsToFloat(s4 i) +*******************************************************************************/ + +void builtin_arraycopy(java_handle_t *src, s4 srcStart, + java_handle_t *dest, s4 destStart, s4 len) { - imm_union imb; + arraydescriptor *sdesc; + arraydescriptor *ddesc; + s4 i; - imb.i = i; - return imb.f; -} + if ((src == NULL) || (dest == NULL)) { + exceptions_throw_nullpointerexception(); + return; + } + sdesc = LLNI_vftbl_direct(src)->arraydesc; + ddesc = LLNI_vftbl_direct(dest)->arraydesc; -/* used to convert DBL_xxx defines into double values */ + if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) { + exceptions_throw_arraystoreexception(); + return; + } -inline float longBitsToDouble(s8 l) -{ - imm_union imb; + /* we try to throw exception with the same message as SUN does */ - imb.l = l; - return imb.d; -} + 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; + } + if (sdesc->componentvftbl == ddesc->componentvftbl) { + /* We copy primitive values or references of exactly the same type */ -java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o) -{ - return (java_arrayheader *) - Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o); -} + 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 */ -s4 builtin_dummy() -{ - panic("Internal error: builtin_dummy called (native function is missing)"); - return 0; /* for the compiler */ + 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; + + LLNI_objectarray_element_get(oas, srcStart + i, o); + + if (!builtin_canstore(oad, o)) + return; + + LLNI_objectarray_element_set(oad, 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; + + LLNI_objectarray_element_get(oas, srcStart + i, o); + + if (!builtin_canstore(oad, o)) + return; + + LLNI_objectarray_element_set(oad, destStart + i, o); + } + } + } } -/* builtin_asm_get_exceptionptrptr ********************************************* +/* builtin_nanotime ************************************************************ - this is a wrapper for calls from asmpart + Return the current time in nanoseconds. *******************************************************************************/ -#if defined(USE_THREADS) && defined(NATIVE_THREADS) -java_objectheader **builtin_asm_get_exceptionptrptr() +s8 builtin_nanotime(void) { - return builtin_get_exceptionptrptr(); + struct timeval tv; + s8 usecs; + + if (gettimeofday(&tv, NULL) == -1) + vm_abort("gettimeofday failed: %s", strerror(errno)); + + usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec; + + return usecs * 1000; } -#endif -methodinfo *builtin_asm_get_threadrootmethod() +/* builtin_currenttimemillis *************************************************** + + Return the current time in milliseconds. + +*******************************************************************************/ + +s8 builtin_currenttimemillis(void) { - return *threadrootmethod; + s8 msecs; + + msecs = builtin_nanotime() / 1000 / 1000; + + return msecs; } -inline void* builtin_asm_get_stackframeinfo() +/* builtin_clone *************************************************************** + + Function for cloning objects or arrays. + +*******************************************************************************/ + +java_handle_t *builtin_clone(void *env, java_handle_t *o) { -/*log_text("builtin_asm_get_stackframeinfo()");*/ -#if defined(USE_THREADS) && defined(NATIVE_THREADS) - /*printf("stackframeinfo: %p,%p\n",&THREADINFO->_stackframeinfo,*(&THREADINFO->_stackframeinfo));*/ - return &THREADINFO->_stackframeinfo; -#else -#if defined(__GNUC__) -#warning FIXME FOR OLD THREAD IMPL (jowenn) + arraydescriptor *ad; + java_handle_t *ah; + u4 size; + classinfo *c; + java_handle_t *co; /* cloned object header */ + + /* get the array descriptor */ + + ad = LLNI_vftbl_direct(o)->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_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true); + + if (co == NULL) + return NULL; + + MCOPY(co, o, u1, size); + +#if defined(ENABLE_GC_CACAO) + heap_init_objectheader(co, size); #endif - return &_thread_nativestackframeinfo; /* no threading, at least no native*/ + +#if defined(ENABLE_THREADS) + lock_init_object_lock(co); #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*/ + 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 */ + + LLNI_class_get(o, c); + + /* 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 - 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 + +#if defined(ENABLE_THREADS) + lock_init_object_lock(co); #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; + + return co; } +#if defined(ENABLE_VMLOG) +#define NDEBUG +#include +#endif + + /* * 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 @@ -2139,4 +2677,5 @@ stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelem * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */