Merged revisions 7501-7598 via svnmerge from
[cacao.git] / src / vm / vm.c
index 8f5eff6a0762063be84ad72f4f64bb10cd41776e..5d1cc1e49031606ff24df2ae3298a25e508baf82 100644 (file)
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-            Martin Platter
-
    $Id: vm.c 4357 2006-01-22 23:33:38Z twisti $
 
 */
 
 #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/rt-timing.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"
 
 #if defined(ENABLE_PROFILING)
 
 #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"
 #endif
@@ -144,6 +147,7 @@ enum {
 
        OPT_HELP,
        OPT_X,
+       OPT_XX,
 
        OPT_ESA,
        OPT_DSA,
@@ -171,7 +175,6 @@ enum {
 
        OPT_VERBOSE1,
        OPT_NOIEEE,
-       OPT_SOFTNULL,
 
 #if defined(ENABLE_STATISTICS)
        OPT_TIME,
@@ -214,7 +217,18 @@ enum {
 
 #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 */
@@ -263,6 +277,7 @@ 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 },
@@ -282,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 },
@@ -350,11 +364,24 @@ opt_struct opts[] = {
        { "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 },
@@ -380,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)");
@@ -397,11 +424,11 @@ void usage(void)
        puts("    -showversion             print product version and continue");
        puts("    -help, -?                print this help message");
        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");
-       puts("");
 
 #ifdef ENABLE_JVMTI
        puts("    -agentlib:<agent-lib-name>=<options>  library to load containg JVMTI agent");
@@ -409,11 +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
@@ -423,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");
@@ -453,14 +527,23 @@ void usage(void)
        puts("      (e)xceptionstubs       disassembled exception stubs (only with -sa)");
        puts("      (n)ative               disassembled native stubs");
 #endif
-       puts("           (d)atasegment     data segment listing");
+       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
@@ -474,46 +557,7 @@ void usage(void)
        /* 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);
-}   
+}
 
 
 /* version *********************************************************************
@@ -527,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");
@@ -623,7 +667,7 @@ bool vm_createjvm(JavaVM **p_vm, void **p_env, void *vm_args)
 
        env = NEW(_Jv_JNIEnv);
 
-#if defined(ENABLE_JAVASE)
+#if defined(ENABLE_JNI)
        env->env = &_Jv_JNINativeInterface;
 #endif
 
@@ -635,7 +679,7 @@ bool vm_createjvm(JavaVM **p_vm, void **p_env, void *vm_args)
 
        vm = NEW(_Jv_JavaVM);
 
-#if defined(ENABLE_JAVASE)
+#if defined(ENABLE_JNI)
        vm->functions = &_Jv_JNIInvokeInterface;
 #endif
 
@@ -649,7 +693,7 @@ bool vm_createjvm(JavaVM **p_vm, void **p_env, void *vm_args)
        if (!vm_create(_vm_args))
                goto error;
 
-#if defined(ENABLE_JAVASE)
+#if defined(ENABLE_JNI)
        /* setup the local ref table (must be created after vm_create) */
 
        if (!jni_init_localref_table())
@@ -718,6 +762,13 @@ bool vm_create(JavaVMInitArgs *vm_args)
        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();
@@ -835,7 +886,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
        opt_version       = false;
        opt_exit          = false;
 
-       checknull         = false;
        opt_noieee        = false;
 
        opt_heapmaxsize   = HEAP_MAXSIZE;
@@ -1031,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;
@@ -1050,8 +1104,16 @@ 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;
@@ -1086,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;
@@ -1203,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 (i = 0; i < strlen(opt_arg); i++) {         
-                               switch (opt_arg[i]) {
-                               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) */
 
@@ -1250,6 +1312,10 @@ 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;
@@ -1373,19 +1439,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
        }
 #endif
 
-       /* 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). */
-
-       if (!properties_postinit())
-               vm_abort("properties_postinit failed");
-
-       /* Now we have all options handled and we can print the version
-          information. */
-
-       if (opt_version)
-               version(opt_exit);
-
        /* initialize this JVM ****************************************************/
 
        vm_initializing = true;
@@ -1410,46 +1463,64 @@ bool vm_create(JavaVMInitArgs *vm_args)
        }
 #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) */
+               vm_abort("vm_create: utf8_init failed");
 
-       if (!classcache_init())
-               throw_main_exception_exit();
-
-       /* 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");
+
+       /* 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();
 
@@ -1478,68 +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_JAVASE)
+#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
 
 #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())
-               throw_main_exception_exit();
-               
+               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())
-               throw_main_exception_exit();
+               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(); */
+/*                     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);
@@ -1568,15 +1656,15 @@ bool vm_create(JavaVMInitArgs *vm_args)
 
 void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
 {
-       utf              *mainutf;
-       classinfo        *mainclass;
-       methodinfo       *m;
-       java_objectarray *oa; 
-       s4                oalength;
-       utf              *u;
-       java_lang_String *s;
-       s4                status;
-       s4                i;
+       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) {
@@ -1599,29 +1687,36 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
 
        status = 0;
 
-       if (opt_jar == true)
+       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)
-       if (!(mainclass = load_class_bootstrap(mainutf)))
-               throw_main_exception_exit();
+       mainclass = load_class_bootstrap(mainutf);
 #else
-       if (!(mainclass = load_class_from_sysloader(mainutf)))
-               throw_main_exception_exit();
+       mainclass = load_class_from_sysloader(mainutf);
 #endif
 
        /* error loading class */
 
-       if ((*exceptionptr != NULL) || (mainclass == NULL))
-               throw_main_exception_exit();
+       if ((exceptions_get_exception() != NULL) || (mainclass == NULL)) {
+               exceptions_print_stacktrace(); 
+               vm_exit(1);
+       }
 
-       if (!link_class(mainclass))
-               throw_main_exception_exit();
+       if (!link_class(mainclass)) {
+               exceptions_print_stacktrace();
+               vm_exit(1);
+       }
                        
        /* find the `main' method of the main class */
 
@@ -1631,18 +1726,21 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
                                                                 class_java_lang_Object,
                                                                 false);
 
-       if (*exceptionptr) {
-               throw_main_exception_exit();
+       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)) {
-               *exceptionptr = NULL;
+               exceptions_clear_exception();
+               exceptions_throw_nosuchmethoderror(mainclass,
+                                                                                  utf_new_char("main"), 
+                                                                                  utf_new_char("([Ljava/lang/String;)V"));
 
-               *exceptionptr =
-                       new_exception_message(string_java_lang_NoSuchMethodError, "main");
-               throw_main_exception_exit();
+               exceptions_print_stacktrace();
+               vm_exit(1);
        }
 
        /* build argument array */
@@ -1655,7 +1753,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
                u = utf_new_char(vm_args->options[opt_index + i].optionString);
                s = javastring_new(u);
 
-               oa->data[i] = (java_objectheader *) s;
+               oa->data[i] = s;
        }
 
 #ifdef TYPEINFO_DEBUG_TEST
@@ -1684,14 +1782,14 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
 
        /* exception occurred? */
 
-       if (*exceptionptr) {
-               throw_main_exception();
+       if (exceptions_get_exception()) {
+               exceptions_print_stacktrace();
                status = 1;
        }
 
        /* unload the JavaVM */
 
-       vm_destroy(vm);
+       (void) vm_destroy(vm);
 
        /* and exit */
 
@@ -1741,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 */
 
@@ -1752,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 */
 
@@ -1853,8 +1955,6 @@ void vm_exit_handler(void)
 #endif
                }
 
-               mem_usagelog(1);
-
                if (opt_getcompilingtime)
                        print_times();
 #endif /* defined(ENABLE_STATISTICS) */
@@ -1900,20 +2000,23 @@ static char *vm_get_mainclass_from_jar(char *mainstring)
        classinfo         *c;
        java_objectheader *o;
        methodinfo        *m;
-       java_lang_String  *s;
+       java_objectheader *s;
 
        c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
 
-       if (c == NULL)
-               throw_main_exception_exit();
-       
+       if (c == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
+
        /* create JarFile object */
 
        o = builtin_new(c);
 
-       if (o == NULL)
-               throw_main_exception_exit();
-
+       if (o == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
 
        m = class_resolveclassmethod(c,
                                                                 utf_init, 
@@ -1921,15 +2024,19 @@ static char *vm_get_mainclass_from_jar(char *mainstring)
                                                                 class_java_lang_Object,
                                                                 true);
 
-       if (m == NULL)
-               throw_main_exception_exit();
+       if (m == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
 
        s = javastring_new_from_ascii(mainstring);
 
        (void) vm_call_method(m, o, s);
 
-       if (*exceptionptr)
-               throw_main_exception_exit();
+       if (exceptions_get_exception()) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
 
        /* get manifest object */
 
@@ -1939,14 +2046,16 @@ static char *vm_get_mainclass_from_jar(char *mainstring)
                                                                 class_java_lang_Object,
                                                                 true);
 
-       if (m == NULL)
-               throw_main_exception_exit();
+       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);
-               vm_exit(1);
+               return NULL;
        }
 
 
@@ -1958,14 +2067,16 @@ static char *vm_get_mainclass_from_jar(char *mainstring)
                                                                 class_java_lang_Object,
                                                                 true);
 
-       if (m == NULL)
-               throw_main_exception_exit();
+       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);
-               vm_exit(1);
+               return NULL;
        }
 
 
@@ -1977,15 +2088,19 @@ static char *vm_get_mainclass_from_jar(char *mainstring)
                                                                 class_java_lang_Object,
                                                                 true);
 
-       if (m == NULL)
-               throw_main_exception_exit();
+       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)
-               throw_main_exception_exit();
+       if (o == NULL) {
+               exceptions_print_stacktrace();
+               return NULL;
+       }
 
        return javastring_tochar(o);
 }
@@ -2034,7 +2149,7 @@ static void vm_compile_all(void)
 
                                                /* print out exception and cause */
 
-                                               exceptions_print_exception(*exceptionptr);
+                                               exceptions_print_current_exception();
 
                                                /* goto next class */
 
@@ -2058,7 +2173,7 @@ static void vm_compile_all(void)
 
                                                        /* print out exception and cause */
 
-                                                       exceptions_print_exception(*exceptionptr);
+                                                       exceptions_print_current_exception();
                                                }
                                        }
                                }
@@ -2082,11 +2197,13 @@ static void vm_compile_method(void)
 
        /* create, load and link the main class */
 
-       if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring))))
-               throw_main_exception_exit();
+       mainclass = load_class_bootstrap(utf_new_char(mainstring));
+
+       if (mainclass == NULL)
+               exceptions_print_stacktrace();
 
        if (!link_class(mainclass))
-               throw_main_exception_exit();
+               exceptions_print_stacktrace();
 
        if (opt_signature != NULL) {
                m = class_resolveclassmethod(mainclass,
@@ -2103,17 +2220,9 @@ static void vm_compile_method(void)
                                                                         false);
        }
 
-       if (m == NULL) {
-               char message[MAXLOGTEXT];
-               sprintf(message, "%s%s", opt_method,
-                               opt_signature ? opt_signature : "");
-
-               *exceptionptr =
-                       new_exception_message(string_java_lang_NoSuchMethodException,
-                                                                 message);
-                                                                                
-               throw_main_exception_exit();
-       }
+       if (m == NULL)
+               vm_abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
+                                opt_method, opt_signature ? opt_signature : "");
                
        jit_compile(m);
 }
@@ -2377,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)
@@ -2388,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;
 }
 
@@ -2507,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)
@@ -2518,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;
 }
 
@@ -2637,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)
@@ -2648,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;
 }
 
@@ -2769,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)
@@ -2780,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;
 }
 
@@ -2902,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)
@@ -2913,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;
 }