* src/vm/jit/verify/typecheck.c (verify_fieldaccess): New function.
[cacao.git] / src / vm / vm.c
index 748890fe6ef736cadbd47a132be8940317f5b5cd..3179ea7579250e4bc047203ddf602c6bcb93e946 100644 (file)
 #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"
@@ -62,6 +68,9 @@
 #include "vm/vm.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/asmpart.h"
+
+#include "vm/jit/recompile.h"
+
 #include "vm/jit/profile/profile.h"
 #include "vm/rt-timing.h"
 
@@ -69,6 +78,7 @@
 #include "native/jvmti/cacaodbg.h"
 #endif
 
+
 /* Invocation API variables ***************************************************/
 
 _Jv_JavaVM *_Jv_jvm;                    /* denotes a Java VM                  */
@@ -82,11 +92,11 @@ 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      *mainstring = NULL;
 classinfo *mainclass = NULL;
 
 char *specificmethodname = NULL;
@@ -94,6 +104,10 @@ char *specificsignature = NULL;
 
 bool startit = true;
 
+#if defined(ENABLE_INTRP)
+u1 *intrp_main_stack = NULL;
+#endif
+
 
 /* define heap sizes **********************************************************/
 
@@ -105,6 +119,8 @@ bool startit = true;
 /* define command line options ************************************************/
 
 enum {
+       OPT_FOO,
+
        /* Java options */
 
        OPT_JAR,
@@ -124,6 +140,9 @@ enum {
        OPT_HELP,
        OPT_X,
 
+       OPT_ESA,
+       OPT_DSA,
+
        /* Java non-standard options */
 
        OPT_JIT,
@@ -133,6 +152,8 @@ enum {
        OPT_BOOTCLASSPATH_A,
        OPT_BOOTCLASSPATH_P,
 
+       OPT_GLIBJ,
+
        OPT_PROF,
        OPT_PROF_OPTION,
 
@@ -153,10 +174,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,
@@ -176,7 +201,7 @@ enum {
        OPT_IFCONV,
 #endif
 
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
        OPT_LSRA,
 #endif
 
@@ -209,6 +234,8 @@ enum {
 
 
 opt_struct opts[] = {
+       { "foo",               false, OPT_FOO },
+
        /* Java options */
 
        { "jar",               false, OPT_JAR },
@@ -217,6 +244,7 @@ opt_struct opts[] = {
        { "d64",               false, OPT_D64 },
        { "client",            false, OPT_IGNORE },
        { "server",            false, OPT_IGNORE },
+       { "jvm",               false, OPT_IGNORE },
        { "hotspot",           false, OPT_IGNORE },
 
        { "classpath",         true,  OPT_CLASSPATH },
@@ -229,6 +257,11 @@ opt_struct opts[] = {
        { "?",                 false, OPT_HELP },
        { "X",                 false, OPT_X },
 
+       { "esa",                     false, OPT_ESA },
+       { "enablesystemassertions",  false, OPT_ESA },
+       { "dsa",                     false, OPT_DSA },
+       { "disablesystemassertions", false, OPT_DSA },
+
        { "noasyncgc",         false, OPT_IGNORE },
 #if defined(ENABLE_VERIFIER)
        { "noverify",          false, OPT_NOVERIFY },
@@ -251,15 +284,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
 
@@ -286,11 +323,14 @@ opt_struct opts[] = {
        { "Xbootclasspath:",   true,  OPT_BOOTCLASSPATH },
        { "Xbootclasspath/a:", true,  OPT_BOOTCLASSPATH_A },
        { "Xbootclasspath/p:", true,  OPT_BOOTCLASSPATH_P },
+       { "Xglibj:",           true,  OPT_GLIBJ },
+
 #ifdef ENABLE_JVMTI
        { "Xdebug",            false, OPT_DEBUG },
        { "Xnoagent",          false, OPT_NOAGENT },
        { "Xrunjdwp",          true,  OPT_XRUNJDWP },
 #endif 
+
        { "Xms",               true,  OPT_MS },
        { "ms",                true,  OPT_MS },
        { "Xmx",               true,  OPT_MX },
@@ -305,8 +345,13 @@ opt_struct opts[] = {
 #if defined(ENABLE_INLINING)
        { "i",                 true,  OPT_INLINING },
 #endif
+
+#if !defined(NDEBUG)
        { "m",                 true,  OPT_METHOD },
+#endif
+
        { "s",                 true,  OPT_SHOW },
+       { "debug-color",      false,  OPT_DEBUGCOLOR },
 
        { NULL,                false, 0 }
 };
@@ -330,6 +375,7 @@ void usage(void)
        puts("    -d64                     use 64-bit data model if available");
        puts("    -client                  compatibility (currently ignored)");
        puts("    -server                  compatibility (currently ignored)");
+       puts("    -jvm                     compatibility (currently ignored)");
        puts("    -hotspot                 compatibility (currently ignored)\n");
 
        puts("    -cp <path>               specify a path to look for classes");
@@ -340,16 +386,24 @@ 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("    -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");
+       puts ("                                         for jdwp help use: -agentlib:jdwp=help");
        puts("    -agentpath:<path-to-agent>=<options>  path to library containg JVMTI agent");
 #endif
 
-       puts("CACAO options:\n");
+       puts("CACAO options:");
        puts("    -v                       write state-information");
-       puts("    -verbose[:call|exception]enable specific verbose output");
+       puts("    -verbose[:call|exception|jit]");
+       puts("                             enable specific verbose output");
+       puts("    -debug-color             colored output for ANSI terms");
 #ifdef TYPECHECK_VERBOSE
        puts("    -verbosetc               write debug messages while typechecking");
 #endif
@@ -372,17 +426,23 @@ 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(how)...               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("           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)");
@@ -396,6 +456,9 @@ void usage(void)
 #if defined(ENABLE_LSRA)
        puts("    -lsra                    use linear scan register allocation");
 #endif
+#if defined(ENABLE_SSA)
+       puts("    -lsra                    use linear scan register allocation (with SSA)");
+#endif
 
        /* exit with error code */
 
@@ -417,6 +480,9 @@ static void Xusage(void)
        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);
@@ -424,9 +490,9 @@ static void Xusage(void)
 #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("    -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");
+       puts("                             enable remote debugging\n");
 #endif 
 
        /* exit with error code */
@@ -441,7 +507,7 @@ static void Xusage(void)
 
 *******************************************************************************/
 
-static void version(void)
+static void version(bool opt_exit)
 {
        puts("java version \""JAVA_VERSION"\"");
        puts("CACAO version "VERSION"");
@@ -471,17 +537,23 @@ static void version(void)
        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_PATH":"CLASSPATH_GLIBJ_ZIP_PATH"");
-       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);
+       puts("  java.boot.class.path           : "CACAO_VM_ZIP":"CLASSPATH_GLIBJ_ZIP"");
+       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", bootclasspath);
+       printf("  gnu.classpath.boot.library.path: %s\n", classpath_libdir);
+
+       /* exit normally, if requested */
+
+       if (opt_exit)
+               exit(0);
 }
 
 
@@ -502,6 +574,15 @@ 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_create *******************************************************************
 
    Creates a JVM.  Called by JNI_CreateJavaVM.
@@ -511,18 +592,18 @@ static void fullversion(void)
 bool vm_create(JavaVMInitArgs *vm_args)
 {
        char *cp;
-       s4    cplen;
+       s4    len;
        s4    opt;
        s4    i, j, k;
-
+       bool  opt_version;
+       bool  opt_exit;
 
 #if defined(ENABLE_JVMTI)
        lt_dlhandle  handle;
-       char* libname;
-       bool agentbypath = false;;
+       char *libname, *agentarg;
+       bool jdwp,agentbypath;
+       jdwp = agentbypath = false;
 #endif
-       
-
 
        /* check the JNI version requested */
 
@@ -541,6 +622,15 @@ 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 -------------------------------------------------------");
+
+       /* set the VM starttime */
+
+       _Jv_jvm->starttime = builtin_currenttimemillis();
 
        /* get stuff from the environment *****************************************/
 
@@ -548,46 +638,104 @@ bool vm_create(JavaVMInitArgs *vm_args)
        nogc_init(HEAP_MAXSIZE, HEAP_STARTSIZE);
 #endif
 
+#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) {
+       if (cp != NULL) {
                bootclasspath = MNEW(char, strlen(cp) + strlen("0"));
                strcpy(bootclasspath, cp);
+       }
+       else {
+#if defined(WITH_JRE_LAYOUT)
+               len =
+                       strlen(cacao_prefix) +
+                       strlen("/share/cacao/vm.zip") +
+                       strlen(":") +
+                       strlen(cacao_prefix) +
+                       strlen("/share/classpath/glibj.zip") +
+                       strlen("0");
 
-       } else {
-               cplen = strlen(CACAO_VM_ZIP_PATH) +
+               bootclasspath = MNEW(char, len);
+               strcat(bootclasspath, cacao_prefix);
+               strcat(bootclasspath, "/share/cacao/vm.zip");
+               strcat(bootclasspath, ":");
+               strcat(bootclasspath, cacao_prefix);
+               strcat(bootclasspath, "/share/classpath/glibj.zip");
+#else
+               len = strlen(CACAO_VM_ZIP) +
                        strlen(":") +
-                       strlen(CLASSPATH_GLIBJ_ZIP_PATH) +
+                       strlen(CLASSPATH_GLIBJ_ZIP) +
                        strlen("0");
 
-               bootclasspath = MNEW(char, cplen);
-               strcat(bootclasspath, CACAO_VM_ZIP_PATH);
+               bootclasspath = MNEW(char, len);
+               strcat(bootclasspath, CACAO_VM_ZIP);
                strcat(bootclasspath, ":");
-               strcat(bootclasspath, CLASSPATH_GLIBJ_ZIP_PATH);
+               strcat(bootclasspath, CLASSPATH_GLIBJ_ZIP);
+#endif
        }
 
-
        /* set the classpath */
 
        cp = getenv("CLASSPATH");
 
-       if (cp) {
+       if (cp != NULL) {
                classpath = MNEW(char, strlen(cp) + strlen("0"));
                strcat(classpath, cp);
-
-       else {
+       }
+       else {
                classpath = MNEW(char, strlen(".") + strlen("0"));
                strcpy(classpath, ".");
        }
 
 
        /* interpret the options **************************************************/
-   
-       checknull  = false;
-       opt_noieee = false;
+
+       opt_version       = false;
+       opt_exit          = false;
+
+       checknull         = false;
+       opt_noieee        = false;
 
        opt_heapmaxsize   = HEAP_MAXSIZE;
        opt_heapstartsize = HEAP_STARTSIZE;
@@ -596,7 +744,7 @@ bool vm_create(JavaVMInitArgs *vm_args)
 
 #if defined(ENABLE_JVMTI)
        /* initialize JVMTI related  **********************************************/
-       jdwp = jvmti = false;
+       jvmti = false;
 #endif
 
        /* initialize properties before commandline handling */
@@ -609,11 +757,14 @@ bool vm_create(JavaVMInitArgs *vm_args)
 
        properties_add("java.endorsed.dirs", ""CACAO_PREFIX"/jre/lib/endorsed");
 
-
        /* 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;
                        
@@ -648,7 +799,7 @@ bool vm_create(JavaVMInitArgs *vm_args)
                                if (opt_arg[j] == '=') {
                                        opt_arg[j] = '\0';
                                        properties_add(opt_arg, opt_arg + j + 1);
-                                       goto didit;
+                                       goto opt_d_done;
                                }
                        }
 
@@ -656,12 +807,13 @@ bool vm_create(JavaVMInitArgs *vm_args)
 
                        properties_add(opt_arg, "");
 
-               didit:
+               opt_d_done:
                        break;
 
                case OPT_BOOTCLASSPATH:
                        /* Forget default bootclasspath and set the argument as
                           new boot classpath. */
+
                        MFREE(bootclasspath, char, strlen(bootclasspath));
 
                        bootclasspath = MNEW(char, strlen(opt_arg) + strlen("0"));
@@ -670,12 +822,13 @@ bool vm_create(JavaVMInitArgs *vm_args)
 
                case OPT_BOOTCLASSPATH_A:
                        /* append to end of bootclasspath */
-                       cplen = strlen(bootclasspath);
+
+                       len = strlen(bootclasspath);
 
                        bootclasspath = MREALLOC(bootclasspath,
                                                                         char,
-                                                                        cplen,
-                                                                        cplen + strlen(":") +
+                                                                        len,
+                                                                        len + strlen(":") +
                                                                         strlen(opt_arg) + strlen("0"));
 
                        strcat(bootclasspath, ":");
@@ -684,55 +837,70 @@ bool vm_create(JavaVMInitArgs *vm_args)
 
                case OPT_BOOTCLASSPATH_P:
                        /* prepend in front of bootclasspath */
+
                        cp = bootclasspath;
-                       cplen = strlen(cp);
+                       len = strlen(cp);
 
                        bootclasspath = MNEW(char, strlen(opt_arg) + strlen(":") +
-                                                                cplen + strlen("0"));
+                                                                len + strlen("0"));
 
                        strcpy(bootclasspath, opt_arg);
                        strcat(bootclasspath, ":");
                        strcat(bootclasspath, cp);
 
-                       MFREE(cp, char, cplen);
+                       MFREE(cp, char, len);
+                       break;
+
+               case OPT_GLIBJ:
+                       /* use as Java core library, but prepend VM interface classes */
+
+                       MFREE(bootclasspath, char, strlen(bootclasspath));
+
+                       len = strlen(CACAO_VM_ZIP) +
+                               strlen(":") +
+                               strlen(opt_arg) +
+                               strlen("0");
+
+                       bootclasspath = MNEW(char, len);
+
+                       strcpy(bootclasspath, CACAO_VM_ZIP);
+                       strcat(bootclasspath, ":");
+                       strcat(bootclasspath, opt_arg);
                        break;
 
 #if defined(ENABLE_JVMTI)
                case OPT_DEBUG:
-                       jdwp=true;
+                       /* 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:
-                       transport = opt_arg;
-                       j=0;
-                       while (transport[j]!='=') j++;
-                       j++;
-                       while (j<strlen(transport)) {
-                               if (strncmp("suspend=",&transport[j],8)==0) {
-                                       if ((j+8)>=strlen(transport) || 
-                                               (transport[j+8]!= 'y' && transport[j+8]!= 'n')) {
-                                               printf("bad Xrunjdwp option: -Xrunjdwp%s\n",transport);
-                                               usage();
-                                               break;
-                                       }
-                                       else {
-                                               suspend = transport[j+8] == 'y';
-                                               break;
-                                       }
-                               }
-                               while (transport[j]!=',') j++;
-                               j++;
-                       }
-                       
+                       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
@@ -789,6 +957,9 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        else if (strcmp("exception", opt_arg) == 0)
                                opt_verboseexception = true;
                        break;
+               case OPT_DEBUGCOLOR:
+                       opt_debugcolor = true;
+                       break;
 
 #if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
                case OPT_VERBOSETC:
@@ -797,8 +968,8 @@ bool vm_create(JavaVMInitArgs *vm_args)
 #endif
                                
                case OPT_VERSION:
-                       version();
-                       exit(0);
+                       opt_version = true;
+                       opt_exit    = true;
                        break;
 
                case OPT_FULLVERSION:
@@ -806,7 +977,7 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        break;
 
                case OPT_SHOWVERSION:
-                       version();
+                       opt_version = true;
                        break;
 
                case OPT_NOIEEE:
@@ -862,51 +1033,63 @@ 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;
                                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 'e':
+                                       opt_showexceptionstubs = true;
                                        break;
+
                                case 'n':
                                        opt_shownativestub = true;
                                        break;
-                               case 'u':
-                                       showutf = true;
+#endif
+
+                               case 'd':
+                                       opt_showddatasegment = true;
                                        break;
+
                                default:
                                        usage();
                                }
@@ -953,7 +1136,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;
@@ -967,6 +1150,14 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        Xusage();
                        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;
+
                case OPT_PROF_OPTION:
                        /* use <= to get the last \0 too */
 
@@ -1006,6 +1197,10 @@ bool vm_create(JavaVMInitArgs *vm_args)
                case OPT_INTRP:
 #if defined(ENABLE_INTRP)
                        opt_intrp = true;
+#if defined(ENABLE_VERIFIER)
+                       /* XXX currently the verifier does not work with the interpreter */
+                       opt_verify = false;
+#endif
 #else
                        printf("-Xint option not enabled.\n");
                        exit(1);
@@ -1042,6 +1237,13 @@ 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) {
@@ -1059,8 +1261,8 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        classpath = MNEW(char, strlen(mainstring) + strlen("0"));
 
                        strcpy(classpath, mainstring);
-               
-               else {
+               }
+               else {
                        /* replace .'s with /'s in classname */
 
                        for (i = strlen(mainstring) - 1; i >= 0; i--)
@@ -1073,8 +1275,13 @@ 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));
+
+               jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
        }
-       jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
+
 #endif
 
 
@@ -1209,15 +1416,29 @@ bool vm_create(JavaVMInitArgs *vm_args)
 #endif
 
 #if defined(ENABLE_THREADS)
+       /* initialize recompilation */
+
+       if (!recompile_init())
+               throw_main_exception_exit();
+               
        /* finally, start the finalizer thread */
 
        if (!finalizer_start_thread())
                throw_main_exception_exit();
 
+       /* start the recompilation thread (must be done before the
+          profiling thread) */
+
+       if (!recompile_start_thread())
+               throw_main_exception_exit();
+
+# if defined(ENABLE_PROFILING)
        /* start the profile sampling thread */
 
-/*     if (!profile_start_thread()) */
-/*             throw_main_exception_exit(); */
+       if (opt_prof)
+               if (!profile_start_thread())
+                       throw_main_exception_exit();
+# endif
 #endif
 
 #if defined(ENABLE_JVMTI)
@@ -1241,6 +1462,140 @@ 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_lang_String *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);
+
+       /* load the main class */
+
+       mainutf = utf_new_char(mainstring);
+
+       if (!(mainclass = load_class_from_sysloader(mainutf)))
+               throw_main_exception_exit();
+
+       /* error loading class, clear exceptionptr for new exception */
+
+       if (*exceptionptr || !mainclass) {
+               /*                      *exceptionptr = NULL; */
+
+               /*                      *exceptionptr = */
+               /*                              new_exception_message(string_java_lang_NoClassDefFoundError, */
+               /*                                                                        mainstring); */
+               throw_main_exception_exit();
+       }
+
+       if (!link_class(mainclass))
+               throw_main_exception_exit();
+                       
+       /* 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 (*exceptionptr) {
+               throw_main_exception_exit();
+       }
+
+       /* there is no main method or it isn't static */
+
+       if ((m == NULL) || !(m->flags & ACC_STATIC)) {
+               *exceptionptr = NULL;
+
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NoSuchMethodError, "main");
+               throw_main_exception_exit();
+       }
+
+       /* 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] = (java_objectheader *) 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
+
+       /* increase total started thread count */
+
+       _Jv_jvm->total_started_thread_count++;
+
+       /* start the main thread */
+
+       (void) vm_call_method(m, NULL, oa);
+
+       /* exception occurred? */
+
+       if (*exceptionptr) {
+               throw_main_exception();
+               status = 1;
+       }
+
+       /* unload the JavaVM */
+
+       vm_destroy(vm);
+
+       /* and exit */
+
+       vm_exit(status);
+}
+
+
 /* vm_destroy ******************************************************************
 
    Unloads a Java VM and reclaims its resources.
@@ -1325,8 +1680,19 @@ void vm_shutdown(s4 status)
        {
                log_text("CACAO terminated by shutdown");
                dolog("Exit status: %d\n", (s4) status);
+
        }
 
+#if defined(ENABLE_JVMTI)
+       /* terminate cacaodbgserver */
+       if (dbgcom!=NULL) {
+               pthread_mutex_lock(&dbgcomlock);
+               dbgcom->running=1;
+               pthread_mutex_unlock(&dbgcomlock);
+               jvmti_cacaodbgserver_quit();
+       }       
+#endif
+
        exit(status);
 }
 
@@ -1420,6 +1786,237 @@ 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_lang_String  *s;
+
+       c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
+
+       if (c == NULL)
+               throw_main_exception_exit();
+       
+       /* create JarFile object */
+
+       o = builtin_new(c);
+
+       if (o == NULL)
+               throw_main_exception_exit();
+
+
+       m = class_resolveclassmethod(c,
+                                                                utf_init, 
+                                                                utf_java_lang_String__void,
+                                                                class_java_lang_Object,
+                                                                true);
+
+       if (m == NULL)
+               throw_main_exception_exit();
+
+       s = javastring_new_from_ascii(mainstring);
+
+       (void) vm_call_method(m, o, s);
+
+       if (*exceptionptr)
+               throw_main_exception_exit();
+
+       /* 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)
+               throw_main_exception_exit();
+
+       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);
+       }
+
+
+       /* 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)
+               throw_main_exception_exit();
+
+       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);
+       }
+
+
+       /* 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)
+               throw_main_exception_exit();
+
+       s = javastring_new_from_ascii("Main-Class");
+
+       o = vm_call_method(m, o, s);
+
+       if (o == NULL)
+               throw_main_exception_exit();
+
+       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_exception(*exceptionptr);
+
+                                               /* 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_exception(*exceptionptr);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+#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 */
+
+       if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring))))
+               throw_main_exception_exit();
+
+       if (!link_class(mainclass))
+               throw_main_exception_exit();
+
+       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) {
+               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();
+       }
+               
+       jit_compile(m);
+}
+#endif /* !defined(NDEBUG) */
+
+
 /* vm_vmargs_from_valist *******************************************************
 
    XXX