X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fvm.c;h=ea79bcc71946caef7fadd6fa1f59dd49e9eb0432;hb=8c81647e1c96715f45498a3ada7f795b5c9dfe81;hp=4c7c09d2949878a0e8e656567d3d9fcbc5297d45;hpb=9f859ad50d3d5d98c185d40b86b2179bc4dc9aeb;p=cacao.git diff --git a/src/vm/vm.c b/src/vm/vm.c index 4c7c09d29..ea79bcc71 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -1,9 +1,7 @@ /* src/vm/vm.c - VM startup and shutdown functions - 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 + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -39,11 +37,13 @@ #include "vm/jit/abi-asm.h" +#include "mm/codememory.h" #include "mm/gc-common.h" #include "mm/memory.h" #include "native/jni.h" #include "native/llni.h" +#include "native/localref.h" #include "native/native.h" #include "native/include/java_lang_Object.h" /* required by j.l.C */ @@ -58,24 +58,41 @@ #include "native/vm/nativevm.h" -#include "threads/threads-common.h" +#include "threads/lock-common.h" +#include "threads/mutex.h" +#include "threads/threadlist.h" +#include "threads/thread.h" #include "toolbox/logging.h" +#include "vm/array.h" + +#if defined(ENABLE_ASSERTION) +#include "vm/assertion.h" +#endif + #include "vm/builtin.h" #include "vm/exceptions.h" #include "vm/finalizer.h" #include "vm/global.h" #include "vm/initialize.h" +#include "vm/package.h" #include "vm/primitive.h" #include "vm/properties.h" #include "vm/signallocal.h" #include "vm/stringlocal.h" #include "vm/vm.h" -#include "vm/jit/jit.h" -#include "vm/jit/md.h" +#include "vm/jit/argument.h" #include "vm/jit/asmpart.h" +#include "vm/jit/code.h" + +#if defined(ENABLE_DISASSEMBLER) +# include "vm/jit/disass.h" +#endif + +#include "vm/jit/jit.h" +#include "vm/jit/methodtree.h" #if defined(ENABLE_PROFILING) # include "vm/jit/optimizing/profile.h" @@ -83,10 +100,17 @@ #include "vm/jit/optimizing/recompile.h" +#if defined(ENABLE_PYTHON) +# include "vm/jit/python.h" +#endif + +#include "vm/jit/trap.h" + #include "vmcore/classcache.h" #include "vmcore/options.h" #include "vmcore/statistics.h" #include "vmcore/suck.h" +#include "vmcore/system.h" #if defined(ENABLE_JVMTI) # include "native/jvmti/cacaodbg.h" @@ -108,7 +132,8 @@ _Jv_JNIEnv *_Jv_env; /* pointer to native method interface */ s4 vms = 0; /* number of VMs created */ bool vm_initializing = false; -bool vm_exiting = false; +bool vm_created = false; +bool vm_exiting = false; char *mainstring = NULL; classinfo *mainclass = NULL; @@ -122,7 +147,7 @@ u1 *intrp_main_stack = NULL; #define HEAP_MAXSIZE 128 * 1024 * 1024 /* default 128MB */ #define HEAP_STARTSIZE 2 * 1024 * 1024 /* default 2MB */ -#define STACK_SIZE 64 * 1024 /* default 64kB */ +#define STACK_SIZE 128 * 1024 /* default 64kB */ /* define command line options ************************************************/ @@ -152,6 +177,9 @@ enum { OPT_EA, OPT_DA, + OPT_EA_NOARG, + OPT_DA_NOARG, + OPT_ESA, OPT_DSA, @@ -218,19 +246,6 @@ enum { OPT_LSRA, #endif -#if defined(ENABLE_INLINING) - OPT_INLINING, -#if !defined(NDEBUG) - OPT_INLINE_LOG, -#endif -#if defined(ENABLE_INLINING_DEBUG) - OPT_INLINE_DEBUG_ALL, - OPT_INLINE_DEBUG_END, - OPT_INLINE_DEBUG_MIN, - OPT_INLINE_DEBUG_MAX, -#endif /* defined(ENABLE_INLINING_DEBUG) */ -#endif /* defined(ENABLE_INLINING) */ - #if defined(ENABLE_INTRP) /* interpreter options */ @@ -285,12 +300,16 @@ opt_struct opts[] = { { "?", false, OPT_HELP }, { "X", false, OPT_X }, { "XX:", true, OPT_XX }, - { "XX", false, OPT_XX }, { "ea:", true, OPT_EA }, { "da:", true, OPT_DA }, - { "ea", false, OPT_EA }, - { "da", false, OPT_DA }, + { "ea", false, OPT_EA_NOARG }, + { "da", false, OPT_DA_NOARG }, + + { "enableassertions:", true, OPT_EA }, + { "disableassertions:", true, OPT_DA }, + { "enableassertions", false, OPT_EA_NOARG }, + { "disableassertions", false, OPT_DA_NOARG }, { "esa", false, OPT_ESA }, { "enablesystemassertions", false, OPT_ESA }, @@ -330,9 +349,12 @@ opt_struct opts[] = { #if defined(ENABLE_IFCONV) { "ifconv", false, OPT_IFCONV }, #endif -#if defined(ENABLE_LSRA) || defined(ENABLE_SSA) +#if defined(ENABLE_LSRA) { "lsra", false, OPT_LSRA }, #endif +#if defined(ENABLE_SSA) + { "lsra", true, OPT_LSRA }, +#endif #if defined(ENABLE_INTRP) /* interpreter options */ @@ -377,21 +399,6 @@ opt_struct opts[] = { { "Xprof", false, OPT_PROF }, #endif - /* inlining options */ - -#if defined(ENABLE_INLINING) -#if defined(ENABLE_INLINING_DEBUG) - { "ia", false, OPT_INLINE_DEBUG_ALL }, - { "ii", true, OPT_INLINE_DEBUG_MIN }, - { "im", true, OPT_INLINE_DEBUG_MAX }, - { "ie", true, OPT_INLINE_DEBUG_END }, -#endif /* defined(ENABLE_INLINING_DEBUG) */ -#if !defined(NDEBUG) - { "il", false, OPT_INLINE_LOG }, -#endif - { "i", false, OPT_INLINING }, -#endif /* defined(ENABLE_INLINING) */ - /* keep these at the end of the list */ #if !defined(NDEBUG) @@ -509,8 +516,7 @@ static void XXusage(void) { puts(" -v write state-information"); #if !defined(NDEBUG) - puts(" -verbose[:jit|threads]"); - puts(" enable specific verbose output"); + puts(" -verbose:jit enable specific verbose output"); puts(" -debug-color colored output for ANSI terms"); #endif #ifdef TYPECHECK_VERBOSE @@ -547,24 +553,9 @@ static void XXusage(void) #if defined(ENABLE_DISASSEMBLER) puts(" (a)ssembler disassembled listing"); puts(" n(o)ps show NOPs in disassembler output"); - puts(" (e)xceptionstubs disassembled exception stubs (only with -sa)"); - puts(" (n)ative disassembled native stubs"); #endif puts(" (d)atasegment data segment listing"); -#if defined(ENABLE_INLINING) - puts(" -i activate inlining"); -#if !defined(NDEBUG) - puts(" -il log inlining"); -#endif -#if defined(ENABLE_INLINING_DEBUG) - puts(" -ia use inlining for all methods"); - puts(" -ii set minimum size for inlined result"); - puts(" -im set maximum size for inlined result"); - puts(" -ie stop inlining after the given number of roots"); -#endif /* defined(ENABLE_INLINING_DEBUG) */ -#endif /* defined(ENABLE_INLINING) */ - #if defined(ENABLE_IFCONV) puts(" -ifconv use if-conversion"); #endif @@ -572,7 +563,9 @@ static void XXusage(void) puts(" -lsra use linear scan register allocation"); #endif #if defined(ENABLE_SSA) - puts(" -lsra use linear scan register allocation (with SSA)"); + puts(" -lsra:... use linear scan register allocation (with SSA)"); + puts(" (d)ead code elimination"); + puts(" (c)opy propagation"); #endif #if defined(ENABLE_DEBUG_FILTER) puts(" -XXfi begin of dynamic scope for verbosecall filter"); @@ -595,22 +588,12 @@ static void XXusage(void) static void version(bool opt_exit) { puts("java version \""JAVA_VERSION"\""); - puts("CACAO version "VERSION""); - - puts("Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,"); - puts("C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,"); - puts("E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,"); - puts("J. Wenninger, Institut f. Computersprachen - TU Wien\n"); - - puts("This program is free software; you can redistribute it and/or"); - puts("modify it under the terms of the GNU General Public License as"); - puts("published by the Free Software Foundation; either version 2, or (at"); - puts("your option) any later version.\n"); + puts("CACAO version "VERSION"\n"); - puts("This program is distributed in the hope that it will be useful, but"); - puts("WITHOUT ANY WARRANTY; without even the implied warranty of"); - puts("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU"); - puts("General Public License for more details."); + puts("Copyright (C) 1996-2005, 2006, 2007, 2008"); + puts("CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO"); + puts("This is free software; see the source for copying conditions. There is NO"); + puts("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."); /* exit normally, if requested */ @@ -636,7 +619,7 @@ static void fullversion(void) } -void vm_printconfig(void) +static void vm_printconfig(void) { puts("Configure/Build options:\n"); puts(" ./configure: "VERSION_CONFIGURE_ARGS""); @@ -652,7 +635,7 @@ void vm_printconfig(void) printf(" initial heap size : %d\n", HEAP_STARTSIZE); printf(" stack size : %d\n", STACK_SIZE); -#if defined(WITH_JRE_LAYOUT) +#if defined(ENABLE_JRE_LAYOUT) /* When we're building with JRE-layout, the default paths are the same as the runtime paths. */ #else @@ -738,13 +721,6 @@ bool vm_createjvm(JavaVM **p_vm, void **p_env, void *vm_args) if (!vm_create(_vm_args)) goto error; -#if defined(ENABLE_JNI) - /* setup the local ref table (must be created after vm_create) */ - - if (!localref_table_init()) - goto error; -#endif - /* now return the values */ *p_vm = (JavaVM *) vm; @@ -786,32 +762,50 @@ bool vm_create(JavaVMInitArgs *vm_args) jdwp = agentbypath = false; #endif -#if defined(ENABLE_VMLOG) - vmlog_cacao_init(vm_args); -#endif - - /* check the JNI version requested */ +#if defined(ENABLE_JNI) + /* Check the JNI version requested. */ - switch (vm_args->version) { - case JNI_VERSION_1_1: - break; - case JNI_VERSION_1_2: - case JNI_VERSION_1_4: - break; - default: + if (!jni_version_check(vm_args->version)) return false; - } +#endif - /* we only support 1 JVM instance */ + /* We only support 1 JVM instance. */ if (vms > 0) return false; + /* Install the exit handler. */ + if (atexit(vm_exit_handler)) vm_abort("atexit failed: %s\n", strerror(errno)); - if (opt_verbose) - log_text("CACAO started -------------------------------------------------------"); + /* Set some options. */ + + opt_version = false; + opt_exit = false; + + opt_noieee = false; + + opt_heapmaxsize = HEAP_MAXSIZE; + opt_heapstartsize = HEAP_STARTSIZE; + opt_stacksize = STACK_SIZE; + + /* Initialize the properties list before command-line handling. + Otherwise -XX:+PrintConfig crashes. */ + + properties_init(); + + /* First of all, parse the -XX options. */ + +#if defined(ENABLE_VMLOG) + vmlog_cacao_init_options(); +#endif + + options_xx(vm_args); + +#if defined(ENABLE_VMLOG) + vmlog_cacao_init(); +#endif /* We need to check if the actual size of a java.lang.Class object is smaller or equal than the assumption made in @@ -824,26 +818,13 @@ bool vm_create(JavaVMInitArgs *vm_args) _Jv_jvm->starttime = builtin_currenttimemillis(); - /* interpret the options **************************************************/ - - opt_version = false; - opt_exit = false; - - opt_noieee = false; - - opt_heapmaxsize = HEAP_MAXSIZE; - opt_heapstartsize = HEAP_STARTSIZE; - opt_stacksize = STACK_SIZE; - - #if defined(ENABLE_JVMTI) /* initialize JVMTI related **********************************************/ jvmti = false; #endif - /* Initialize and fill properties before command-line handling. */ + /* Fill the properties before command-line handling. */ - properties_init(); properties_set(); /* iterate over all passed options */ @@ -1070,9 +1051,6 @@ bool vm_create(JavaVMInitArgs *vm_args) initverbose = true; compileverbose = true; } - else if (strcmp("threads", opt_arg) == 0) { - opt_verbosethreads = true; - } #endif else { printf("Unknown -verbose option: %s\n", opt_arg); @@ -1195,14 +1173,6 @@ bool vm_create(JavaVMInitArgs *vm_args) case 'o': opt_shownops = true; break; - - case 'e': - opt_showexceptionstubs = true; - break; - - case 'n': - opt_shownativestub = true; - break; #endif case 'd': @@ -1221,41 +1191,37 @@ bool vm_create(JavaVMInitArgs *vm_args) break; #endif -#if defined(ENABLE_INLINING) -#if defined(ENABLE_INLINING_DEBUG) - case OPT_INLINE_DEBUG_ALL: - opt_inline_debug_all = true; - break; - case OPT_INLINE_DEBUG_END: - opt_inline_debug_end_counter = atoi(opt_arg); - break; - case OPT_INLINE_DEBUG_MIN: - opt_inline_debug_min_size = atoi(opt_arg); - break; - case OPT_INLINE_DEBUG_MAX: - opt_inline_debug_max_size = atoi(opt_arg); - break; -#endif /* defined(ENABLE_INLINING_DEBUG) */ -#if !defined(NDEBUG) - case OPT_INLINE_LOG: - opt_inline_debug_log = true; - break; -#endif /* !defined(NDEBUG) */ - - case OPT_INLINING: - opt_inlining = true; - break; -#endif /* defined(ENABLE_INLINING) */ - #if defined(ENABLE_IFCONV) case OPT_IFCONV: opt_ifconv = true; break; #endif -#if defined(ENABLE_LSRA) || defined(ENABLE_SSA) +#if defined(ENABLE_LSRA) + case OPT_LSRA: + opt_lsra = true; + break; +#endif +#if defined(ENABLE_SSA) case OPT_LSRA: opt_lsra = true; + for (i = 0; i < strlen(opt_arg); i++) { + switch (opt_arg[i]) { + case 'c': + opt_ssa_cp = true; + break; + + case 'd': + opt_ssa_dce = true; + break; + + case ':': + break; + + default: + usage(); + } + } break; #endif @@ -1268,23 +1234,43 @@ bool vm_create(JavaVMInitArgs *vm_args) break; case OPT_XX: - options_xx(opt_arg); + /* Already parsed. */ break; case OPT_EA: - /* currently ignored */ +#if defined(ENABLE_ASSERTION) + assertion_ea_da(opt_arg, true); +#endif break; case OPT_DA: - /* currently ignored */ +#if defined(ENABLE_ASSERTION) + assertion_ea_da(opt_arg, false); +#endif + break; + + case OPT_EA_NOARG: +#if defined(ENABLE_ASSERTION) + assertion_user_enabled = true; +#endif + break; + + case OPT_DA_NOARG: +#if defined(ENABLE_ASSERTION) + assertion_user_enabled = false; +#endif break; case OPT_ESA: - _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = true; +#if defined(ENABLE_ASSERTION) + assertion_system_enabled = true; +#endif break; case OPT_DSA: - _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = false; +#if defined(ENABLE_ASSERTION) + assertion_system_enabled = false; +#endif break; #if defined(ENABLE_PROFILING) @@ -1429,10 +1415,16 @@ bool vm_create(JavaVMInitArgs *vm_args) gc_init(opt_heapmaxsize, opt_heapstartsize); #if defined(ENABLE_THREADS) + /* BEFORE: threads_preinit */ + + threadlist_init(); + /* AFTER: gc_init (directly after, as this initializes the stopworldlock lock */ threads_preinit(); + lock_init(); + critical_init(); #endif /* install architecture dependent signal handlers */ @@ -1456,8 +1448,7 @@ bool vm_create(JavaVMInitArgs *vm_args) /* AFTER: threads_preinit */ - if (!utf8_init()) - vm_abort("vm_create: utf8_init failed"); + utf8_init(); /* AFTER: thread_preinit */ @@ -1485,11 +1476,10 @@ bool vm_create(JavaVMInitArgs *vm_args) if (!classcache_init()) vm_abort("vm_create: classcache_init failed"); - /* initialize the memory subsystem (must be done _after_ - threads_preinit) */ + /* Initialize the code memory management. */ + /* AFTER: threads_preinit */ - if (!memory_init()) - vm_abort("vm_create: memory_init failed"); + codememory_init(); /* initialize the finalizer stuff (must be done _after_ threads_preinit) */ @@ -1497,44 +1487,40 @@ bool vm_create(JavaVMInitArgs *vm_args) if (!finalizer_init()) vm_abort("vm_create: finalizer_init failed"); - /* initialize the codegen subsystems */ + /* Initialize the JIT compiler. */ - codegen_init(); + jit_init(); + code_init(); + methodtree_init(); - /* initializes jit compiler */ +#if defined(ENABLE_PYTHON) + pythonpass_init(); +#endif - jit_init(); + /* BEFORE: loader_preinit */ - /* machine dependent initialization */ + package_init(); -#if defined(ENABLE_JIT) -# if defined(ENABLE_INTRP) - if (opt_intrp) - intrp_md_init(); - else -# endif - md_init(); -#else - intrp_md_init(); -#endif + /* AFTER: utf8_init, classcache_init */ - /* initialize the loader subsystems (must be done _after_ - classcache_init) */ + loader_preinit(); + linker_preinit(); - if (!loader_init()) - vm_abort("vm_create: loader_init failed"); + /* AFTER: loader_preinit, linker_preinit */ - /* Link some important VM classes. */ - /* AFTER: utf8_init */ + primitive_init(); + + loader_init(); + linker_init(); - if (!linker_init()) - vm_abort("vm_create: linker_init failed"); + /* AFTER: loader_init, linker_init */ - if (!primitive_init()) - vm_abort("vm_create: primitive_init failed"); + primitive_postinit(); + method_init(); - if (!exceptions_init()) - vm_abort("vm_create: exceptions_init failed"); +#if defined(ENABLE_JIT) + trap_init(); +#endif if (!builtin_init()) vm_abort("vm_create: builtin_init failed"); @@ -1548,8 +1534,7 @@ bool vm_create(JavaVMInitArgs *vm_args) /* Register the native methods implemented in the VM. */ /* BEFORE: threads_init */ - if (!nativevm_preinit()) - vm_abort("vm_create: nativevm_preinit failed"); + nativevm_preinit(); #if defined(ENABLE_JNI) /* Initialize the JNI subsystem (must be done _before_ @@ -1560,16 +1545,27 @@ bool vm_create(JavaVMInitArgs *vm_args) vm_abort("vm_create: jni_init failed"); #endif +#if defined(ENABLE_JNI) || defined(ENABLE_HANDLES) + /* Initialize the local reference table for the main thread. */ + /* BEFORE: threads_init */ + + if (!localref_table_init()) + vm_abort("vm_create: localref_table_init failed"); +#endif + + /* Iinitialize some important system classes. */ + /* BEFORE: threads_init */ + + initialize_init(); + #if defined(ENABLE_THREADS) - if (!threads_init()) - vm_abort("vm_create: threads_init failed"); + threads_init(); #endif /* Initialize the native VM subsystem. */ /* AFTER: threads_init (at least for SUN's classes) */ - if (!nativevm_init()) - vm_abort("vm_create: nativevm_init failed"); + nativevm_init(); #if defined(ENABLE_PROFILING) /* initialize profiling */ @@ -1622,20 +1618,31 @@ bool vm_create(JavaVMInitArgs *vm_args) #endif #if defined(ENABLE_JVMTI) +# if defined(ENABLE_GC_CACAO) + /* XXX this will not work with the new indirection cells for classloaders!!! */ + assert(0); +# endif if (jvmti) { /* add agent library to native library hashtable */ native_hashtable_library_add(utf_new_char(libname), class_java_lang_Object->classloader, handle); } #endif - /* increment the number of VMs */ + /* Increment the number of VMs. */ vms++; - /* initialization is done */ + /* Initialization is done, VM is created.. */ + vm_created = true; vm_initializing = false; + /* Print the VM configuration after all stuff is set and the VM is + initialized. */ + + if (opt_PrintConfig) + vm_printconfig(); + /* everything's ok */ return true; @@ -1658,8 +1665,12 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) s4 oalength; utf *u; java_handle_t *s; - s4 status; - s4 i; + int status; + int i; + +#if defined(ENABLE_THREADS) + threadobject *t; +#endif #if !defined(NDEBUG) if (compileall) { @@ -1751,7 +1762,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) u = utf_new_char(vm_args->options[opt_index + i].optionString); s = javastring_new(u); - LLNI_objectarray_element_set(oa, i, s); + array_objectarray_element_set(oa, i, s); } #ifdef TYPEINFO_DEBUG_TEST @@ -1785,11 +1796,21 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) status = 1; } - /* unload the JavaVM */ +#if defined(ENABLE_THREADS) + /* Detach the main thread so that it appears to have ended when + the application's main method exits. */ + + t = thread_get_current(); + + if (!threads_detach_thread(t)) + vm_abort("vm_run: Could not detach main thread."); +#endif + + /* Destroy the JavaVM. */ (void) vm_destroy(vm); - /* and exit */ + /* And exit. */ vm_exit(status); } @@ -1801,13 +1822,30 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) *******************************************************************************/ -s4 vm_destroy(JavaVM *vm) +int vm_destroy(JavaVM *vm) { #if defined(ENABLE_THREADS) + /* Create a a trivial new Java waiter thread called + "DestroyJavaVM". */ + + JavaVMAttachArgs args; + + args.name = "DestroyJavaVM"; + args.group = NULL; + + if (!threads_attach_current_thread(&args, false)) + return 1; + + /* Wait until we are the last non-daemon thread. */ + threads_join_all_threads(); #endif - /* everything's ok */ + /* VM is gone. */ + + vm_created = false; + + /* Everything is ok. */ return 0; } @@ -1889,9 +1927,9 @@ void vm_shutdown(s4 status) #if defined(ENABLE_JVMTI) /* terminate cacaodbgserver */ if (dbgcom!=NULL) { - pthread_mutex_lock(&dbgcomlock); + mutex_lock(&dbgcomlock); dbgcom->running=1; - pthread_mutex_unlock(&dbgcomlock); + mutex_unlock(&dbgcomlock); jvmti_cacaodbgserver_quit(); } #endif @@ -1965,13 +2003,104 @@ void vm_exit_handler(void) Prints an error message and aborts the VM. + IN: + text ... error message to print + *******************************************************************************/ void vm_abort(const char *text, ...) { va_list ap; - /* print the log message */ + /* Print the log message. */ + + log_start(); + + va_start(ap, text); + log_vprint(text, ap); + va_end(ap); + + log_finish(); + + /* Now abort the VM. */ + + system_abort(); +} + + +/* vm_abort_errnum ************************************************************* + + Prints an error message, appends ":" plus the strerror-message of + errnum and aborts the VM. + + IN: + errnum ... error number + text ..... error message to print + +*******************************************************************************/ + +void vm_abort_errnum(int errnum, const char *text, ...) +{ + va_list ap; + + /* Print the log message. */ + + log_start(); + + va_start(ap, text); + log_vprint(text, ap); + va_end(ap); + + /* Print the strerror-message of errnum. */ + + log_print(": %s", system_strerror(errnum)); + + log_finish(); + + /* Now abort the VM. */ + + system_abort(); +} + + +/* vm_abort_errno ************************************************************** + + Equal to vm_abort_errnum, but uses errno to get the error number. + + IN: + text ... error message to print + +*******************************************************************************/ + +void vm_abort_errno(const char *text, ...) +{ + va_list ap; + + va_start(ap, text); + vm_abort_errnum(errno, text, ap); + va_end(ap); +} + + +/* vm_abort_disassemble ******************************************************** + + Prints an error message, disassemble the given code range (if + enabled) and aborts the VM. + + IN: + pc.......PC to disassemble + count....number of instructions to disassemble + +*******************************************************************************/ + +void vm_abort_disassemble(void *pc, int count, const char *text, ...) +{ + va_list ap; +#if defined(ENABLE_DISASSEMBLER) + int i; +#endif + + /* Print debug message. */ log_start(); @@ -1981,9 +2110,24 @@ void vm_abort(const char *text, ...) log_finish(); - /* now abort the VM */ + /* Print the PC. */ + +#if SIZEOF_VOID_P == 8 + log_println("PC=0x%016lx", pc); +#else + log_println("PC=0x%08x", pc); +#endif + +#if defined(ENABLE_DISASSEMBLER) + log_println("machine instructions at PC:"); + + /* Disassemble the given number of instructions. */ + + for (i = 0; i < count; i++) + pc = disassinstr(pc); +#endif - abort(); + vm_abort("Aborting..."); } @@ -2059,7 +2203,9 @@ static char *vm_get_mainclass_from_jar(char *mainstring) /* get Main Attributes */ - m = class_resolveclassmethod(o->vftbl->class, + LLNI_class_get(o, c); + + m = class_resolveclassmethod(c, utf_new_char("getMainAttributes"), utf_new_char("()Ljava/util/jar/Attributes;"), class_java_lang_Object, @@ -2080,7 +2226,9 @@ static char *vm_get_mainclass_from_jar(char *mainstring) /* get property Main-Class */ - m = class_resolveclassmethod(o->vftbl->class, + LLNI_class_get(o, c); + + m = class_resolveclassmethod(c, utf_new_char("getValue"), utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"), class_java_lang_Object, @@ -2096,7 +2244,8 @@ static char *vm_get_mainclass_from_jar(char *mainstring) o = vm_call_method(m, o, s); if (o == NULL) { - exceptions_print_stacktrace(); + fprintf(stderr, "Failed to load Main-Class manifest attribute from\n"); + fprintf(stderr, "%s\n", mainstring); return NULL; } @@ -2227,537 +2376,59 @@ static void vm_compile_method(void) #endif /* !defined(NDEBUG) */ -/* vm_array_store_int ********************************************************** +/* vm_call_array *************************************************************** + + Calls a Java method with a variable number of arguments, passed via + an argument array. - Helper function to store an integer into the argument array, taking - care of architecture specific issues. + ATTENTION: This function has to be used outside the nativeworld. *******************************************************************************/ -static void vm_array_store_int(uint64_t *array, paramdesc *pd, int32_t value) -{ - int32_t index; - - if (!pd->inmemory) { - index = pd->index; - array[index] = (int64_t) value; - } - else { - index = ARG_CNT + pd->index; -#if SIZEOF_VOID_P == 8 - array[index] = (int64_t) value; -#else -# if WORDS_BIGENDIAN == 1 - array[index] = ((int64_t) value) << 32; -# else - array[index] = (int64_t) value; -# endif -#endif - } +#define VM_CALL_ARRAY(name, type) \ +static type vm_call##name##_array(methodinfo *m, uint64_t *array) \ +{ \ + methoddesc *md; \ + void *pv; \ + type value; \ + \ + assert(m->code != NULL); \ + \ + md = m->parseddesc; \ + pv = m->code->entrypoint; \ + \ + STATISTICS(count_calls_native_to_java++); \ + \ + value = asm_vm_call_method##name(pv, array, md->memuse); \ + \ + return value; \ } +static java_handle_t *vm_call_array(methodinfo *m, uint64_t *array) +{ + methoddesc *md; + void *pv; + java_object_t *o; -/* vm_array_store_lng ********************************************************** + assert(m->code != NULL); - Helper function to store a long into the argument array, taking - care of architecture specific issues. + md = m->parseddesc; + pv = m->code->entrypoint; -*******************************************************************************/ + STATISTICS(count_calls_native_to_java++); -static void vm_array_store_lng(uint64_t *array, paramdesc *pd, int64_t value) -{ - int32_t index; + o = asm_vm_call_method(pv, array, md->memuse); -#if SIZEOF_VOID_P == 8 - if (!pd->inmemory) - index = pd->index; - else - index = ARG_CNT + pd->index; + if (md->returntype.type == TYPE_VOID) + o = NULL; - array[index] = value; -#else - if (!pd->inmemory) { - /* move low and high 32-bits into it's own argument slot */ - - index = GET_LOW_REG(pd->index); - array[index] = value & 0x00000000ffffffff; - - index = GET_HIGH_REG(pd->index); - array[index] = value >> 32; - } - else { - index = ARG_CNT + pd->index; - array[index] = value; - } -#endif + return LLNI_WRAP(o); } - -/* vm_array_store_flt ********************************************************** - - Helper function to store a float into the argument array, taking - care of architecture specific issues. - -*******************************************************************************/ - -static void vm_array_store_flt(uint64_t *array, paramdesc *pd, uint64_t value) -{ - int32_t index; - - if (!pd->inmemory) { -#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS) - index = pd->index; -#else - index = INT_ARG_CNT + pd->index; -#endif -#if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__) - array[index] = value >> 32; -#else - array[index] = value; -#endif - } - else { - index = ARG_CNT + pd->index; -#if defined(__SPARC_64__) - array[index] = value >> 32; -#else - array[index] = value; -#endif - } -} - - -/* vm_array_store_dbl ********************************************************** - - Helper function to store a double into the argument array, taking - care of architecture specific issues. - -*******************************************************************************/ - -static void vm_array_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value) -{ - int32_t index; - - if (!pd->inmemory) { -#if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS) - index = GET_LOW_REG(pd->index); - array[index] = value & 0x00000000ffffffff; - - index = GET_HIGH_REG(pd->index); - array[index] = value >> 32; -#else - index = INT_ARG_CNT + pd->index; - array[index] = value; -#endif - } - else { - index = ARG_CNT + pd->index; - array[index] = value; - } -} - - -/* vm_array_store_adr ********************************************************** - - Helper function to store an address into the argument array, taking - care of architecture specific issues. - -*******************************************************************************/ - -static void vm_array_store_adr(uint64_t *array, paramdesc *pd, void *value) -{ - int32_t index; - - if (!pd->inmemory) { -#if defined(HAS_ADDRESS_REGISTER_FILE) - /* When the architecture has address registers, place them - after integer and float registers. */ - - index = INT_ARG_CNT + FLT_ARG_CNT + pd->index; -#else - index = pd->index; -#endif - array[index] = (uint64_t) (intptr_t) value; - } - else { - index = ARG_CNT + pd->index; -#if SIZEOF_VOID_P == 8 - array[index] = (uint64_t) (intptr_t) value; -#else -# if WORDS_BIGENDIAN == 1 - array[index] = ((uint64_t) (intptr_t) value) << 32; -# else - array[index] = (uint64_t) (intptr_t) value; -# endif -#endif - } -} - - -/* vm_array_from_valist ******************************************************** - - XXX - -*******************************************************************************/ - -uint64_t *vm_array_from_valist(methodinfo *m, java_object_t *o, va_list ap) -{ - methoddesc *md; - paramdesc *pd; - typedesc *td; - uint64_t *array; - int32_t i; - imm_union value; - - /* get the descriptors */ - - md = m->parseddesc; - pd = md->params; - td = md->paramtypes; - - /* allocate argument array */ - - array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse); - - /* if method is non-static fill first block and skip `this' pointer */ - - i = 0; - - if (o != NULL) { - /* the `this' pointer */ - vm_array_store_adr(array, pd, o); - - pd++; - td++; - i++; - } - - for (; i < md->paramcount; i++, pd++, td++) { - switch (td->type) { - case TYPE_INT: - value.i = va_arg(ap, int32_t); - vm_array_store_int(array, pd, value.i); - break; - - case TYPE_LNG: - value.l = va_arg(ap, int64_t); - vm_array_store_lng(array, pd, value.l); - break; - - case TYPE_FLT: -#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__) - /* This is required to load the correct float value in - assembler code. */ - - value.d = (double) va_arg(ap, double); -#else - value.f = (float) va_arg(ap, double); -#endif - vm_array_store_flt(array, pd, value.l); - break; - - case TYPE_DBL: - value.d = va_arg(ap, double); - vm_array_store_dbl(array, pd, value.l); - break; - - case TYPE_ADR: - value.a = va_arg(ap, void*); - vm_array_store_adr(array, pd, value.a); - break; - } - } - - return array; -} - - -/* vm_array_from_jvalue ******************************************************** - - XXX - -*******************************************************************************/ - -static uint64_t *vm_array_from_jvalue(methodinfo *m, java_object_t *o, - const jvalue *args) -{ - methoddesc *md; - paramdesc *pd; - typedesc *td; - uint64_t *array; - int32_t i; - int32_t j; - - /* get the descriptors */ - - md = m->parseddesc; - pd = md->params; - td = md->paramtypes; - - /* allocate argument array */ - -#if defined(HAS_ADDRESS_REGISTER_FILE) - array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse); -#else - array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse); -#endif - - /* if method is non-static fill first block and skip `this' pointer */ - - i = 0; - - if (o != NULL) { - /* the `this' pointer */ - vm_array_store_adr(array, pd, o); - - pd++; - td++; - i++; - } - - for (j = 0; i < md->paramcount; i++, j++, pd++, td++) { - switch (td->decltype) { - case TYPE_INT: - vm_array_store_int(array, pd, args[j].i); - break; - - case TYPE_LNG: - vm_array_store_lng(array, pd, args[j].j); - break; - - case TYPE_FLT: - vm_array_store_flt(array, pd, args[j].j); - break; - - case TYPE_DBL: - vm_array_store_dbl(array, pd, args[j].j); - break; - - case TYPE_ADR: - vm_array_store_adr(array, pd, args[j].l); - break; - } - } - - return array; -} - - -/* vm_array_from_objectarray *************************************************** - - XXX - -*******************************************************************************/ - -uint64_t *vm_array_from_objectarray(methodinfo *m, java_object_t *o, - java_handle_objectarray_t *params) -{ - methoddesc *md; - paramdesc *pd; - typedesc *td; - uint64_t *array; - java_handle_t *param; - classinfo *c; - int type; - int32_t i; - int32_t j; - imm_union value; - - /* get the descriptors */ - - md = m->parseddesc; - pd = md->params; - td = md->paramtypes; - - /* allocate argument array */ - - array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse); - - /* if method is non-static fill first block and skip `this' pointer */ - - i = 0; - - if (o != NULL) { - /* this pointer */ - vm_array_store_adr(array, pd, o); - - pd++; - td++; - i++; - } - - for (j = 0; i < md->paramcount; i++, j++, pd++, td++) { - LLNI_objectarray_element_get(params, j, param); - - switch (td->type) { - case TYPE_INT: - if (param == NULL) - goto illegal_arg; - - /* convert the value according to its declared type */ - - c = param->vftbl->class; - type = primitive_type_get_by_wrapperclass(c); - - switch (td->decltype) { - case PRIMITIVETYPE_BOOLEAN: - switch (type) { - case PRIMITIVETYPE_BOOLEAN: - /* This type is OK. */ - break; - default: - goto illegal_arg; - } - break; - - case PRIMITIVETYPE_BYTE: - switch (type) { - case PRIMITIVETYPE_BYTE: - /* This type is OK. */ - break; - default: - goto illegal_arg; - } - break; - - case PRIMITIVETYPE_CHAR: - switch (type) { - case PRIMITIVETYPE_CHAR: - /* This type is OK. */ - break; - default: - goto illegal_arg; - } - break; - - case PRIMITIVETYPE_SHORT: - switch (type) { - case PRIMITIVETYPE_BYTE: - case PRIMITIVETYPE_SHORT: - /* These types are OK. */ - break; - default: - goto illegal_arg; - } - break; - - case PRIMITIVETYPE_INT: - switch (type) { - case PRIMITIVETYPE_BYTE: - case PRIMITIVETYPE_SHORT: - case PRIMITIVETYPE_INT: - /* These types are OK. */ - break; - default: - goto illegal_arg; - } - break; - - default: - vm_abort("vm_array_from_objectarray: invalid type %d", - td->decltype); - } - - value = primitive_unbox(param); - vm_array_store_int(array, pd, value.i); - break; - - case TYPE_LNG: - if (param == NULL) - goto illegal_arg; - - c = param->vftbl->class; - type = primitive_type_get_by_wrapperclass(c); - - assert(td->decltype == PRIMITIVETYPE_LONG); - - switch (type) { - case PRIMITIVETYPE_BYTE: - case PRIMITIVETYPE_SHORT: - case PRIMITIVETYPE_INT: - case PRIMITIVETYPE_LONG: - /* These types are OK. */ - break; - default: - goto illegal_arg; - } - - value = primitive_unbox(param); - vm_array_store_lng(array, pd, value.l); - break; - - case TYPE_FLT: - if (param == NULL) - goto illegal_arg; - - c = param->vftbl->class; - type = primitive_type_get_by_wrapperclass(c); - - assert(td->decltype == PRIMITIVETYPE_FLOAT); - - switch (type) { - case PRIMITIVETYPE_FLOAT: - /* This type is OK. */ - break; - default: - goto illegal_arg; - } - - value = primitive_unbox(param); - vm_array_store_flt(array, pd, value.l); - break; - - case TYPE_DBL: - if (param == NULL) - goto illegal_arg; - - c = param->vftbl->class; - type = primitive_type_get_by_wrapperclass(c); - - assert(td->decltype == PRIMITIVETYPE_DOUBLE); - - switch (type) { - case PRIMITIVETYPE_FLOAT: - case PRIMITIVETYPE_DOUBLE: - /* These types are OK. */ - break; - default: - goto illegal_arg; - } - - value = primitive_unbox(param); - vm_array_store_dbl(array, pd, value.l); - break; - - case TYPE_ADR: - if (!resolve_class_from_typedesc(td, true, true, &c)) - return false; - - if (param != NULL) { - if (td->arraydim > 0) { - if (!builtin_arrayinstanceof(param, c)) - goto illegal_arg; - } - else { - if (!builtin_instanceof(param, c)) - goto illegal_arg; - } - } - - vm_array_store_adr(array, pd, param); - break; - - default: - vm_abort("vm_array_from_objectarray: invalid type %d", td->type); - } - } - - return array; - -illegal_arg: - exceptions_throw_illegalargumentexception(); - return NULL; -} +VM_CALL_ARRAY(_int, int32_t) +VM_CALL_ARRAY(_long, int64_t) +VM_CALL_ARRAY(_float, float) +VM_CALL_ARRAY(_double, double) /* vm_call_method ************************************************************** @@ -2797,14 +2468,22 @@ VM_CALL_METHOD(_double, double) type vm_call_method##name##_valist(methodinfo *m, java_handle_t *o, \ va_list ap) \ { \ - int32_t dumpsize; \ uint64_t *array; \ type value; \ + int32_t dumpmarker; \ + \ + if (m->code == NULL) \ + if (!jit_compile(m)) \ + return 0; \ \ - dumpsize = dump_size(); \ - array = vm_array_from_valist(m, o, ap); \ + THREAD_NATIVEWORLD_EXIT; \ + DMARKER; \ + \ + array = argument_vmarray_from_valist(m, o, ap); \ value = vm_call##name##_array(m, array); \ - dump_release(dumpsize); \ + \ + DRELEASE; \ + THREAD_NATIVEWORLD_ENTER; \ \ return value; \ } @@ -2827,14 +2506,22 @@ VM_CALL_METHOD_VALIST(_double, double) type vm_call_method##name##_jvalue(methodinfo *m, java_handle_t *o, \ const jvalue *args) \ { \ - int32_t dumpsize; \ uint64_t *array; \ type value; \ + int32_t dumpmarker; \ + \ + if (m->code == NULL) \ + if (!jit_compile(m)) \ + return 0; \ + \ + THREAD_NATIVEWORLD_EXIT; \ + DMARKER; \ \ - dumpsize = dump_size(); \ - array = vm_array_from_jvalue(m, o, args); \ + array = argument_vmarray_from_jvalue(m, o, args); \ value = vm_call##name##_array(m, array); \ - dump_release(dumpsize); \ + \ + DRELEASE; \ + THREAD_NATIVEWORLD_ENTER; \ \ return value; \ } @@ -2846,40 +2533,118 @@ VM_CALL_METHOD_JVALUE(_float, float) VM_CALL_METHOD_JVALUE(_double, double) -/* vm_call_array *************************************************************** +/* vm_call_method_objectarray ************************************************** - Calls a Java method with a variable number of arguments, passed via - an argument array. + Calls a Java method with a variable number if arguments, passed via + an objectarray of boxed values. Returns a boxed value. *******************************************************************************/ -#define VM_CALL_ARRAY(name, type) \ -type vm_call##name##_array(methodinfo *m, uint64_t *array) \ -{ \ - methoddesc *md; \ - void *pv; \ - type value; \ - \ - md = m->parseddesc; \ - \ - if (m->code == NULL) \ - if (!jit_compile(m)) \ - return 0; \ - \ - pv = m->code->entrypoint; \ - \ - STATISTICS(count_calls_native_to_java++); \ - \ - value = asm_vm_call_method##name(pv, array, md->memuse); \ - \ - return value; \ -} +java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o, + java_handle_objectarray_t *params) +{ + uint64_t *array; + java_handle_t *xptr; + java_handle_t *ro; + imm_union value; + int32_t dumpmarker; -VM_CALL_ARRAY(, java_handle_t *) -VM_CALL_ARRAY(_int, int32_t) -VM_CALL_ARRAY(_long, int64_t) -VM_CALL_ARRAY(_float, float) -VM_CALL_ARRAY(_double, double) + /* Prevent compiler warnings. */ + + ro = NULL; + + /* compile methods which are not yet compiled */ + + if (m->code == NULL) + if (!jit_compile(m)) + return NULL; + + /* leave the nativeworld */ + + THREAD_NATIVEWORLD_EXIT; + + /* mark start of dump memory area */ + + DMARKER; + + /* Fill the argument array from a object-array. */ + + array = argument_vmarray_from_objectarray(m, o, params); + + if (array == NULL) { + /* release dump area */ + + DRELEASE; + + /* enter the nativeworld again */ + + THREAD_NATIVEWORLD_ENTER; + + exceptions_throw_illegalargumentexception(); + + return NULL; + } + + switch (m->parseddesc->returntype.decltype) { + case PRIMITIVETYPE_VOID: + value.a = vm_call_array(m, array); + break; + + case PRIMITIVETYPE_BOOLEAN: + case PRIMITIVETYPE_BYTE: + case PRIMITIVETYPE_CHAR: + case PRIMITIVETYPE_SHORT: + case PRIMITIVETYPE_INT: + value.i = vm_call_int_array(m, array); + break; + + case PRIMITIVETYPE_LONG: + value.l = vm_call_long_array(m, array); + break; + + case PRIMITIVETYPE_FLOAT: + value.f = vm_call_float_array(m, array); + break; + + case PRIMITIVETYPE_DOUBLE: + value.d = vm_call_double_array(m, array); + break; + + case TYPE_ADR: + ro = vm_call_array(m, array); + break; + + default: + vm_abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.decltype); + } + + /* release dump area */ + + DRELEASE; + + /* enter the nativeworld again */ + + THREAD_NATIVEWORLD_ENTER; + + /* box the return value if necesarry */ + + if (m->parseddesc->returntype.decltype != TYPE_ADR) + ro = primitive_box(m->parseddesc->returntype.decltype, value); + + /* check for an exception */ + + xptr = exceptions_get_exception(); + + if (xptr != NULL) { + /* clear exception pointer, we are calling JIT code again */ + + exceptions_clear_exception(); + + exceptions_throw_invocationtargetexception(xptr); + } + + return ro; +} /* @@ -2893,4 +2658,5 @@ VM_CALL_ARRAY(_double, double) * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */