Merged revisions 7501-7598 via svnmerge from
[cacao.git] / src / vm / vm.c
index 4a9efc84983ef9ae92aa1b2ccb5d9d07b23fbdf8..5d1cc1e49031606ff24df2ae3298a25e508baf82 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/vm.c - VM startup and shutdown functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes: Martin Platter
-
    $Id: vm.c 4357 2006-01-22 23:33:38Z twisti $
 
 */
 #include "config.h"
 
 #include <assert.h>
+#include <errno.h>
 #include <stdlib.h>
 
+#if defined(WITH_JRE_LAYOUT)
+# include <libgen.h>
+# include <unistd.h>
+#endif
+
 #include "vm/types.h"
 
-#include "mm/boehm.h"
+#include "mm/gc-common.h"
 #include "mm/memory.h"
+
 #include "native/jni.h"
 #include "native/native.h"
+#include "native/include/java_lang_Class.h"
+#include "native/include/java_lang_String.h"
 
 #if defined(ENABLE_THREADS)
 # include "threads/native/threads.h"
 #endif
 
-#include "vm/classcache.h"
+#include "toolbox/logging.h"
+
+#include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/finalizer.h"
 #include "vm/global.h"
 #include "vm/initialize.h"
-#include "vm/options.h"
 #include "vm/properties.h"
 #include "vm/signallocal.h"
 #include "vm/stringlocal.h"
-#include "vm/suck.h"
 #include "vm/vm.h"
+
 #include "vm/jit/jit.h"
+#include "vm/jit/md.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/profile/profile.h"
-#include "vm/rt-timing.h"
+
+#if defined(ENABLE_PROFILING)
+# include "vm/jit/optimizing/profile.h"
+#endif
+
+#include "vm/jit/optimizing/recompile.h"
+
+#include "vmcore/classcache.h"
+#include "vmcore/options.h"
+#include "vmcore/suck.h"
 
 #if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
+# include "native/jvmti/cacaodbg.h"
 #endif
 
+
 /* Invocation API variables ***************************************************/
 
 _Jv_JavaVM *_Jv_jvm;                    /* denotes a Java VM                  */
@@ -82,11 +96,15 @@ s4 vms = 0;                             /* number of VMs created              */
 bool vm_initializing = false;
 bool vm_exiting = false;
 
-#if defined(ENABLE_INTRP)
-u1 *intrp_main_stack = NULL;
-#endif
+char      *cacao_prefix = NULL;
+char      *cacao_libjvm = NULL;
+char      *classpath_libdir = NULL;
 
-char *mainstring = NULL;
+char      *_Jv_bootclasspath;           /* contains the boot classpath        */
+char      *_Jv_classpath;               /* contains the classpath             */
+char      *_Jv_java_library_path;
+
+char      *mainstring = NULL;
 classinfo *mainclass = NULL;
 
 char *specificmethodname = NULL;
@@ -94,6 +112,10 @@ char *specificsignature = NULL;
 
 bool startit = true;
 
+#if defined(ENABLE_INTRP)
+u1 *intrp_main_stack = NULL;
+#endif
+
 
 /* define heap sizes **********************************************************/
 
@@ -105,6 +127,8 @@ bool startit = true;
 /* define command line options ************************************************/
 
 enum {
+       OPT_FOO,
+
        /* Java options */
 
        OPT_JAR,
@@ -123,6 +147,10 @@ enum {
 
        OPT_HELP,
        OPT_X,
+       OPT_XX,
+
+       OPT_ESA,
+       OPT_DSA,
 
        /* Java non-standard options */
 
@@ -133,10 +161,12 @@ enum {
        OPT_BOOTCLASSPATH_A,
        OPT_BOOTCLASSPATH_P,
 
-       OPT_GLIBJ,
+       OPT_BOOTCLASSPATH_C,
 
+#if defined(ENABLE_PROFILING)
        OPT_PROF,
        OPT_PROF_OPTION,
+#endif
 
        OPT_MS,
        OPT_MX,
@@ -145,7 +175,6 @@ enum {
 
        OPT_VERBOSE1,
        OPT_NOIEEE,
-       OPT_SOFTNULL,
 
 #if defined(ENABLE_STATISTICS)
        OPT_TIME,
@@ -155,10 +184,14 @@ enum {
        OPT_LOG,
        OPT_CHECK,
        OPT_LOAD,
-       OPT_METHOD,
-       OPT_SIGNATURE,
        OPT_SHOW,
+       OPT_DEBUGCOLOR,
+
+#if !defined(NDEBUG)
        OPT_ALL,
+       OPT_METHOD,
+       OPT_SIGNATURE,
+#endif
 
 #if defined(ENABLE_VERIFIER)
        OPT_NOVERIFY,
@@ -178,13 +211,24 @@ enum {
        OPT_IFCONV,
 #endif
 
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
        OPT_LSRA,
 #endif
 
 #if defined(ENABLE_INLINING)
        OPT_INLINING,
-#endif
+#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,
+       OPT_INLINE_REPLACE_VERBOSE,
+       OPT_INLINE_REPLACE_VERBOSE2,
+#endif /* defined(ENABLE_INLINING_DEBUG) */
+#endif /* defined(ENABLE_INLINING) */
 
 #if defined(ENABLE_INTRP)
        /* interpreter options */
@@ -211,6 +255,8 @@ enum {
 
 
 opt_struct opts[] = {
+       { "foo",               false, OPT_FOO },
+
        /* Java options */
 
        { "jar",               false, OPT_JAR },
@@ -231,6 +277,12 @@ opt_struct opts[] = {
        { "help",              false, OPT_HELP },
        { "?",                 false, OPT_HELP },
        { "X",                 false, OPT_X },
+       { "XX",                false, OPT_XX },
+
+       { "esa",                     false, OPT_ESA },
+       { "enablesystemassertions",  false, OPT_ESA },
+       { "dsa",                     false, OPT_DSA },
+       { "disablesystemassertions", false, OPT_DSA },
 
        { "noasyncgc",         false, OPT_IGNORE },
 #if defined(ENABLE_VERIFIER)
@@ -245,7 +297,6 @@ opt_struct opts[] = {
 #if defined(__ALPHA__)
        { "noieee",            false, OPT_NOIEEE },
 #endif
-       { "softnull",          false, OPT_SOFTNULL },
 #if defined(ENABLE_STATISTICS)
        { "time",              false, OPT_TIME },
        { "stat",              false, OPT_STAT },
@@ -254,15 +305,19 @@ opt_struct opts[] = {
        { "c",                 true,  OPT_CHECK },
        { "l",                 false, OPT_LOAD },
        { "eager",             false, OPT_EAGER },
-       { "sig",               true,  OPT_SIGNATURE },
+
+#if !defined(NDEBUG)
        { "all",               false, OPT_ALL },
+       { "sig",               true,  OPT_SIGNATURE },
+#endif
+
 #if defined(ENABLE_LOOP)
        { "oloop",             false, OPT_OLOOP },
 #endif
 #if defined(ENABLE_IFCONV)
        { "ifconv",            false, OPT_IFCONV },
 #endif
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
        { "lsra",              false, OPT_LSRA },
 #endif
 
@@ -289,7 +344,7 @@ opt_struct opts[] = {
        { "Xbootclasspath:",   true,  OPT_BOOTCLASSPATH },
        { "Xbootclasspath/a:", true,  OPT_BOOTCLASSPATH_A },
        { "Xbootclasspath/p:", true,  OPT_BOOTCLASSPATH_P },
-       { "Xglibj:",           true,  OPT_GLIBJ },
+       { "Xbootclasspath/c:", true,  OPT_BOOTCLASSPATH_C },
 
 #ifdef ENABLE_JVMTI
        { "Xdebug",            false, OPT_DEBUG },
@@ -303,16 +358,37 @@ opt_struct opts[] = {
        { "mx",                true,  OPT_MX },
        { "Xss",               true,  OPT_SS },
        { "ss",                true,  OPT_SS },
+
+#if defined(ENABLE_PROFILING)
        { "Xprof:",            true,  OPT_PROF_OPTION },
        { "Xprof",             false, OPT_PROF },
+#endif
 
-       /* keep these at the end of the list */
+       /* inlining options */
 
 #if defined(ENABLE_INLINING)
-       { "i",                 true,  OPT_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 },
+       { "ir",                false, OPT_INLINE_REPLACE_VERBOSE },
+       { "iR",                false, OPT_INLINE_REPLACE_VERBOSE2 },
+#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)
        { "m",                 true,  OPT_METHOD },
+#endif
+
        { "s",                 true,  OPT_SHOW },
+       { "debug-color",      false,  OPT_DEBUGCOLOR },
 
        { NULL,                false, 0 }
 };
@@ -331,7 +407,7 @@ void usage(void)
        puts("   or  cacao [-options] -jar jarfile [arguments]");
        puts("               (to run a standalone jar file)\n");
 
-       puts("Java options:");
+       puts("where options include:");
        puts("    -d32                     use 32-bit data model if available");
        puts("    -d64                     use 64-bit data model if available");
        puts("    -client                  compatibility (currently ignored)");
@@ -347,7 +423,12 @@ void usage(void)
        puts("    -fullversion             print jpackage-compatible product version and exit");
        puts("    -showversion             print product version and continue");
        puts("    -help, -?                print this help message");
-       puts("    -X                       print help on non-standard Java options\n");
+       puts("    -X                       print help on non-standard Java options");
+       puts("    -XX                      print help on CACAO options");
+       puts("    -esa | -enablesystemassertions");
+       puts("                             enable system assertions");
+       puts("    -dsa | -disablesystemassertions");
+       puts("                             disable system assertions");
 
 #ifdef ENABLE_JVMTI
        puts("    -agentlib:<agent-lib-name>=<options>  library to load containg JVMTI agent");
@@ -355,10 +436,59 @@ void usage(void)
        puts("    -agentpath:<path-to-agent>=<options>  path to library containg JVMTI agent");
 #endif
 
-       puts("CACAO options:");
+       /* exit with error code */
+
+       exit(1);
+}   
+
+
+static void Xusage(void)
+{
+#if defined(ENABLE_JIT)
+       puts("    -Xjit                    JIT mode execution (default)");
+#endif
+#if defined(ENABLE_INTRP)
+       puts("    -Xint                    interpreter mode execution");
+#endif
+       puts("    -Xbootclasspath:<zip/jar files and directories separated by :>");
+    puts("                             value is set as bootstrap class path");
+       puts("    -Xbootclasspath/a:<zip/jar files and directories separated by :>");
+       puts("                             value is appended to the bootstrap class path");
+       puts("    -Xbootclasspath/p:<zip/jar files and directories separated by :>");
+       puts("                             value is prepended to the bootstrap class path");
+       puts("    -Xbootclasspath/c:<zip/jar files and directories separated by :>");
+       puts("                             value is used as Java core library, but the");
+       puts("                             hardcoded VM interface classes are prepended");
+       printf("    -Xms<size>               set the initial size of the heap (default: %dMB)\n", HEAP_STARTSIZE / 1024 / 1024);
+       printf("    -Xmx<size>               set the maximum size of the heap (default: %dMB)\n", HEAP_MAXSIZE / 1024 / 1024);
+       printf("    -Xss<size>               set the thread stack size (default: %dkB)\n", STACK_SIZE / 1024);
+
+#if defined(ENABLE_PROFILING)
+       puts("    -Xprof[:bb]              collect and print profiling data");
+#endif
+
+#if defined(ENABLE_JVMTI)
+    /* -Xdebug option depend on gnu classpath JDWP options. options: 
+        transport=dt_socket,address=<hostname:port>,server=(y|n),suspend(y|n) */
+       puts("    -Xdebug                  enable remote debugging\n");
+       puts("    -Xrunjdwp transport=[dt_socket|...],address=<hostname:port>,server=[y|n],suspend=[y|n]\n");
+       puts("                             enable remote debugging\n");
+#endif 
+
+       /* exit with error code */
+
+       exit(1);
+}   
+
+
+static void XXusage(void)
+{
        puts("    -v                       write state-information");
-       puts("    -verbose[:call|exception|jit]");
+#if !defined(NDEBUG)
+       puts("    -verbose[:call|exception|jit|memory]");
        puts("                             enable specific verbose output");
+       puts("    -debug-color             colored output for ANSI terms");
+#endif
 #ifdef TYPECHECK_VERBOSE
        puts("    -verbosetc               write debug messages while typechecking");
 #endif
@@ -368,7 +498,6 @@ void usage(void)
 #if defined(ENABLE_VERIFIER)
        puts("    -noverify                don't verify classfiles");
 #endif
-       puts("    -softnull                use software nullpointer check");
 #if defined(ENABLE_STATISTICS)
        puts("    -time                    measure the runtime");
        puts("    -stat                    detailed compiler statistics");
@@ -381,70 +510,54 @@ void usage(void)
 #endif
        puts("    -l                       don't start the class after loading");
        puts("    -eager                   perform eager class loading and linking");
+#if !defined(NDEBUG)
        puts("    -all                     compile all methods, no execution");
        puts("    -m                       compile only a specific method");
        puts("    -sig                     specify signature for a specific method");
-       puts("    -s(how)a(ssembler)       show disassembled listing");
-       puts("           c(onstants)       show the constant pool");
-       puts("           d(atasegment)     show data segment listing");
-       puts("           e(xceptionstubs)  show disassembled exception stubs (only with -sa)");
-       puts("           i(ntermediate)    show intermediate representation");
-       puts("           m(ethods)         show class fields and methods");
-       puts("           n(ative)          show disassembled native stubs");
-       puts("           u(tf)             show the utf - hash");
+#endif
+
+       puts("    -s...                    show...");
+       puts("      (c)onstants            the constant pool");
+       puts("      (m)ethods              class fields and methods");
+       puts("      (u)tf                  the utf - hash");
+       puts("      (i)ntermediate         intermediate representation");
+#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     n(line)           activate inlining");
-       puts("           v(irtual)         inline virtual methods (uses/turns rt option on)");
-       puts("           e(exception)      inline methods with exceptions");
-       puts("           p(aramopt)        optimize argument renaming");
-       puts("           o(utsiders)       inline methods of foreign classes");
+       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 <size>               set minimum size for inlined result");
+       puts("    -im <size>               set maximum size for inlined result");
+       puts("    -ie <number>             stop inlining after the given number of roots");
+       puts("    -ir                      log on-stack replacement");
+       puts("    -iR                      log on-stack replacement, more verbose");
+#endif /* defined(ENABLE_INLINING_DEBUG) */
 #endif /* defined(ENABLE_INLINING) */
+
 #if defined(ENABLE_IFCONV)
        puts("    -ifconv                  use if-conversion");
 #endif
 #if defined(ENABLE_LSRA)
        puts("    -lsra                    use linear scan register allocation");
 #endif
-
-       /* exit with error code */
-
-       exit(1);
-}   
-
-
-static void Xusage(void)
-{
-#if defined(ENABLE_JIT)
-       puts("    -Xjit                    JIT mode execution (default)");
+#if defined(ENABLE_SSA)
+       puts("    -lsra                    use linear scan register allocation (with SSA)");
 #endif
-#if defined(ENABLE_INTRP)
-       puts("    -Xint                    interpreter mode execution");
-#endif
-       puts("    -Xbootclasspath:<zip/jar files and directories separated by :>");
-    puts("                             value is set as bootstrap class path");
-       puts("    -Xbootclasspath/a:<zip/jar files and directories separated by :>");
-       puts("                             value is appended to the bootstrap class path");
-       puts("    -Xbootclasspath/p:<zip/jar files and directories separated by :>");
-       puts("                             value is prepended to the bootstrap class path");
-       puts("    -Xglibj:<zip/jar files and directories separated by :>");
-       puts("                             value is used as Java core library, but the");
-       puts("                             hardcoded VM interface classes are prepended");
-       printf("    -Xms<size>               set the initial size of the heap (default: %dMB)\n", HEAP_STARTSIZE / 1024 / 1024);
-       printf("    -Xmx<size>               set the maximum size of the heap (default: %dMB)\n", HEAP_MAXSIZE / 1024 / 1024);
-       printf("    -Xss<size>               set the thread stack size (default: %dkB)\n", STACK_SIZE / 1024);
-       puts("    -Xprof[:bb]              collect and print profiling data");
-#if defined(ENABLE_JVMTI)
-    /* -Xdebug option depend on gnu classpath JDWP options. options: 
-        transport=dt_socket,address=<hostname:port>,server=(y|n),suspend(y|n) */
-       puts("    -Xdebug                  enable remote debugging\n");
-       puts("    -Xrunjdwp transport=[dt_socket|...],address=<hostname:port>,server=[y|n],suspend=[y|n]\n");
-       puts("                             enable remote debugging\n");
-#endif 
 
        /* exit with error code */
 
        exit(1);
-}   
+}
 
 
 /* version *********************************************************************
@@ -458,7 +571,7 @@ static void version(bool opt_exit)
        puts("java version \""JAVA_VERSION"\"");
        puts("CACAO version "VERSION"");
 
-       puts("Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,");
+       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");
@@ -483,17 +596,23 @@ static void version(bool opt_exit)
        puts("  CFLAGS     : "VERSION_CFLAGS"\n");
 
        puts("Default variables:\n");
-       printf("  maximum heap size   : %d\n", HEAP_MAXSIZE);
-       printf("  initial heap size   : %d\n", HEAP_STARTSIZE);
-       printf("  stack size          : %d\n", STACK_SIZE);
-       puts("  java.boot.class.path: "CACAO_VM_ZIP":"CLASSPATH_GLIBJ_ZIP"");
-       puts("  java.library.path   : "CLASSPATH_LIBRARY_PATH"\n");
+       printf("  maximum heap size              : %d\n", HEAP_MAXSIZE);
+       printf("  initial heap size              : %d\n", HEAP_STARTSIZE);
+       printf("  stack size                     : %d\n", STACK_SIZE);
+#if defined(WITH_CLASSPATH_GNU)
+       puts("  java.boot.class.path           : "CACAO_VM_ZIP":"CLASSPATH_CLASSES"");
+#else
+       puts("  java.boot.class.path           : "CLASSPATH_CLASSES"");
+#endif
+       puts("  gnu.classpath.boot.library.path: "CLASSPATH_LIBDIR"/classpath\n");
 
        puts("Runtime variables:\n");
-       printf("  maximum heap size   : %d\n", opt_heapmaxsize);
-       printf("  initial heap size   : %d\n", opt_heapstartsize);
-       printf("  stack size          : %d\n", opt_stacksize);
-       printf("  java.boot.class.path: %s\n", bootclasspath);
+       printf("  maximum heap size              : %d\n", opt_heapmaxsize);
+       printf("  initial heap size              : %d\n", opt_heapstartsize);
+       printf("  stack size                     : %d\n", opt_stacksize);
+       printf("  java.boot.class.path           : %s\n", _Jv_bootclasspath);
+       printf("  gnu.classpath.boot.library.path: %s\n", classpath_libdir);
+       printf("  java.class.path                : %s\n", _Jv_classpath);
 
        /* exit normally, if requested */
 
@@ -519,18 +638,97 @@ static void fullversion(void)
 }
 
 
+/* forward declarations *******************************************************/
+
+static char *vm_get_mainclass_from_jar(char *mainstring);
+#if !defined(NDEBUG)
+static void  vm_compile_all(void);
+static void  vm_compile_method(void);
+#endif
+
+
+/* vm_createjvm ****************************************************************
+
+   Implementation for JNI_CreateJavaVM.
+
+*******************************************************************************/
+
+bool vm_createjvm(JavaVM **p_vm, void **p_env, void *vm_args)
+{
+       JavaVMInitArgs *_vm_args;
+       _Jv_JNIEnv     *env;
+       _Jv_JavaVM     *vm;
+
+       /* get the arguments for the new JVM */
+
+       _vm_args = (JavaVMInitArgs *) vm_args;
+
+       /* get the VM and Env tables (must be set before vm_create) */
+
+       env = NEW(_Jv_JNIEnv);
+
+#if defined(ENABLE_JNI)
+       env->env = &_Jv_JNINativeInterface;
+#endif
+
+       /* XXX Set the global variable.  Maybe we should do that differently. */
+
+       _Jv_env = env;
+
+       /* create and fill a JavaVM structure */
+
+       vm = NEW(_Jv_JavaVM);
+
+#if defined(ENABLE_JNI)
+       vm->functions = &_Jv_JNIInvokeInterface;
+#endif
+
+       /* XXX Set the global variable.  Maybe we should do that differently. */
+       /* XXX JVMTI Agents needs a JavaVM  */
+
+       _Jv_jvm = vm;
+
+       /* actually create the JVM */
+
+       if (!vm_create(_vm_args))
+               goto error;
+
+#if defined(ENABLE_JNI)
+       /* setup the local ref table (must be created after vm_create) */
+
+       if (!jni_init_localref_table())
+               goto error;
+#endif
+
+       /* now return the values */
+
+       *p_vm  = (JavaVM *) vm;
+       *p_env = (void *) env;
+
+       return true;
+
+ error:
+       /* release allocated memory */
+
+       FREE(env, _Jv_JNIEnv);
+       FREE(vm, _Jv_JavaVM);
+
+       return false;
+}
+
+
 /* vm_create *******************************************************************
 
-   Creates a JVM.  Called by JNI_CreateJavaVM.
+   Creates a JVM.  Called by vm_createjvm.
 
 *******************************************************************************/
 
 bool vm_create(JavaVMInitArgs *vm_args)
 {
        char *cp;
-       s4    cplen;
+       s4    len;
        s4    opt;
-       s4    i, j, k;
+       s4    i, j;
        bool  opt_version;
        bool  opt_exit;
 
@@ -558,52 +756,136 @@ bool vm_create(JavaVMInitArgs *vm_args)
        if (vms > 0)
                return false;
 
+       if (atexit(vm_exit_handler))
+               vm_abort("atexit failed: %s\n", strerror(errno));
+
+       if (opt_verbose)
+               log_text("CACAO started -------------------------------------------------------");
+
+       /* We need to check if the actual size of a java.lang.Class object
+          is smaller or equal than the assumption made in
+          src/vmcore/class.h. */
+
+       if (sizeof(java_lang_Class) > sizeof(dummy_java_lang_Class))
+               vm_abort("vm_create: java_lang_Class structure is bigger than classinfo.object (%d > %d)", sizeof(java_lang_Class), sizeof(dummy_java_lang_Class));
+
+       /* set the VM starttime */
+
+       _Jv_jvm->starttime = builtin_currenttimemillis();
+
        /* get stuff from the environment *****************************************/
 
-#if defined(DISABLE_GC)
-       nogc_init(HEAP_MAXSIZE, HEAP_STARTSIZE);
+#if defined(WITH_JRE_LAYOUT)
+       /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
+
+       cacao_prefix = MNEW(char, 4096);
+
+       if (readlink("/proc/self/exe", cacao_prefix, 4095) == -1)
+               vm_abort("readlink failed: %s\n", strerror(errno));
+
+       /* get the path of the current executable */
+
+       cacao_prefix = dirname(cacao_prefix);
+
+       if ((strlen(cacao_prefix) + strlen("/..") + strlen("0")) > 4096)
+               vm_abort("libjvm name to long for buffer\n");
+
+       /* concatenate the library name */
+
+       strcat(cacao_prefix, "/..");
+
+       /* now set path to libjvm.so */
+
+       len = strlen(cacao_prefix) + strlen("/lib/libjvm") + strlen("0");
+
+       cacao_libjvm = MNEW(char, len);
+       strcpy(cacao_libjvm, cacao_prefix);
+       strcat(cacao_libjvm, "/lib/libjvm");
+
+       /* and finally set the path to GNU Classpath libraries */
+
+       len = strlen(cacao_prefix) + strlen("/lib/classpath") + strlen("0");
+
+       classpath_libdir = MNEW(char, len);
+       strcpy(classpath_libdir, cacao_prefix);
+       strcat(classpath_libdir, "/lib/classpath");
+#else
+       cacao_prefix     = CACAO_PREFIX;
+       cacao_libjvm     = CACAO_LIBDIR"/libjvm";
+       classpath_libdir = CLASSPATH_LIBDIR"/classpath";
 #endif
 
        /* set the bootclasspath */
 
        cp = getenv("BOOTCLASSPATH");
 
-       if (cp) {
-               bootclasspath = MNEW(char, strlen(cp) + strlen("0"));
-               strcpy(bootclasspath, cp);
+       if (cp != NULL) {
+               _Jv_bootclasspath = MNEW(char, strlen(cp) + strlen("0"));
+               strcpy(_Jv_bootclasspath, cp);
+       }
+       else {
+#if defined(WITH_JRE_LAYOUT)
+               len =
+# if defined(WITH_CLASSPATH_GNU)
+                       strlen(cacao_prefix) +
+                       strlen("/share/cacao/vm.zip") +
+                       strlen(":") +
+# endif
+                       strlen(cacao_prefix) +
+                       strlen("/share/classpath/glibj.zip") +
+                       strlen("0");
 
-       } else {
-               cplen = strlen(CACAO_VM_ZIP) +
+               _Jv_bootclasspath = MNEW(char, len);
+# if defined(WITH_CLASSPATH_GNU)
+               strcat(_Jv_bootclasspath, cacao_prefix);
+               strcat(_Jv_bootclasspath, "/share/cacao/vm.zip");
+               strcat(_Jv_bootclasspath, ":");
+# endif
+               strcat(_Jv_bootclasspath, cacao_prefix);
+               strcat(_Jv_bootclasspath, "/share/classpath/glibj.zip");
+#else
+               len =
+# if defined(WITH_CLASSPATH_GNU)
+                       strlen(CACAO_VM_ZIP) +
                        strlen(":") +
-                       strlen(CLASSPATH_GLIBJ_ZIP) +
+# endif
+                       strlen(CLASSPATH_CLASSES) +
                        strlen("0");
 
-               bootclasspath = MNEW(char, cplen);
-               strcat(bootclasspath, CACAO_VM_ZIP);
-               strcat(bootclasspath, ":");
-               strcat(bootclasspath, CLASSPATH_GLIBJ_ZIP);
+               _Jv_bootclasspath = MNEW(char, len);
+# if defined(WITH_CLASSPATH_GNU)
+               strcat(_Jv_bootclasspath, CACAO_VM_ZIP);
+               strcat(_Jv_bootclasspath, ":");
+# endif
+               strcat(_Jv_bootclasspath, CLASSPATH_CLASSES);
+#endif
        }
 
        /* set the classpath */
 
        cp = getenv("CLASSPATH");
 
-       if (cp) {
-               classpath = MNEW(char, strlen(cp) + strlen("0"));
-               strcat(classpath, cp);
-
-       } else {
-               classpath = MNEW(char, strlen(".") + strlen("0"));
-               strcpy(classpath, ".");
+       if (cp != NULL) {
+               _Jv_classpath = MNEW(char, strlen(cp) + strlen("0"));
+               strcat(_Jv_classpath, cp);
        }
+       else {
+               _Jv_classpath = MNEW(char, strlen(".") + strlen("0"));
+               strcpy(_Jv_classpath, ".");
+       }
+
+       /* get and set java.library.path */
+
+       _Jv_java_library_path = getenv("LD_LIBRARY_PATH");
 
+       if (_Jv_java_library_path == NULL)
+               _Jv_java_library_path = "";
 
        /* interpret the options **************************************************/
 
        opt_version       = false;
        opt_exit          = false;
 
-       checknull         = false;
        opt_noieee        = false;
 
        opt_heapmaxsize   = HEAP_MAXSIZE;
@@ -616,21 +898,19 @@ bool vm_create(JavaVMInitArgs *vm_args)
        jvmti = false;
 #endif
 
-       /* initialize properties before commandline handling */
+       /* initialize and fill properties before command-line handling */
 
        if (!properties_init())
-               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                  "Unable to init properties");
-
-       /* add some default properties */
-
-       properties_add("java.endorsed.dirs", ""CACAO_PREFIX"/jre/lib/endorsed");
-
+               vm_abort("properties_init failed");
 
        /* iterate over all passed options */
 
        while ((opt = options_get(opts, vm_args)) != OPT_DONE) {
                switch (opt) {
+               case OPT_FOO:
+                       opt_foo = true;
+                       break;
+
                case OPT_IGNORE:
                        break;
                        
@@ -654,17 +934,17 @@ bool vm_create(JavaVMInitArgs *vm_args)
 
                case OPT_CLASSPATH:
                        /* forget old classpath and set the argument as new classpath */
-                       MFREE(classpath, char, strlen(classpath));
+                       MFREE(_Jv_classpath, char, strlen(_Jv_classpath));
 
-                       classpath = MNEW(char, strlen(opt_arg) + strlen("0"));
-                       strcpy(classpath, opt_arg);
+                       _Jv_classpath = MNEW(char, strlen(opt_arg) + strlen("0"));
+                       strcpy(_Jv_classpath, opt_arg);
                        break;
 
                case OPT_D:
-                       for (j = 0; j < strlen(opt_arg); j++) {
-                               if (opt_arg[j] == '=') {
-                                       opt_arg[j] = '\0';
-                                       properties_add(opt_arg, opt_arg + j + 1);
+                       for (i = 0; i < strlen(opt_arg); i++) {
+                               if (opt_arg[i] == '=') {
+                                       opt_arg[i] = '\0';
+                                       properties_add(opt_arg, opt_arg + i + 1);
                                        goto opt_d_done;
                                }
                        }
@@ -680,79 +960,93 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        /* Forget default bootclasspath and set the argument as
                           new boot classpath. */
 
-                       MFREE(bootclasspath, char, strlen(bootclasspath));
+                       MFREE(_Jv_bootclasspath, char, strlen(_Jv_bootclasspath));
 
-                       bootclasspath = MNEW(char, strlen(opt_arg) + strlen("0"));
-                       strcpy(bootclasspath, opt_arg);
+                       _Jv_bootclasspath = MNEW(char, strlen(opt_arg) + strlen("0"));
+                       strcpy(_Jv_bootclasspath, opt_arg);
                        break;
 
                case OPT_BOOTCLASSPATH_A:
                        /* append to end of bootclasspath */
 
-                       cplen = strlen(bootclasspath);
+                       len = strlen(_Jv_bootclasspath);
 
-                       bootclasspath = MREALLOC(bootclasspath,
-                                                                        char,
-                                                                        cplen,
-                                                                        cplen + strlen(":") +
-                                                                        strlen(opt_arg) + strlen("0"));
+                       _Jv_bootclasspath = MREALLOC(_Jv_bootclasspath,
+                                                                                char,
+                                                                                len + strlen("0"),
+                                                                                len + strlen(":") +
+                                                                                strlen(opt_arg) + strlen("0"));
 
-                       strcat(bootclasspath, ":");
-                       strcat(bootclasspath, opt_arg);
+                       strcat(_Jv_bootclasspath, ":");
+                       strcat(_Jv_bootclasspath, opt_arg);
                        break;
 
                case OPT_BOOTCLASSPATH_P:
                        /* prepend in front of bootclasspath */
 
-                       cp = bootclasspath;
-                       cplen = strlen(cp);
+                       cp = _Jv_bootclasspath;
+                       len = strlen(cp);
 
-                       bootclasspath = MNEW(char, strlen(opt_arg) + strlen(":") +
-                                                                cplen + strlen("0"));
+                       _Jv_bootclasspath = MNEW(char, strlen(opt_arg) + strlen(":") +
+                                                                        len + strlen("0"));
 
-                       strcpy(bootclasspath, opt_arg);
-                       strcat(bootclasspath, ":");
-                       strcat(bootclasspath, cp);
+                       strcpy(_Jv_bootclasspath, opt_arg);
+                       strcat(_Jv_bootclasspath, ":");
+                       strcat(_Jv_bootclasspath, cp);
 
-                       MFREE(cp, char, cplen);
+                       MFREE(cp, char, len);
                        break;
 
-               case OPT_GLIBJ:
+               case OPT_BOOTCLASSPATH_C:
                        /* use as Java core library, but prepend VM interface classes */
 
-                       MFREE(bootclasspath, char, strlen(bootclasspath));
+                       MFREE(_Jv_bootclasspath, char, strlen(_Jv_bootclasspath));
 
-                       cplen = strlen(CACAO_VM_ZIP) +
+                       len = strlen(CACAO_VM_ZIP) +
                                strlen(":") +
                                strlen(opt_arg) +
                                strlen("0");
 
-                       bootclasspath = MNEW(char, cplen);
+                       _Jv_bootclasspath = MNEW(char, len);
 
-                       strcpy(bootclasspath, CACAO_VM_ZIP);
-                       strcat(bootclasspath, ":");
-                       strcat(bootclasspath, opt_arg);
+                       strcpy(_Jv_bootclasspath, CACAO_VM_ZIP);
+                       strcat(_Jv_bootclasspath, ":");
+                       strcat(_Jv_bootclasspath, opt_arg);
                        break;
 
 #if defined(ENABLE_JVMTI)
                case OPT_DEBUG:
                        /* this option exists only for compatibility reasons */
                        break;
+
                case OPT_NOAGENT:
                        /* I don't know yet what Xnoagent should do. This is only for 
                           compatiblity with eclipse - motse */
                        break;
+
                case OPT_XRUNJDWP:
-                       agentbypath=jvmti=jdwp=true;
-                       i = strlen(opt_arg)+33;
-                       agentarg = MNEW(char,i);
-                       /* XXX how can I get the <prefix>/lib directory ? */
-                       snprintf(agentarg,i,"/usr/local/cacao/lib/libjdwp.so=%s",&opt_arg[1]);
+                       agentbypath = true;
+                       jvmti       = true;
+                       jdwp        = true;
+
+                       len =
+                               strlen(CACAO_LIBDIR) +
+                               strlen("/libjdwp.so=") +
+                               strlen(opt_arg) +
+                               strlen("0");
+
+                       agentarg = MNEW(char, len);
+
+                       strcpy(agentarg, CACAO_LIBDIR);
+                       strcat(agentarg, "/libjdwp.so=");
+                       strcat(agentarg, &opt_arg[1]);
                        break;
+
                case OPT_AGENTPATH:
                        agentbypath = true;
+
                case OPT_AGENTLIB:
-                       jvmti=true;
+                       jvmti = true;
                        agentarg = opt_arg;
                        break;
 #endif
@@ -787,18 +1081,22 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        break;
 
                case OPT_VERBOSE:
-                       if (strcmp("class", opt_arg) == 0)
+                       if (strcmp("class", opt_arg) == 0) {
                                opt_verboseclass = true;
-
-                       else if (strcmp("gc", opt_arg) == 0)
+                       }
+                       else if (strcmp("gc", opt_arg) == 0) {
                                opt_verbosegc = true;
-
-                       else if (strcmp("jni", opt_arg) == 0)
+                       }
+                       else if (strcmp("jni", opt_arg) == 0) {
                                opt_verbosejni = true;
-
-                       else if (strcmp("call", opt_arg) == 0)
+                       }
+#if !defined(NDEBUG)
+                       else if (strcmp("call", opt_arg) == 0) {
                                opt_verbosecall = true;
-
+                       }
+                       else if (strcmp("exception", opt_arg) == 0) {
+                               opt_verboseexception = true;
+                       }
                        else if (strcmp("jit", opt_arg) == 0) {
                                opt_verbose = true;
                                loadverbose = true;
@@ -806,8 +1104,19 @@ bool vm_create(JavaVMInitArgs *vm_args)
                                initverbose = true;
                                compileverbose = true;
                        }
-                       else if (strcmp("exception", opt_arg) == 0)
-                               opt_verboseexception = true;
+                       else if (strcmp("memory", opt_arg) == 0) {
+                               opt_verbosememory = true;
+
+# if defined(ENABLE_STATISTICS)
+                               /* we also need statistics */
+
+                               opt_stat = true;
+# endif
+                       }
+#endif
+                       break;
+               case OPT_DEBUGCOLOR:
+                       opt_debugcolor = true;
                        break;
 
 #if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
@@ -839,10 +1148,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        break;
 #endif
 
-               case OPT_SOFTNULL:
-                       checknull = true;
-                       break;
-
 #if defined(ENABLE_STATISTICS)
                case OPT_TIME:
                        opt_getcompilingtime = true;
@@ -859,8 +1164,8 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        break;
                        
                case OPT_CHECK:
-                       for (j = 0; j < strlen(opt_arg); j++) {
-                               switch (opt_arg[j]) {
+                       for (i = 0; i < strlen(opt_arg); i++) {
+                               switch (opt_arg[i]) {
                                case 'b':
                                        checkbounds = false;
                                        break;
@@ -882,51 +1187,67 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        opt_eager = true;
                        break;
 
+#if !defined(NDEBUG)
+               case OPT_ALL:
+                       compileall = true;
+                       opt_run = false;
+                       makeinitializations = false;
+                       break;
+
                case OPT_METHOD:
                        opt_run = false;
                        opt_method = opt_arg;
                        makeinitializations = false;
                        break;
-                       
+
                case OPT_SIGNATURE:
                        opt_signature = opt_arg;
                        break;
-                       
-               case OPT_ALL:
-                       compileall = true;
-                       opt_run = false;
-                       makeinitializations = false;
-                       break;
-                       
+#endif
+
                case OPT_SHOW:       /* Display options */
-                       for (j = 0; j < strlen(opt_arg); j++) {         
-                               switch (opt_arg[j]) {
-                               case 'a':
-                                       opt_showdisassemble = true;
-                                       compileverbose = true;
-                                       break;
+                       for (i = 0; i < strlen(opt_arg); i++) {         
+                               switch (opt_arg[i]) {
                                case 'c':
                                        showconstantpool = true;
                                        break;
-                               case 'd':
-                                       opt_showddatasegment = true;
+
+                               case 'u':
+                                       showutf = true;
                                        break;
-                               case 'e':
-                                       opt_showexceptionstubs = true;
+
+                               case 'm':
+                                       showmethods = true;
                                        break;
+
                                case 'i':
                                        opt_showintermediate = true;
                                        compileverbose = true;
                                        break;
-                               case 'm':
-                                       showmethods = true;
+
+#if defined(ENABLE_DISASSEMBLER)
+                               case 'a':
+                                       opt_showdisassemble = true;
+                                       compileverbose = true;
+                                       break;
+
+                               case 'o':
+                                       opt_shownops = true;
+                                       break;
+
+                               case 'e':
+                                       opt_showexceptionstubs = true;
                                        break;
+
                                case 'n':
                                        opt_shownativestub = true;
                                        break;
-                               case 'u':
-                                       showutf = true;
+#endif
+
+                               case 'd':
+                                       opt_showddatasegment = true;
                                        break;
+
                                default:
                                        usage();
                                }
@@ -940,30 +1261,34 @@ bool vm_create(JavaVMInitArgs *vm_args)
 #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;
+               case OPT_INLINE_REPLACE_VERBOSE:
+                       opt_replace_verbose = 1;
+                       break;
+               case OPT_INLINE_REPLACE_VERBOSE2:
+                       opt_replace_verbose = 2;
+                       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:
-                       for (j = 0; j < strlen(opt_arg); j++) {         
-                               switch (opt_arg[j]) {
-                               case 'n':
-                                       /* define in options.h; Used in main.c, jit.c
-                                          & inline.c inlining is currently
-                                          deactivated */
-                                       break;
-                               case 'v':
-                                       inlinevirtuals = true;
-                                       break;
-                               case 'e':
-                                       inlineexceptions = true;
-                                       break;
-                               case 'p':
-                                       inlineparamopt = true;
-                                       break;
-                               case 'o':
-                                       inlineoutsiders = true;
-                                       break;
-                               default:
-                                       usage();
-                               }
-                       }
+                       opt_inlining = true;
                        break;
 #endif /* defined(ENABLE_INLINING) */
 
@@ -973,7 +1298,7 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        break;
 #endif
 
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
                case OPT_LSRA:
                        opt_lsra = true;
                        break;
@@ -987,25 +1312,38 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        Xusage();
                        break;
 
+               case OPT_XX:
+                       XXusage();
+                       break;
+
+               case OPT_ESA:
+                       _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = true;
+                       break;
+
+               case OPT_DSA:
+                       _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = false;
+                       break;
+
+#if defined(ENABLE_PROFILING)
                case OPT_PROF_OPTION:
                        /* use <= to get the last \0 too */
 
-                       for (j = 0, k = 0; j <= strlen(opt_arg); j++) {
-                               if (opt_arg[j] == ',')
-                                       opt_arg[j] = '\0';
+                       for (i = 0, j = 0; i <= strlen(opt_arg); i++) {
+                               if (opt_arg[i] == ',')
+                                       opt_arg[i] = '\0';
 
-                               if (opt_arg[j] == '\0') {
-                                       if (strcmp("bb", opt_arg + k) == 0)
+                               if (opt_arg[i] == '\0') {
+                                       if (strcmp("bb", opt_arg + j) == 0)
                                                opt_prof_bb = true;
 
                                        else {
-                                               printf("Unknown option: -Xprof:%s\n", opt_arg + k);
+                                               printf("Unknown option: -Xprof:%s\n", opt_arg + j);
                                                usage();
                                        }
 
                                        /* set k to next char */
 
-                                       k = j + 1;
+                                       j = i + 1;
                                }
                        }
                        /* fall through */
@@ -1013,6 +1351,7 @@ bool vm_create(JavaVMInitArgs *vm_args)
                case OPT_PROF:
                        opt_prof = true;
                        break;
+#endif
 
                case OPT_JIT:
 #if defined(ENABLE_JIT)
@@ -1061,14 +1400,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
                }
        }
 
-
-       /* Now we have all options handled and we can print the version
-          information. */
-
-       if (opt_version)
-               version(opt_exit);
-
-
        /* get the main class *****************************************************/
 
        if (opt_index < vm_args->nOptions) {
@@ -1079,15 +1410,15 @@ bool vm_create(JavaVMInitArgs *vm_args)
                if (opt_jar == true) {
                        /* free old classpath */
 
-                       MFREE(classpath, char, strlen(classpath));
+                       MFREE(_Jv_classpath, char, strlen(_Jv_classpath));
 
                        /* put jarfile into classpath */
 
-                       classpath = MNEW(char, strlen(mainstring) + strlen("0"));
+                       _Jv_classpath = MNEW(char, strlen(mainstring) + strlen("0"));
 
-                       strcpy(classpath, mainstring);
-               
-               else {
+                       strcpy(_Jv_classpath, mainstring);
+               }
+               else {
                        /* replace .'s with /'s in classname */
 
                        for (i = strlen(mainstring) - 1; i >= 0; i--)
@@ -1100,17 +1431,25 @@ bool vm_create(JavaVMInitArgs *vm_args)
        if (jvmti) {
                jvmti_set_phase(JVMTI_PHASE_ONLOAD);
                jvmti_agentload(agentarg, agentbypath, &handle, &libname);
-               if (jdwp) MFREE(agentarg,char,strlen(agentarg));
+
+               if (jdwp)
+                       MFREE(agentarg, char, strlen(agentarg));
+
                jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
        }
-
 #endif
 
-
        /* initialize this JVM ****************************************************/
 
        vm_initializing = true;
 
+#if defined(ENABLE_THREADS)
+       /* pre-initialize some core thread stuff, like the stopworldlock,
+          thus this has to happen _before_ gc_init()!!! */
+
+       threads_preinit();
+#endif
+
        /* initialize the garbage collector */
 
        gc_init(opt_heapmaxsize, opt_heapstartsize);
@@ -1124,50 +1463,64 @@ bool vm_create(JavaVMInitArgs *vm_args)
        }
 #endif
 
-#if defined(ENABLE_THREADS)
-       threads_preinit();
-#endif
-
-       /* initialize the string hashtable stuff: lock (must be done
-          _after_ threads_preinit) */
+       /* AFTER: threads_preinit */
 
        if (!string_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: string_init failed");
 
-       /* initialize the utf8 hashtable stuff: lock, often used utf8
-          strings (must be done _after_ threads_preinit) */
+       /* AFTER: threads_preinit */
 
        if (!utf8_init())
-               throw_main_exception_exit();
-
-       /* initialize the classcache hashtable stuff: lock, hashtable
-          (must be done _after_ threads_preinit) */
-
-       if (!classcache_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: utf8_init failed");
 
-       /* initialize the loader with bootclasspath (must be done _after_
-          thread_preinit) */
+       /* AFTER: thread_preinit */
 
        if (!suck_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: suck_init failed");
 
        suck_add_from_property("java.endorsed.dirs");
-       suck_add(bootclasspath);
+
+       /* Now we have all options handled and we can print the version
+          information.
+
+          AFTER: suck_add_from_property("java.endorsed.dirs"); */
+
+       if (opt_version)
+               version(opt_exit);
+
+       /* AFTER: utf8_init */
+
+       suck_add(_Jv_bootclasspath);
+
+       /* Now re-set some of the properties that may have changed. This
+          must be done after _all_ environment variables have been
+          processes (e.g. -jar handling).
+
+          AFTER: suck_add_from_property, since it may change the
+          _Jv_bootclasspath pointer. */
+
+       if (!properties_postinit())
+               vm_abort("vm_create: properties_postinit failed");
+
+       /* initialize the classcache hashtable stuff: lock, hashtable
+          (must be done _after_ threads_preinit) */
+
+       if (!classcache_init())
+               vm_abort("vm_create: classcache_init failed");
 
        /* initialize the memory subsystem (must be done _after_
           threads_preinit) */
 
        if (!memory_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: memory_init failed");
 
        /* initialize the finalizer stuff (must be done _after_
           threads_preinit) */
 
        if (!finalizer_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: finalizer_init failed");
 
-       /* install architecture dependent signal handler used for exceptions */
+       /* install architecture dependent signal handlers */
 
        signal_init();
 
@@ -1196,63 +1549,85 @@ bool vm_create(JavaVMInitArgs *vm_args)
        classcache_init) */
 
        if (!loader_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: loader_init failed");
 
        if (!linker_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: linker_init failed");
 
        if (!native_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: native_init failed");
 
        if (!exceptions_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: exceptions_init failed");
 
        if (!builtin_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: builtin_init failed");
 
+#if defined(ENABLE_JNI)
        /* Initialize the JNI subsystem (must be done _before_
           threads_init, as threads_init can call JNI methods
           (e.g. NewGlobalRef). */
 
        if (!jni_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: jni_init failed");
+#endif
 
 #if defined(ENABLE_THREADS)
        if (!threads_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: threads_init failed");
 #endif
 
-       /* That's important, otherwise we get into trouble, if the Runtime
-          static initializer is called before (circular dependency. This
-          is with classpath 0.09. Another important thing is, that this
-          has to happen after initThreads!!! */
-
-       if (!initialize_class(class_java_lang_System))
-               throw_main_exception_exit();
-
 #if defined(ENABLE_PROFILING)
        /* initialize profiling */
 
        if (!profile_init())
-               throw_main_exception_exit();
+               vm_abort("vm_create: profile_init failed");
 #endif
 
 #if defined(ENABLE_THREADS)
+       /* initialize recompilation */
+
+       if (!recompile_init())
+               vm_abort("vm_create: recompile_init failed");
+
+       /* start the signal handler thread */
+
+       if (!signal_start_thread())
+               vm_abort("vm_create: signal_start_thread failed");
+
        /* finally, start the finalizer thread */
 
        if (!finalizer_start_thread())
-               throw_main_exception_exit();
+               vm_abort("vm_create: finalizer_start_thread failed");
+
+# if !defined(NDEBUG)
+       /* start the memory profiling thread */
+
+       if (opt_verbosememory)
+               if (!memory_start_thread())
+                       vm_abort("vm_create: memory_start_thread failed");
+# endif
+
+       /* start the recompilation thread (must be done before the
+          profiling thread) */
+
+       if (!recompile_start_thread())
+               vm_abort("vm_create: recompile_start_thread failed");
 
 # if defined(ENABLE_PROFILING)
        /* start the profile sampling thread */
 
-       if (opt_prof)
-               if (!profile_start_thread())
-                       throw_main_exception_exit();
+/*     if (opt_prof) */
+/*             if (!profile_start_thread()) */
+/*                     exceptions_print_stacktrace(); */
 # endif
 #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);
@@ -1273,6 +1648,155 @@ bool vm_create(JavaVMInitArgs *vm_args)
 }
 
 
+/* vm_run **********************************************************************
+
+   Runs the main-method of the passed class.
+
+*******************************************************************************/
+
+void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
+{
+       utf               *mainutf;
+       classinfo         *mainclass;
+       methodinfo        *m;
+       java_objectarray  *oa; 
+       s4                 oalength;
+       utf               *u;
+       java_objectheader *s;
+       s4                 status;
+       s4                 i;
+
+#if !defined(NDEBUG)
+       if (compileall) {
+               vm_compile_all();
+               return;
+       }
+
+       if (opt_method != NULL) {
+               vm_compile_method();
+               return;
+       }
+#endif /* !defined(NDEBUG) */
+
+       /* should we run the main-method? */
+
+       if (mainstring == NULL)
+               usage();
+
+       /* set return value to OK */
+
+       status = 0;
+
+       if (opt_jar == true) {
+               /* open jar file with java.util.jar.JarFile */
+
+               mainstring = vm_get_mainclass_from_jar(mainstring);
+
+               if (mainstring == NULL)
+                       vm_exit(1);
+       }
+
+       /* load the main class */
+
+       mainutf = utf_new_char(mainstring);
+
+#if defined(ENABLE_JAVAME_CLDC1_1)
+       mainclass = load_class_bootstrap(mainutf);
+#else
+       mainclass = load_class_from_sysloader(mainutf);
+#endif
+
+       /* error loading class */
+
+       if ((exceptions_get_exception() != NULL) || (mainclass == NULL)) {
+               exceptions_print_stacktrace(); 
+               vm_exit(1);
+       }
+
+       if (!link_class(mainclass)) {
+               exceptions_print_stacktrace();
+               vm_exit(1);
+       }
+                       
+       /* find the `main' method of the main class */
+
+       m = class_resolveclassmethod(mainclass,
+                                                                utf_new_char("main"), 
+                                                                utf_new_char("([Ljava/lang/String;)V"),
+                                                                class_java_lang_Object,
+                                                                false);
+
+       if (exceptions_get_exception()) {
+               exceptions_print_stacktrace();
+               vm_exit(1);
+       }
+
+       /* there is no main method or it isn't static */
+
+       if ((m == NULL) || !(m->flags & ACC_STATIC)) {
+               exceptions_clear_exception();
+               exceptions_throw_nosuchmethoderror(mainclass,
+                                                                                  utf_new_char("main"), 
+                                                                                  utf_new_char("([Ljava/lang/String;)V"));
+
+               exceptions_print_stacktrace();
+               vm_exit(1);
+       }
+
+       /* build argument array */
+
+       oalength = vm_args->nOptions - opt_index;
+
+       oa = builtin_anewarray(oalength, class_java_lang_String);
+
+       for (i = 0; i < oalength; i++) {
+               u = utf_new_char(vm_args->options[opt_index + i].optionString);
+               s = javastring_new(u);
+
+               oa->data[i] = s;
+       }
+
+#ifdef TYPEINFO_DEBUG_TEST
+       /* test the typeinfo system */
+       typeinfo_test();
+#endif
+       /*class_showmethods(currentThread->group->header.vftbl->class); */
+
+#if defined(ENABLE_JVMTI)
+       jvmti_set_phase(JVMTI_PHASE_LIVE);
+#endif
+
+       /* set ThreadMXBean variables */
+
+       _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+       _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
+
+       if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
+               _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
+               _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
+                       _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
+
+       /* start the main thread */
+
+       (void) vm_call_method(m, NULL, oa);
+
+       /* exception occurred? */
+
+       if (exceptions_get_exception()) {
+               exceptions_print_stacktrace();
+               status = 1;
+       }
+
+       /* unload the JavaVM */
+
+       (void) vm_destroy(vm);
+
+       /* and exit */
+
+       vm_exit(status);
+}
+
+
 /* vm_destroy ******************************************************************
 
    Unloads a Java VM and reclaims its resources.
@@ -1315,8 +1839,10 @@ void vm_exit(s4 status)
        }
 #endif
 
-       if (!link_class(class_java_lang_System))
-               throw_main_exception_exit();
+       if (!link_class(class_java_lang_System)) {
+               exceptions_print_stacktrace();
+               exit(1);
+       }
 
        /* call java.lang.System.exit(I)V */
 
@@ -1326,8 +1852,10 @@ void vm_exit(s4 status)
                                                                 class_java_lang_Object,
                                                                 true);
        
-       if (m == NULL)
-               throw_main_exception_exit();
+       if (m == NULL) {
+               exceptions_print_stacktrace();
+               exit(1);
+       }
 
        /* call the exit function with passed exit status */
 
@@ -1427,8 +1955,6 @@ void vm_exit_handler(void)
 #endif
                }
 
-               mem_usagelog(1);
-
                if (opt_getcompilingtime)
                        print_times();
 #endif /* defined(ENABLE_STATISTICS) */
@@ -1463,6 +1989,246 @@ void vm_abort(const char *text, ...)
 }
 
 
+/* vm_get_mainclass_from_jar ***************************************************
+
+   Gets the name of the main class from a JAR's manifest file.
+
+*******************************************************************************/
+
+static char *vm_get_mainclass_from_jar(char *mainstring)
+{
+       classinfo         *c;
+       java_objectheader *o;
+       methodinfo        *m;
+       java_objectheader *s;
+
+       c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
+
+       if (c == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
+
+       /* create JarFile object */
+
+       o = builtin_new(c);
+
+       if (o == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
+
+       m = class_resolveclassmethod(c,
+                                                                utf_init, 
+                                                                utf_java_lang_String__void,
+                                                                class_java_lang_Object,
+                                                                true);
+
+       if (m == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
+
+       s = javastring_new_from_ascii(mainstring);
+
+       (void) vm_call_method(m, o, s);
+
+       if (exceptions_get_exception()) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
+
+       /* get manifest object */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_new_char("getManifest"), 
+                                                                utf_new_char("()Ljava/util/jar/Manifest;"),
+                                                                class_java_lang_Object,
+                                                                true);
+
+       if (m == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
+
+       o = vm_call_method(m, o);
+
+       if (o == NULL) {
+               fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring);
+               return NULL;
+       }
+
+
+       /* get Main Attributes */
+
+       m = class_resolveclassmethod(o->vftbl->class,
+                                                                utf_new_char("getMainAttributes"), 
+                                                                utf_new_char("()Ljava/util/jar/Attributes;"),
+                                                                class_java_lang_Object,
+                                                                true);
+
+       if (m == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
+
+       o = vm_call_method(m, o);
+
+       if (o == NULL) {
+               fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring);
+               return NULL;
+       }
+
+
+       /* get property Main-Class */
+
+       m = class_resolveclassmethod(o->vftbl->class,
+                                                                utf_new_char("getValue"), 
+                                                                utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"),
+                                                                class_java_lang_Object,
+                                                                true);
+
+       if (m == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
+
+       s = javastring_new_from_ascii("Main-Class");
+
+       o = vm_call_method(m, o, s);
+
+       if (o == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
+
+       return javastring_tochar(o);
+}
+
+
+/* vm_compile_all **************************************************************
+
+   Compile all methods found in the bootclasspath.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+static void vm_compile_all(void)
+{
+       classinfo              *c;
+       methodinfo             *m;
+       u4                      slot;
+       classcache_name_entry  *nmen;
+       classcache_class_entry *clsen;
+       s4                      i;
+
+       /* create all classes found in the bootclasspath */
+       /* XXX currently only works with zip/jar's */
+
+       loader_load_all_classes();
+
+       /* link all classes */
+
+       for (slot = 0; slot < hashtable_classcache.size; slot++) {
+               nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+
+               for (; nmen; nmen = nmen->hashlink) {
+                       /* iterate over all class entries */
+
+                       for (clsen = nmen->classes; clsen; clsen = clsen->next) {
+                               c = clsen->classobj;
+
+                               if (c == NULL)
+                                       continue;
+
+                               if (!(c->state & CLASS_LINKED)) {
+                                       if (!link_class(c)) {
+                                               fprintf(stderr, "Error linking: ");
+                                               utf_fprint_printable_ascii_classname(stderr, c->name);
+                                               fprintf(stderr, "\n");
+
+                                               /* print out exception and cause */
+
+                                               exceptions_print_current_exception();
+
+                                               /* goto next class */
+
+                                               continue;
+                                       }
+                               }
+
+                               /* compile all class methods */
+
+                               for (i = 0; i < c->methodscount; i++) {
+                                       m = &(c->methods[i]);
+
+                                       if (m->jcode != NULL) {
+                                               if (!jit_compile(m)) {
+                                                       fprintf(stderr, "Error compiling: ");
+                                                       utf_fprint_printable_ascii_classname(stderr, c->name);
+                                                       fprintf(stderr, ".");
+                                                       utf_fprint_printable_ascii(stderr, m->name);
+                                                       utf_fprint_printable_ascii(stderr, m->descriptor);
+                                                       fprintf(stderr, "\n");
+
+                                                       /* print out exception and cause */
+
+                                                       exceptions_print_current_exception();
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* vm_compile_method ***********************************************************
+
+   Compile a specific method.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+static void vm_compile_method(void)
+{
+       methodinfo *m;
+
+       /* create, load and link the main class */
+
+       mainclass = load_class_bootstrap(utf_new_char(mainstring));
+
+       if (mainclass == NULL)
+               exceptions_print_stacktrace();
+
+       if (!link_class(mainclass))
+               exceptions_print_stacktrace();
+
+       if (opt_signature != NULL) {
+               m = class_resolveclassmethod(mainclass,
+                                                                        utf_new_char(opt_method),
+                                                                        utf_new_char(opt_signature),
+                                                                        mainclass,
+                                                                        false);
+       }
+       else {
+               m = class_resolveclassmethod(mainclass,
+                                                                        utf_new_char(opt_method),
+                                                                        NULL,
+                                                                        mainclass,
+                                                                        false);
+       }
+
+       if (m == NULL)
+               vm_abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
+                                opt_method, opt_signature ? opt_signature : "");
+               
+       jit_compile(m);
+}
+#endif /* !defined(NDEBUG) */
+
+
 /* vm_vmargs_from_valist *******************************************************
 
    XXX
@@ -1720,6 +2486,10 @@ java_objectheader *vm_call_method_vmarg(methodinfo *m, s4 vmargscount,
 {
        java_objectheader *o;
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
+#endif
+
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (opt_intrp)
@@ -1731,6 +2501,10 @@ java_objectheader *vm_call_method_vmarg(methodinfo *m, s4 vmargscount,
        o = intrp_asm_vm_call_method(m, vmargscount, vmargs);
 #endif
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
+#endif
+
        return o;
 }
 
@@ -1850,6 +2624,10 @@ s4 vm_call_method_int_vmarg(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
 {
        s4 i;
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
+#endif
+
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (opt_intrp)
@@ -1861,6 +2639,10 @@ s4 vm_call_method_int_vmarg(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
        i = intrp_asm_vm_call_method_int(m, vmargscount, vmargs);
 #endif
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
+#endif
+
        return i;
 }
 
@@ -1980,6 +2762,10 @@ s8 vm_call_method_long_vmarg(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
 {
        s8 l;
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
+#endif
+
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (opt_intrp)
@@ -1991,6 +2777,10 @@ s8 vm_call_method_long_vmarg(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
        l = intrp_asm_vm_call_method_long(m, vmargscount, vmargs);
 #endif
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
+#endif
+
        return l;
 }
 
@@ -2112,6 +2902,10 @@ float vm_call_method_float_vmarg(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
 {
        float f;
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
+#endif
+
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (opt_intrp)
@@ -2123,6 +2917,10 @@ float vm_call_method_float_vmarg(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
        f = intrp_asm_vm_call_method_float(m, vmargscount, vmargs);
 #endif
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
+#endif
+
        return f;
 }
 
@@ -2245,6 +3043,10 @@ double vm_call_method_double_vmarg(methodinfo *m, s4 vmargscount,
 {
        double d;
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
+#endif
+
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (opt_intrp)
@@ -2256,6 +3058,10 @@ double vm_call_method_double_vmarg(methodinfo *m, s4 vmargscount,
        d = intrp_asm_vm_call_method_double(m, vmargscount, vmargs);
 #endif
 
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
+#endif
+
        return d;
 }