almost all required function implemented - first integration with jdwp - nothing...
[cacao.git] / src / cacao / cacao.c
index c953477ac5d80e51dce2b5da93cc4f39ce4c3d84..a3e4d37a486c071cf232be17de8728a402ceb52b 100644 (file)
@@ -1,10 +1,9 @@
-/* main.c - contains main() and variables for the global options
+/* src/cacao/cacao.c - contains main() of cacao
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   Institut f. Computersprachen, TU Wien
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
-   S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
-   J. Wenninger
+   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+   Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
@@ -30,6 +29,7 @@
    Changes: Andi Krall
             Mark Probst
             Philipp Tomsich
+            Christian Thalinger
 
    This module does the following tasks:
      - Command line option handling
      - Calling the class loader
      - Running the main method
 
-   $Id: cacao.c 991 2004-03-29 11:22:34Z stefan $
+   $Id: cacao.c 3570 2005-11-04 16:58:36Z motse $
 
 */
 
 
+#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
-#include "main.h"
-#include "global.h"
-#include "tables.h"
-#include "loader.h"
-#include "jit.h"
-#include "asmpart.h"
-#include "builtin.h"
-#include "native.h"
-#include "mm/boehm.h"
-#include "threads/thread.h"
-#include "toolbox/loging.h"
-#include "toolbox/memory.h"
-#include "parseRTstats.h"
-#include "nat/java_lang_Throwable.h"
 
-#ifdef TYPEINFO_DEBUG_TEST
-#include "typeinfo.h"
+#include "config.h"
+#include "cacao/cacao.h"
+#include "mm/boehm.h"
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/jvmti.h"
+#include "native/jvmti/dbg.h"
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/wait.h>
 #endif
 
-/* command line option */
-
-bool verbose =  false;
-bool compileall = false;
-bool runverbose = false;       /* trace all method invocation                */
-bool verboseexception = false;       /* trace all method invocation                */
-bool collectverbose = false;
+#include "toolbox/logging.h"
+#include "vm/exceptions.h"
+#include "vm/finalizer.h"
+#include "vm/global.h"
+#include "vm/initialize.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/signallocal.h"
+#include "vm/statistics.h"
+#include "vm/stringlocal.h"
+#include "vm/tables.h"
+#include "vm/classcache.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
 
-bool loadverbose = false;
-bool linkverbose = false;
-bool initverbose = false;
+#ifdef TYPEINFO_DEBUG_TEST
+#include "vm/jit/verify/typeinfo.h"
+#endif
 
-bool opt_rt = false;           /* true if RTA parse should be used     RT-CO */
-bool opt_xta = false;          /* true if XTA parse should be used    XTA-CO */
-bool opt_vta = false;          /* true if VTA parse should be used    VTA-CO */
 
-bool opt_liberalutf = false;   /* Don't check overlong UTF-8 sequences       */
+/* define heap sizes **********************************************************/
 
-bool showmethods = false;
-bool showconstantpool = false;
-bool showutf = false;
+#define HEAP_MAXSIZE      64 * 1024 * 1024; /* default 64MB                   */
+#define HEAP_STARTSIZE    2 * 1024 * 1024;  /* default 2MB                    */
+#define STACK_SIZE        128 * 1024;       /* default 128kB                  */
 
-bool compileverbose =  false;  /* trace compiler actions                     */
-bool showstack = false;
-bool showdisassemble = false;  /* generate disassembler listing              */
-bool showddatasegment = false; /* generate data segment listing              */
-bool showintermediate = false; /* generate intermediate code listing         */
+#if defined(ENABLE_INTRP)
+u1 *intrp_main_stack;
+#endif
 
-bool useinlining = false;      /* use method inlining                        */
-bool inlinevirtuals = false;   /* inline unique virtual methods              */
-bool inlineexceptions = false; /* inline methods, that contain excptions     */
-bool inlineparamopt = false;   /* optimize parameter passing to inlined methods */
-bool inlineoutsiders = false;  /* inline methods, that are not member of the invoker's class */
 
-bool checkbounds = true;       /* check array bounds                         */
-bool checknull = true;         /* check null pointers                        */
-bool opt_noieee = false;       /* don't implement ieee compliant floats      */
-bool checksync = true;         /* do synchronization                         */
-bool opt_loops = false;        /* optimize array accesses in loops           */
+/* CACAO related stuff ********************************************************/
 
-bool makeinitializations = true;
+bool cacao_initializing;
+bool cacao_exiting;
 
-bool getloadingtime = false;   /* to measure the runtime                     */
-s8 loadingtime = 0;
 
-bool getcompilingtime = false; /* compute compile time                       */
-s8 compilingtime = 0;          /* accumulated compile time                   */
+/* Invocation API variables ***************************************************/
 
-int has_ext_instr_set = 0;     /* has instruction set extensions */
+JavaVM *jvm;                        /* denotes a Java VM                      */
+JNIEnv *env;                        /* pointer to native method interface     */
+JDK1_1InitArgs vm_args;             /* JDK 1.1 VM initialization arguments    */
 
-bool statistics = false;
 
-bool opt_verify = true;        /* true if classfiles should be verified      */
+char *bootclasspath;                    /* contains the boot classpath        */
+char *classpath;                        /* contains the classpath             */
 
-char mainString[256];
-static classinfo *topclass;
+char *mainstring;
+static classinfo *mainclass;
 
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
 void **stackbottom = 0;
 #endif
 
 
-/* internal function: get_opt *************************************************
-       
-       decodes the next command line option
-       
-******************************************************************************/
-
-#define OPT_DONE       -1
-#define OPT_ERROR       0
-#define OPT_IGNORE      1
-
-#define OPT_CLASSPATH   2
-#define OPT_D           3
-#define OPT_MS          4
-#define OPT_MX          5
-#define OPT_VERBOSE1    6
-#define OPT_VERBOSE     7
-#define OPT_VERBOSEGC   8
-#define OPT_VERBOSECALL 9
-#define OPT_NOIEEE      10
-#define OPT_SOFTNULL    11
-#define OPT_TIME        12
-#define OPT_STAT        13
-#define OPT_LOG         14
-#define OPT_CHECK       15
-#define OPT_LOAD        16
-#define OPT_METHOD      17
-#define OPT_SIGNATURE   18
-#define OPT_SHOW        19
-#define OPT_ALL         20
-#define OPT_OLOOP       24
-#define OPT_INLINING   25
-#define OPT_RT          26
-#define OPT_XTA         27 
-#define OPT_VTA         28
-#define OPT_VERBOSETC   29
-#define OPT_NOVERIFY    30
-#define OPT_LIBERALUTF  31
+/* define command line options ************************************************/
+
+#define OPT_CLASSPATH        2
+#define OPT_D                3
+#define OPT_MS               4
+#define OPT_MX               5
+#define OPT_VERBOSE1         6
+#define OPT_VERBOSE          7
+#define OPT_VERBOSESPECIFIC  8
+#define OPT_VERBOSECALL      9
+#define OPT_NOIEEE           10
+#define OPT_SOFTNULL         11
+#define OPT_TIME             12
+
+#if defined(STATISTICS)
+#define OPT_STAT             13
+#endif /* defined(STATISTICS) */
+
+#define OPT_LOG              14
+#define OPT_CHECK            15
+#define OPT_LOAD             16
+#define OPT_METHOD           17
+#define OPT_SIGNATURE        18
+#define OPT_SHOW             19
+#define OPT_ALL              20
+#define OPT_OLOOP            24
+#define OPT_INLINING        25
+
+#define STATIC_ANALYSIS
+#if defined(STATIC_ANALYSIS)
+# define OPT_RT              26
+# define OPT_XTA             27 
+# define OPT_VTA             28
+#endif /* defined(STATIC_ANALYSIS) */
+
+#define OPT_VERBOSETC        29
+#define OPT_NOVERIFY         30
+#define OPT_LIBERALUTF       31
 #define OPT_VERBOSEEXCEPTION 32
-
-struct {char *name; bool arg; int value;} opts[] = {
-       {"classpath",   true,   OPT_CLASSPATH},
-       {"D",           true,   OPT_D},
-       {"ms",          true,   OPT_MS},
-       {"mx",          true,   OPT_MX},
-       {"noasyncgc",   false,  OPT_IGNORE},
-       {"noverify",    false,  OPT_NOVERIFY},
-       {"liberalutf",  false,  OPT_LIBERALUTF},
-       {"oss",         true,   OPT_IGNORE},
-       {"ss",          true,   OPT_IGNORE},
-       {"v",           false,  OPT_VERBOSE1},
-       {"verbose",     false,  OPT_VERBOSE},
-       {"verbosegc",   false,  OPT_VERBOSEGC},
-       {"verbosecall", false,  OPT_VERBOSECALL},
-       {"verboseexception", false, OPT_VERBOSEEXCEPTION},
+#define OPT_EAGER            33
+
+#if defined(LSRA)
+#define OPT_LSRA             34
+#endif /* defined(LSRA) */
+
+#define OPT_JAR              35
+#define OPT_BOOTCLASSPATH    36
+#define OPT_BOOTCLASSPATH_A  37
+#define OPT_BOOTCLASSPATH_P  38
+#define OPT_VERSION          39
+#define OPT_SHOWVERSION      40
+#define OPT_FULLVERSION      41
+
+#define OPT_HELP             100
+#define OPT_X                101
+
+#define OPT_JIT              102
+#define OPT_INTRP            103
+
+#define OPT_STATIC_SUPERS    104
+#define OPT_TRACE            105
+
+#define OPT_SS               106
+
+#ifdef ENABLE_JVMTI
+#define OPT_DEBUG            107
+#define OPT_AGENTLIB         108
+#define OPT_AGENTPATH        109
+#endif 
+
+opt_struct opts[] = {
+       { "classpath",         true,  OPT_CLASSPATH },
+       { "cp",                true,  OPT_CLASSPATH },
+       { "D",                 true,  OPT_D },
+       { "noasyncgc",         false, OPT_IGNORE },
+       { "noverify",          false, OPT_NOVERIFY },
+       { "liberalutf",        false, OPT_LIBERALUTF },
+       { "v",                 false, OPT_VERBOSE1 },
+       { "verbose",           false, OPT_VERBOSE },
+       { "verbose:",          true,  OPT_VERBOSESPECIFIC },
+       { "verbosecall",       false, OPT_VERBOSECALL },
+       { "verboseexception",  false, OPT_VERBOSEEXCEPTION },
 #ifdef TYPECHECK_VERBOSE
-       {"verbosetc",   false,  OPT_VERBOSETC},
+       { "verbosetc",         false, OPT_VERBOSETC },
 #endif
 #if defined(__ALPHA__)
-       {"noieee",      false,  OPT_NOIEEE},
+       { "noieee",            false, OPT_NOIEEE },
+#endif
+       { "softnull",          false, OPT_SOFTNULL },
+       { "time",              false, OPT_TIME },
+#if defined(STATISTICS)
+       { "stat",              false, OPT_STAT },
+#endif
+       { "log",               true,  OPT_LOG },
+       { "c",                 true,  OPT_CHECK },
+       { "l",                 false, OPT_LOAD },
+       { "eager",             false, OPT_EAGER },
+       { "sig",               true,  OPT_SIGNATURE },
+       { "all",               false, OPT_ALL },
+       { "oloop",             false, OPT_OLOOP },
+#ifdef STATIC_ANALYSIS
+       { "rt",                false, OPT_RT },
+       { "xta",               false, OPT_XTA },
+       { "vta",               false, OPT_VTA },
+#endif
+#ifdef LSRA
+       { "lsra",              false, OPT_LSRA },
 #endif
-       {"softnull",    false,  OPT_SOFTNULL},
-       {"time",        false,  OPT_TIME},
-       {"stat",        false,  OPT_STAT},
-       {"log",         true,   OPT_LOG},
-       {"c",           true,   OPT_CHECK},
-       {"l",           false,  OPT_LOAD},
-       {"m",           true,   OPT_METHOD},
-       {"sig",         true,   OPT_SIGNATURE},
-       {"s",           true,   OPT_SHOW},
-       {"all",         false,  OPT_ALL},
-       {"oloop",       false,  OPT_OLOOP},
-       {"i",               true,   OPT_INLINING},
-       {"rt",          false,  OPT_RT},
-       {"xta",         false,  OPT_XTA},
-       {"vta",         false,  OPT_VTA},
-       {NULL,  false, 0}
+       { "jar",               false, OPT_JAR },
+       { "version",           false, OPT_VERSION },
+       { "showversion",       false, OPT_SHOWVERSION },
+       { "fullversion",       false, OPT_FULLVERSION },
+       { "help",              false, OPT_HELP },
+       { "?",                 false, OPT_HELP },
+
+       /* interpreter options */
+
+       { "trace",             false, OPT_TRACE },
+       { "static-supers",     true,  OPT_STATIC_SUPERS },
+
+       /* JVMTI Agent Command Line Options */
+#ifdef ENABLE_JVMTI
+       { "agentlib:",         true,  OPT_AGENTLIB },
+       { "agentpath:",        true,  OPT_AGENTPATH },
+#endif
+
+       /* X options */
+
+       { "X",                 false, OPT_X },
+       { "Xjit",              false, OPT_JIT },
+       { "Xint",              false, OPT_INTRP },
+       { "Xbootclasspath:",   true,  OPT_BOOTCLASSPATH },
+       { "Xbootclasspath/a:", true,  OPT_BOOTCLASSPATH_A },
+       { "Xbootclasspath/p:", true,  OPT_BOOTCLASSPATH_P },
+#ifdef ENABLE_JVMTI
+       { "Xdebug",            false, OPT_DEBUG },
+#endif 
+       { "Xms",               true,  OPT_MS },
+       { "Xmx",               true,  OPT_MX },
+       { "Xss",               true,  OPT_SS },
+       { "ms",                true,  OPT_MS },
+       { "mx",                true,  OPT_MX },
+       { "ss",                true,  OPT_SS },
+
+       /* keep these at the end of the list */
+
+       { "i",                 true,  OPT_INLINING },
+       { "m",                 true,  OPT_METHOD },
+       { "s",                 true,  OPT_SHOW },
+
+       { NULL,                false, 0 }
 };
 
-static int opt_ind = 1;
-static char *opt_arg;
 
+/* usage ***********************************************************************
 
-static int get_opt(int argc, char **argv)
-{
-       char *a;
-       int i;
-       
-       if (opt_ind >= argc) return OPT_DONE;
-       
-       a = argv[opt_ind];
-       if (a[0] != '-') return OPT_DONE;
-
-       for (i = 0; opts[i].name; i++) {
-               if (!opts[i].arg) {
-                       if (strcmp(a + 1, opts[i].name) == 0) { /* boolean option found */
-                               opt_ind++;
-                               return opts[i].value;
-                       }
-
-               } else {
-                       if (strcmp(a + 1, opts[i].name) == 0) { /* parameter option found */
-                               opt_ind++;
-                               if (opt_ind < argc) {
-                                       opt_arg = argv[opt_ind];
-                                       opt_ind++;
-                                       return opts[i].value;
-                               }
-                               return OPT_ERROR;
-
-                       } else {
-                               size_t l = strlen(opts[i].name);
-                               if (strlen(a + 1) > l) {
-                                       if (memcmp(a + 1, opts[i].name, l) == 0) {
-                                               opt_ind++;
-                                               opt_arg = a + 1 + l;
-                                               return opts[i].value;
-                                       }
-                               }
-                       }
-               }
-       } /* end for */ 
-
-       return OPT_ERROR;
-}
+   Prints the correct usage syntax to stdout.
 
+*******************************************************************************/
 
+static void usage(void)
+{
+       printf("Usage: cacao [-options] classname [arguments]\n");
+       printf("               (to run a class file)\n");
+       printf("       cacao [-options] -jar jarfile [arguments]\n");
+       printf("               (to run a standalone jar file)\n\n");
+
+       printf("Java options:\n");
+       printf("    -cp <path>               specify a path to look for classes\n");
+       printf("    -classpath <path>        specify a path to look for classes\n");
+       printf("    -D<name>=<value>         add an entry to the property list\n");
+       printf("    -verbose[:class|gc|jni]  enable specific verbose output\n");
+       printf("    -version                 print product version and exit\n");
+       printf("    -fullversion             print jpackage-compatible product version and exit\n");
+       printf("    -showversion             print product version and continue\n");
+       printf("    -help, -?                print this help message\n");
+       printf("    -X                       print help on non-standard Java options\n\n");
+
+#ifdef ENABLE_JVMTI
+       printf("    -agentlib:<agent-lib-name>=<options>  library to load containg JVMTI agent\n");
+       printf("    -agentpath:<path-to-agent>=<options>  path to library containg JVMTI agent\n");
+#endif
 
+       printf("CACAO options:\n");
+       printf("    -v                       write state-information\n");
+       printf("    -verbose                 write more information\n");
+       printf("    -verbosegc               write message for each GC\n");
+       printf("    -verbosecall             write message for each call\n");
+       printf("    -verboseexception        write message for each step of stack unwinding\n");
+#ifdef TYPECHECK_VERBOSE
+       printf("    -verbosetc               write debug messages while typechecking\n");
+#endif
+#if defined(__ALPHA__)
+       printf("    -noieee                  don't use ieee compliant arithmetic\n");
+#endif
+       printf("    -noverify                don't verify classfiles\n");
+       printf("    -liberalutf              don't warn about overlong UTF-8 sequences\n");
+       printf("    -softnull                use software nullpointer check\n");
+       printf("    -time                    measure the runtime\n");
+#if defined(STATISTICS)
+       printf("    -stat                    detailed compiler statistics\n");
+#endif
+       printf("    -log logfile             specify a name for the logfile\n");
+       printf("    -c(heck)b(ounds)         don't check array bounds\n");
+       printf("            s(ync)           don't check for synchronization\n");
+       printf("    -oloop                   optimize array accesses in loops\n"); 
+       printf("    -l                       don't start the class after loading\n");
+       printf("    -eager                   perform eager class loading and linking\n");
+       printf("    -all                     compile all methods, no execution\n");
+       printf("    -m                       compile only a specific method\n");
+       printf("    -sig                     specify signature for a specific method\n");
+       printf("    -s(how)a(ssembler)       show disassembled listing\n");
+       printf("           c(onstants)       show the constant pool\n");
+       printf("           d(atasegment)     show data segment listing\n");
+       printf("           e(xceptionstubs)  show disassembled exception stubs (only with -sa)\n");
+       printf("           i(ntermediate)    show intermediate representation\n");
+       printf("           m(ethods)         show class fields and methods\n");
+       printf("           n(ative)          show disassembled native stubs\n");
+       printf("           u(tf)             show the utf - hash\n");
+       printf("    -i     n(line)           activate inlining\n");
+       printf("           v(irtual)         inline virtual methods (uses/turns rt option on)\n");
+       printf("           e(exception)      inline methods with exceptions\n");
+       printf("           p(aramopt)        optimize argument renaming\n");
+       printf("           o(utsiders)       inline methods of foreign classes\n");
+#ifdef STATIC_ANALYSIS
+       printf("    -rt                      use rapid type analysis\n");
+       printf("    -xta                     use x type analysis\n");
+       printf("    -vta                     use variable type analysis\n");
+#endif
+#ifdef LSRA
+       printf("    -lsra                    use linear scan register allocation\n");
+#endif
 
-/******************** interne Function: print_usage ************************
+       /* exit with error code */
 
-Prints the correct usage syntax to stdout.
+       exit(1);
+}   
 
-***************************************************************************/
 
-static void print_usage()
+static void Xusage(void)
 {
-       printf("USAGE: cacao [options] classname [program arguments]\n");
-       printf("Options:\n");
-       printf("          -classpath path ...... specify a path to look for classes\n");
-       printf("          -Dpropertyname=value . add an entry to the property list\n");
-       printf("          -mx maxmem[k|m] ...... specify the size for the heap\n");
-       printf("          -ms initmem[k|m] ..... specify the initial size for the heap\n");
-       printf("          -v ................... write state-information\n");
-       printf("          -verbose ............. write more information\n");
-       printf("          -verbosegc ........... write message for each GC\n");
-       printf("          -verbosecall ......... write message for each call\n");
-       printf("          -verboseexception .... write message for each step of stack unwinding\n");
-#ifdef TYPECHECK_VERBOSE
-       printf("          -verbosetc ........... write debug messages while typechecking\n");
+#if defined(ENABLE_JIT)
+       printf("    -Xjit             JIT mode execution (default)\n");
 #endif
-#if defined(__ALPHA__)
-       printf("          -noieee .............. don't use ieee compliant arithmetic\n");
+#if defined(ENABLE_INTRP)
+       printf("    -Xint             interpreter mode execution\n");
 #endif
-       printf("          -noverify ............ don't verify classfiles\n");
-       printf("          -liberalutf........... don't warn about overlong UTF-8 sequences\n");
-       printf("          -softnull ............ use software nullpointer check\n");
-       printf("          -time ................ measure the runtime\n");
-       printf("          -stat ................ detailed compiler statistics\n");
-       printf("          -log logfile ......... specify a name for the logfile\n");
-       printf("          -c(heck)b(ounds) ..... don't check array bounds\n");
-       printf("                  s(ync) ....... don't check for synchronization\n");
-       printf("          -oloop ............... optimize array accesses in loops\n"); 
-       printf("          -l ................... don't start the class after loading\n");
-       printf("          -all ................. compile all methods, no execution\n");
-       printf("          -m ................... compile only a specific method\n");
-       printf("          -sig ................. specify signature for a specific method\n");
-       printf("          -s(how)a(ssembler) ... show disassembled listing\n");
-       printf("                 c(onstants) ... show the constant pool\n");
-       printf("                 d(atasegment).. show data segment listing\n");
-       printf("                 i(ntermediate). show intermediate representation\n");
-       printf("                 m(ethods)...... show class fields and methods\n");
-       printf("                 u(tf) ......... show the utf - hash\n");
-       printf("          -i     n ............. activate inlining\n");
-       printf("                 v ............. inline virtual methods\n");
-       printf("                 e ............. inline methods with exceptions\n");
-       printf("                 p ............. optimize argument renaming\n");
-       printf("                 o ............. inline methods of foreign classes\n");
-       printf("          -rt .................. use rapid type analysis\n");
-       printf("          -xta ................. use x type analysis\n");
-       printf("          -vta ................. use variable type analysis\n");
+       printf("    -Xbootclasspath:<zip/jar files and directories separated by :>\n");
+    printf("                      value is set as bootstrap class path\n");
+       printf("    -Xbootclasspath/a:<zip/jar files and directories separated by :>\n");
+       printf("                      value is appended to the bootstrap class path\n");
+       printf("    -Xbootclasspath/p:<zip/jar files and directories separated by :>\n");
+       printf("                      value is prepended to the bootstrap class path\n");
+       printf("    -Xms<size>        set the initial size of the heap (default: 2MB)\n");
+       printf("    -Xmx<size>        set the maximum size of the heap (default: 64MB)\n");
+       printf("    -Xss<size>        set the thread stack size (default: 128kB)\n");
+#if defined(ENABLE_JVMTI)
+       printf("    -Xdebug<transport> enable remote debugging\n");
+#endif 
+
+       /* exit with error code */
+
+       exit(1);
 }   
 
 
+/* version *********************************************************************
 
-/***************************** Function: print_times *********************
+   Only prints cacao version information.
 
-       Prints a summary of CPU time usage.
+*******************************************************************************/
 
-**************************************************************************/
-
-static void print_times()
+static void version(void)
 {
-       s8 totaltime = getcputime();
-       s8 runtime = totaltime - loadingtime - compilingtime;
-       char logtext[MAXLOGTEXT];
+       printf("java version \""JAVA_VERSION"\"\n");
+       printf("CACAO version "VERSION"\n");
+
+       printf("Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,\n");
+       printf("R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,\n");
+       printf("C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,\n");
+       printf("Institut f. Computersprachen - TU Wien\n\n");
+
+       printf("This program is free software; you can redistribute it and/or\n");
+       printf("modify it under the terms of the GNU General Public License as\n");
+       printf("published by the Free Software Foundation; either version 2, or (at\n");
+       printf("your option) any later version.\n\n");
+
+       printf("This program is distributed in the hope that it will be useful, but\n");
+       printf("WITHOUT ANY WARRANTY; without even the implied warranty of\n");
+       printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n");
+       printf("General Public License for more details.\n");
+}
 
-#if defined(__I386__) || defined(__POWERPC__)
-       sprintf(logtext, "Time for loading classes: %lld secs, %lld millis",
-#else
-       sprintf(logtext, "Time for loading classes: %ld secs, %ld millis",
-#endif
-                       loadingtime / 1000000, (loadingtime % 1000000) / 1000);
-       log_text(logtext);
 
-#if defined(__I386__) || defined(__POWERPC__) 
-       sprintf(logtext, "Time for compiling code:  %lld secs, %lld millis",
-#else
-       sprintf(logtext, "Time for compiling code:  %ld secs, %ld millis",
-#endif
-                       compilingtime / 1000000, (compilingtime % 1000000) / 1000);
-       log_text(logtext);
+/* fullversion *****************************************************************
 
-#if defined(__I386__) || defined(__POWERPC__) 
-       sprintf(logtext, "Time for running program: %lld secs, %lld millis",
-#else
-       sprintf(logtext, "Time for running program: %ld secs, %ld millis",
-#endif
-                       runtime / 1000000, (runtime % 1000000) / 1000);
-       log_text(logtext);
+   Prints a Sun compatible version information (required e.g. by
+   jpackage, www.jpackage.org).
 
-#if defined(__I386__) || defined(__POWERPC__) 
-       sprintf(logtext, "Total time: %lld secs, %lld millis",
-#else
-       sprintf(logtext, "Total time: %ld secs, %ld millis",
-#endif
-                       totaltime / 1000000, (totaltime % 1000000) / 1000);
-       log_text(logtext);
+*******************************************************************************/
+
+static void fullversion(void)
+{
+       printf("java full version \"cacao-"JAVA_VERSION"\"\n");
+
+       /* exit normally */
+
+       exit(0);
 }
 
 
+#ifdef TYPECHECK_STATISTICS
+void typecheck_print_statistics(FILE *file);
+#endif
 
+/* setup_debugger_process *****************************************************
 
+   Helper function to start JDWP threads
 
+*******************************************************************************/
+#if defined(ENABLE_JVMTI)
 
-/***************************** Function: print_stats *********************
+static void setup_debugger_process(char* transport) {
+       java_objectheader *o;
+       methodinfo *m;
+       java_lang_String  *s;
 
-       outputs detailed compiler statistics
+       /* new gnu.classpath.jdwp.Jdwp() */
+       mainclass = 
+               load_class_from_sysloader(utf_new_char("gnu.classpath.jdwp.Jdwp"));
+       if (!mainclass)
+               throw_main_exception_exit();
 
-**************************************************************************/
+       o = builtin_new(mainclass);
 
-static void print_stats()
-{
-       char logtext[MAXLOGTEXT];
-
-       sprintf(logtext, "Number of JitCompiler Calls: %d", count_jit_calls);
-       log_text(logtext);
-       sprintf(logtext, "Number of compiled Methods: %d", count_methods);
-       log_text(logtext);
-       sprintf(logtext, "Number of max basic blocks per method: %d", count_max_basic_blocks);
-       log_text(logtext);
-       sprintf(logtext, "Number of compiled basic blocks: %d", count_basic_blocks);
-       log_text(logtext);
-       sprintf(logtext, "Number of max JavaVM-Instructions per method: %d", count_max_javainstr);
-       log_text(logtext);
-       sprintf(logtext, "Number of compiled JavaVM-Instructions: %d", count_javainstr);
-       log_text(logtext);
-       sprintf(logtext, "Size of compiled JavaVM-Instructions:   %d(%d)", count_javacodesize,
-                       count_javacodesize - count_methods * 18);
-       log_text(logtext);
-       sprintf(logtext, "Size of compiled Exception Tables:      %d", count_javaexcsize);
-       log_text(logtext);
-       sprintf(logtext, "Value of extended instruction set var:  %d", has_ext_instr_set);
-       log_text(logtext);
-       sprintf(logtext, "Number of Machine-Instructions: %d", count_code_len >> 2);
-       log_text(logtext);
-       sprintf(logtext, "Number of Spills: %d", count_spills);
-       log_text(logtext);
-       sprintf(logtext, "Number of Activ    Pseudocommands: %5d", count_pcmd_activ);
-       log_text(logtext);
-       sprintf(logtext, "Number of Drop     Pseudocommands: %5d", count_pcmd_drop);
-       log_text(logtext);
-       sprintf(logtext, "Number of Const    Pseudocommands: %5d (zero:%5d)", count_pcmd_load, count_pcmd_zero);
-       log_text(logtext);
-       sprintf(logtext, "Number of ConstAlu Pseudocommands: %5d (cmp: %5d, store:%5d)", count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
-       log_text(logtext);
-       sprintf(logtext, "Number of Move     Pseudocommands: %5d", count_pcmd_move);
-       log_text(logtext);
-       sprintf(logtext, "Number of Load     Pseudocommands: %5d", count_load_instruction);
-       log_text(logtext);
-       sprintf(logtext, "Number of Store    Pseudocommands: %5d (combined: %5d)", count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
-       log_text(logtext);
-       sprintf(logtext, "Number of OP       Pseudocommands: %5d", count_pcmd_op);
-       log_text(logtext);
-       sprintf(logtext, "Number of DUP      Pseudocommands: %5d", count_dup_instruction);
-       log_text(logtext);
-       sprintf(logtext, "Number of Mem      Pseudocommands: %5d", count_pcmd_mem);
-       log_text(logtext);
-       sprintf(logtext, "Number of Method   Pseudocommands: %5d", count_pcmd_met);
-       log_text(logtext);
-       sprintf(logtext, "Number of Branch   Pseudocommands: %5d (rets:%5d, Xrets: %5d)",
-                       count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
-       log_text(logtext);
-       sprintf(logtext, "Number of Table    Pseudocommands: %5d", count_pcmd_table);
-       log_text(logtext);
-       sprintf(logtext, "Number of Useful   Pseudocommands: %5d", count_pcmd_table +
-                       count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
-       log_text(logtext);
-       sprintf(logtext, "Number of Null Pointer Checks:     %5d", count_check_null);
-       log_text(logtext);
-       sprintf(logtext, "Number of Array Bound Checks:      %5d", count_check_bound);
-       log_text(logtext);
-       sprintf(logtext, "Number of Try-Blocks: %d", count_tryblocks);
-       log_text(logtext);
-       sprintf(logtext, "Maximal count of stack elements:   %d", count_max_new_stack);
-       log_text(logtext);
-       sprintf(logtext, "Upper bound of max stack elements: %d", count_upper_bound_new_stack);
-       log_text(logtext);
-       sprintf(logtext, "Distribution of stack sizes at block boundary");
-       log_text(logtext);
-       sprintf(logtext, "    0    1    2    3    4    5    6    7    8    9    >=10");
-       log_text(logtext);
-       sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_block_stack[0],
-                       count_block_stack[1], count_block_stack[2], count_block_stack[3], count_block_stack[4],
-                       count_block_stack[5], count_block_stack[6], count_block_stack[7], count_block_stack[8],
-                       count_block_stack[9], count_block_stack[10]);
-       log_text(logtext);
-       sprintf(logtext, "Distribution of store stack depth");
-       log_text(logtext);
-       sprintf(logtext, "    0    1    2    3    4    5    6    7    8    9    >=10");
-       log_text(logtext);
-       sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_depth[0],
-                       count_store_depth[1], count_store_depth[2], count_store_depth[3], count_store_depth[4],
-                       count_store_depth[5], count_store_depth[6], count_store_depth[7], count_store_depth[8],
-                       count_store_depth[9], count_store_depth[10]);
-       log_text(logtext);
-       sprintf(logtext, "Distribution of store creator chains first part");
-       log_text(logtext);
-       sprintf(logtext, "    0    1    2    3    4    5    6    7    8    9  ");
-       log_text(logtext);
-       sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[0],
-                       count_store_length[1], count_store_length[2], count_store_length[3], count_store_length[4],
-                       count_store_length[5], count_store_length[6], count_store_length[7], count_store_length[8],
-                       count_store_length[9]);
-       log_text(logtext);
-       sprintf(logtext, "Distribution of store creator chains second part");
-       log_text(logtext);
-       sprintf(logtext, "   10   11   12   13   14   15   16   17   18   19  >=20");
-       log_text(logtext);
-       sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[10],
-                       count_store_length[11], count_store_length[12], count_store_length[13], count_store_length[14],
-                       count_store_length[15], count_store_length[16], count_store_length[17], count_store_length[18],
-                       count_store_length[19], count_store_length[20]);
-       log_text(logtext);
-       sprintf(logtext, "Distribution of analysis iterations");
-       log_text(logtext);
-       sprintf(logtext, "    1    2    3    4    >=5");
-       log_text(logtext);
-       sprintf(logtext, "%5d%5d%5d%5d%5d", count_analyse_iterations[0], count_analyse_iterations[1],
-                       count_analyse_iterations[2], count_analyse_iterations[3], count_analyse_iterations[4]);
-       log_text(logtext);
-       sprintf(logtext, "Distribution of basic blocks per method");
-       log_text(logtext);
-       sprintf(logtext, " <= 5 <=10 <=15 <=20 <=30 <=40 <=50 <=75  >75");
-       log_text(logtext);
-       sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_method_bb_distribution[0],
-                       count_method_bb_distribution[1], count_method_bb_distribution[2], count_method_bb_distribution[3],
-                       count_method_bb_distribution[4], count_method_bb_distribution[5], count_method_bb_distribution[6],
-                       count_method_bb_distribution[7], count_method_bb_distribution[8]);
-       log_text(logtext);
-       sprintf(logtext, "Distribution of basic block sizes");
-       log_text(logtext);
-       sprintf(logtext,
-                        "  0    1    2    3    4   5   6   7   8   9 <13 <15 <17 <19 <21 <26 <31 >30");
-       log_text(logtext);
-       sprintf(logtext, "%3d%5d%5d%5d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d",
-                       count_block_size_distribution[0], count_block_size_distribution[1], count_block_size_distribution[2],
-                       count_block_size_distribution[3], count_block_size_distribution[4], count_block_size_distribution[5],
-                       count_block_size_distribution[6], count_block_size_distribution[7], count_block_size_distribution[8],
-                       count_block_size_distribution[9], count_block_size_distribution[10], count_block_size_distribution[11],
-                       count_block_size_distribution[12], count_block_size_distribution[13], count_block_size_distribution[14],
-                       count_block_size_distribution[15], count_block_size_distribution[16], count_block_size_distribution[17]);
-       log_text(logtext);
-       sprintf(logtext, "Size of Code Area (Kb):  %10.3f", (float) count_code_len / 1024);
-       log_text(logtext);
-       sprintf(logtext, "Size of data Area (Kb):  %10.3f", (float) count_data_len / 1024);
-       log_text(logtext);
-       sprintf(logtext, "Size of Class Infos (Kb):%10.3f", (float) (count_class_infos) / 1024);
-       log_text(logtext);
-       sprintf(logtext, "Size of Const Pool (Kb): %10.3f", (float) (count_const_pool_len + count_utf_len) / 1024);
-       log_text(logtext);
-       sprintf(logtext, "Size of Vftbl (Kb):      %10.3f", (float) count_vftbl_len / 1024);
-       log_text(logtext);
-       sprintf(logtext, "Size of comp stub (Kb):  %10.3f", (float) count_cstub_len / 1024);
-       log_text(logtext);
-       sprintf(logtext, "Size of native stub (Kb):%10.3f", (float) count_nstub_len / 1024);
-       log_text(logtext);
-       sprintf(logtext, "Size of Utf (Kb):        %10.3f", (float) count_utf_len / 1024);
-       log_text(logtext);
-       sprintf(logtext, "Size of VMCode (Kb):     %10.3f(%d)", (float) count_vmcode_len / 1024,
-                       count_vmcode_len - 18 * count_all_methods);
-       log_text(logtext);
-       sprintf(logtext, "Size of ExTable (Kb):    %10.3f", (float) count_extable_len / 1024);
-       log_text(logtext);
-       sprintf(logtext, "Number of class loads:   %d", count_class_loads);
-       log_text(logtext);
-       sprintf(logtext, "Number of class inits:   %d", count_class_inits);
-       log_text(logtext);
-       sprintf(logtext, "Number of loaded Methods: %d\n\n", count_all_methods);
-       log_text(logtext);
-
-       sprintf(logtext, "Calls of utf_new: %22d", count_utf_new);
-       log_text(logtext);
-       sprintf(logtext, "Calls of utf_new (element found): %6d\n\n", count_utf_new_found);
-       log_text(logtext);
+       if (!o)
+               throw_main_exception_exit();
+       
+       m = class_resolveclassmethod(mainclass,
+                                                                utf_init, 
+                                                                utf_java_lang_String__void,
+                                                                class_java_lang_Object,
+                                                                true);
+       if (!m)
+               throw_main_exception_exit();
+
+       asm_calljavafunction(m, o, NULL, NULL, NULL);
+
+       /* configure(transport,NULL) */
+       m = class_resolveclassmethod(
+               mainclass, utf_new_char("configure"), 
+               utf_new_char("(Ljava/lang/String;Ljava/lang/Thread;)V"),
+               class_java_lang_Object,
+               false);
+
+
+       s = javastring_new_char(transport);
+       asm_calljavafunction(m, o, s, NULL, NULL);
+       if (!m)
+               throw_main_exception_exit();
+
+       /* _doInitialization */
+       m = class_resolveclassmethod(mainclass,
+                                                                utf_new_char("_doInitialization"), 
+                                                                utf_new_char("()V"),
+                                                                mainclass,
+                                                                false);
+       
+       if (!m)
+               throw_main_exception_exit();
+
+       asm_calljavafunction(m, o, NULL, NULL, NULL);
 }
+#endif
+
 
+/* getmainclassfromjar *********************************************************
 
-/********** Function: class_compile_methods   (debugging only) ********/
+   Gets the name of the main class form a JAR's manifest file.
 
-void class_compile_methods()
+*******************************************************************************/
+
+static char *getmainclassnamefromjar(char *mainstring)
 {
-       int        i;
-       classinfo  *c;
-       methodinfo *m;
+       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)
+               throw_main_exception_exit();
        
-       c = list_first(&linkedclasses);
-       while (c) {
-               for (i = 0; i < c -> methodscount; i++) {
-                       m = &(c->methods[i]);
-                       if (m->jcode) {
-                               (void) jit_compile(m);
-                       }
-               }
-               c = list_next(&linkedclasses, c);
-       }
-}
+       /* create JarFile object */
 
-#ifdef TYPECHECK_STATISTICS
-void typecheck_print_statistics(FILE *file);
-#endif
+       o = builtin_new(c);
 
-/*
- * void exit_handler(void)
- * -----------------------
- * The exit_handler function is called upon program termination to shutdown
- * the various subsystems and release the resources allocated to the VM.
- */
-void exit_handler(void)
-{
-       /********************* Print debug tables ************************/
-                               
-       if (showmethods) class_showmethods(topclass);
-       if (showconstantpool) class_showconstantpool(topclass);
-       if (showutf) utf_show();
+       if (!o)
+               throw_main_exception_exit();
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       clear_thread_flags();           /* restores standard file descriptor
-                                      flags */
-#endif
 
-       /************************ Free all resources *******************/
+       m = class_resolveclassmethod(c,
+                                                                utf_init, 
+                                                                utf_java_lang_String__void,
+                                                                class_java_lang_Object,
+                                                                true);
 
-       heap_close();               /* must be called before compiler_close and
-                                      loader_close because finalization occurs
-                                      here */
+       if (!m)
+               throw_main_exception_exit();
 
-       loader_close();
-       tables_close(literalstring_free);
+       s = javastring_new_char(mainstring);
 
-       if (verbose || getcompilingtime || statistics) {
-               log_text("CACAO terminated");
-               if (statistics) {
-                       print_stats();
-#ifdef TYPECHECK_STATISTICS
-                       typecheck_print_statistics(get_logfile());
-#endif
-               }
-               if (getcompilingtime)
-                       print_times();
-               mem_usagelog(1);
+       asm_calljavafunction(m, o, s, NULL, NULL);
+
+       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)
+               throw_main_exception_exit();
+
+       o = asm_calljavafunction(m, o, NULL, NULL, NULL);
+
+       if (!o) {
+               fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring);
+               cacao_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)
+               throw_main_exception_exit();
+
+       o = asm_calljavafunction(m, o, NULL, NULL, NULL);
+
+       if (!o) {
+               fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring);
+               cacao_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)
+               throw_main_exception_exit();
+
+       s = javastring_new_char("Main-Class");
+
+       o = asm_calljavafunction(m, o, s, NULL, NULL);
+
+       if (!o)
+               throw_main_exception_exit();
+
+       return javastring_tochar(o);
 }
 
 
-/************************** Function: main *******************************
+void exit_handler(void);
+
+
+/* main ************************************************************************
 
    The main program.
    
-**************************************************************************/
+*******************************************************************************/
 
 int main(int argc, char **argv)
 {
        s4 i, j;
-       char *cp;
        void *dummy;
        
-       /********** interne (nur fuer main relevante Optionen) **************/
+       /* local variables ********************************************************/
    
        char logfilename[200] = "";
-       u4 heapsize = 64000000;
-       u4 heapstartsize = 200000;
-       char classpath[500] = ".";
+       u4 heapmaxsize;
+       u4 heapstartsize;
+       char *cp;
+       s4    cplen;
        bool startit = true;
        char *specificmethodname = NULL;
        char *specificsignature = NULL;
+       bool jar = false;
+#if defined(ENABLE_JVMTI)
+       bool dbg = false;
+       char *transport;
+       int waitval;
+#endif
+
 
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        stackbottom = &dummy;
 #endif
        
-       if (0 != atexit(exit_handler))
-               panic("unable to register exit_handler");
+       if (atexit(exit_handler))
+               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                  "Unable to register exit_handler");
+
+       /* initialize global variables */
+
+       cacao_exiting = false;
+
 
        /************ Collect info from the environment ************************/
 
+       /* set the bootclasspath */
+
+       cp = getenv("BOOTCLASSPATH");
+       if (cp) {
+               bootclasspath = MNEW(char, strlen(cp) + strlen("0"));
+               strcpy(bootclasspath, cp);
+
+       } else {
+               cplen = strlen(CACAO_INSTALL_PREFIX) + strlen(CACAO_VM_ZIP_PATH) +
+                       strlen(":") +
+                       strlen(CLASSPATH_INSTALL_DIR) +
+                       strlen(CLASSPATH_GLIBJ_ZIP_PATH) +
+                       strlen("0");
+
+               bootclasspath = MNEW(char, cplen);
+               strcpy(bootclasspath, CACAO_INSTALL_PREFIX);
+               strcat(bootclasspath, CACAO_VM_ZIP_PATH);
+               strcat(bootclasspath, ":");
+               strcat(bootclasspath, CLASSPATH_INSTALL_DIR);
+               strcat(bootclasspath, CLASSPATH_GLIBJ_ZIP_PATH);
+       }
+
+
+       /* set the classpath */
+
        cp = getenv("CLASSPATH");
        if (cp) {
-               strcpy(classpath, cp);
+               classpath = MNEW(char, strlen(cp) + strlen("0"));
+               strcat(classpath, cp);
+
+       } else {
+               classpath = MNEW(char, strlen(".") + strlen("0"));
+               strcpy(classpath, ".");
        }
 
+
        /***************** Interpret the command line *****************/
    
        checknull = false;
        opt_noieee = false;
 
-       while ((i = get_opt(argc, argv)) != OPT_DONE) {
+       heapmaxsize = HEAP_MAXSIZE;
+       heapstartsize = HEAP_STARTSIZE;
+       opt_stacksize = STACK_SIZE;
+
+       while ((i = get_opt(argc, argv, opts)) != OPT_DONE) {
                switch (i) {
-               case OPT_IGNORE: break;
+               case OPT_IGNORE:
+                       break;
                        
-               case OPT_CLASSPATH:    
-                       strcpy(classpath + strlen(classpath), ":");
-                       strcpy(classpath + strlen(classpath), opt_arg);
+               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"));
+                       strcpy(bootclasspath, opt_arg);
                        break;
-                               
+
+               case OPT_BOOTCLASSPATH_A:
+                       /* append to end of bootclasspath */
+                       cplen = strlen(bootclasspath);
+
+                       bootclasspath = MREALLOC(bootclasspath,
+                                                                        char,
+                                                                        cplen,
+                                                                        cplen + strlen(":") +
+                                                                        strlen(opt_arg) + strlen("0"));
+
+                       strcat(bootclasspath, ":");
+                       strcat(bootclasspath, opt_arg);
+                       break;
+
+               case OPT_BOOTCLASSPATH_P:
+                       /* prepend in front of bootclasspath */
+                       cp = bootclasspath;
+                       cplen = strlen(cp);
+
+                       bootclasspath = MNEW(char, strlen(opt_arg) + strlen(":") +
+                                                                cplen + strlen("0"));
+
+                       strcpy(bootclasspath, opt_arg);
+                       strcat(bootclasspath, ":");
+                       strcat(bootclasspath, cp);
+
+                       MFREE(cp, char, cplen);
+                       break;
+
+               case OPT_CLASSPATH:
+                       /* forget old classpath and set the argument as new classpath */
+                       MFREE(classpath, char, strlen(classpath));
+
+                       classpath = MNEW(char, strlen(opt_arg) + strlen("0"));
+                       strcpy(classpath, opt_arg);
+                       break;
+
+               case OPT_JAR:
+                       jar = true;
+                       break;
+
+#if defined(ENABLE_JVMTI)
+               case OPT_DEBUG:
+                       dbg = true;
+                       transport = opt_arg;
+                       break;
+
+               case OPT_AGENTPATH:
+               case OPT_AGENTLIB:
+                       set_jvmti_phase(JVMTI_PHASE_ONLOAD);
+                       agentload(opt_arg);
+                       set_jvmti_phase(JVMTI_PHASE_PRIMORDIAL);
+                       break;
+#endif
+                       
                case OPT_D:
                        {
-                               int n;
-                               int l = strlen(opt_arg);
-                               for (n = 0; n < l; n++) {
-                                       if (opt_arg[n] == '=') {
-                                               opt_arg[n] = '\0';
-                                               attach_property(opt_arg, opt_arg + n + 1);
+                               for (j = 0; j < strlen(opt_arg); j++) {
+                                       if (opt_arg[j] == '=') {
+                                               opt_arg[j] = '\0';
+                                               create_property(opt_arg, opt_arg + j + 1);
                                                goto didit;
                                        }
                                }
-                               print_usage();
-                               exit(10);
+
+                               /* if no '=' is given, just create an empty property */
+                               create_property(opt_arg, "");
                                        
                        didit: ;
                        }       
                        break;
-                               
-               case OPT_MS:
+
                case OPT_MX:
-                       if (opt_arg[strlen(opt_arg) - 1] == 'k') {
-                               j = 1024 * atoi(opt_arg);
-                       }
-                       else if (opt_arg[strlen(opt_arg) - 1] == 'm') {
-                               j = 1024 * 1024 * atoi(opt_arg);
+               case OPT_MS:
+               case OPT_SS:
+                       {
+                               char c;
+                               c = opt_arg[strlen(opt_arg) - 1];
+
+                               if (c == 'k' || c == 'K') {
+                                       j = 1024 * atoi(opt_arg);
+
+                               } else if (c == 'm' || c == 'M') {
+                                       j = 1024 * 1024 * atoi(opt_arg);
+
+                               } else
+                                       j = atoi(opt_arg);
+
+                               if (i == OPT_MX)
+                                       heapmaxsize = j;
+                               else if (i == OPT_MS)
+                                       heapstartsize = j;
+                               else
+                                       opt_stacksize = j;
                        }
-                       else j = atoi(opt_arg);
-                               
-                       if (i == OPT_MX) heapsize = j;
-                       else heapstartsize = j;
                        break;
 
                case OPT_VERBOSE1:
-                       verbose = true;
+                       opt_verbose = true;
                        break;
-                                                               
+
                case OPT_VERBOSE:
-                       verbose = true;
+                       opt_verbose = true;
                        loadverbose = true;
+                       linkverbose = true;
                        initverbose = true;
                        compileverbose = true;
                        break;
-                               
-               case OPT_VERBOSEEXCEPTION:
-                       verboseexception = true;
+
+               case OPT_VERBOSESPECIFIC:
+                       if (strcmp("class", opt_arg) == 0)
+                               opt_verboseclass = true;
+
+                       else if (strcmp("gc", opt_arg) == 0)
+                               opt_verbosegc = true;
+
+                       else if (strcmp("jni", opt_arg) == 0)
+                               opt_verbosejni = true;
                        break;
 
-               case OPT_VERBOSEGC:
-                       collectverbose = true;
+               case OPT_VERBOSEEXCEPTION:
+                       opt_verboseexception = true;
                        break;
 
 #ifdef TYPECHECK_VERBOSE
@@ -709,7 +834,20 @@ int main(int argc, char **argv)
                case OPT_VERBOSECALL:
                        runverbose = true;
                        break;
-                               
+
+               case OPT_VERSION:
+                       version();
+                       exit(0);
+                       break;
+
+               case OPT_FULLVERSION:
+                       fullversion();
+                       break;
+
+               case OPT_SHOWVERSION:
+                       version();
+                       break;
+
                case OPT_NOIEEE:
                        opt_noieee = true;
                        break;
@@ -731,9 +869,11 @@ int main(int argc, char **argv)
                        getloadingtime = true;
                        break;
                                        
+#if defined(STATISTICS)
                case OPT_STAT:
-                       statistics = true;
+                       opt_stat = true;
                        break;
+#endif
                                        
                case OPT_LOG:
                        strcpy(logfilename, opt_arg);
@@ -749,8 +889,7 @@ int main(int argc, char **argv)
                                        checksync = false;
                                        break;
                                default:
-                                       print_usage();
-                                       exit(10);
+                                       usage();
                                }
                        }
                        break;
@@ -760,18 +899,22 @@ int main(int argc, char **argv)
                        makeinitializations = false;
                        break;
 
+               case OPT_EAGER:
+                       opt_eager = true;
+                       break;
+
                case OPT_METHOD:
                        startit = false;
-                       specificmethodname = opt_arg;                   
+                       specificmethodname = opt_arg;
                        makeinitializations = false;
                        break;
                        
                case OPT_SIGNATURE:
-                       specificsignature = opt_arg;                    
+                       specificsignature = opt_arg;
                        break;
                        
                case OPT_ALL:
-                       compileall = true;              
+                       compileall = true;
                        startit = false;
                        makeinitializations = false;
                        break;
@@ -780,28 +923,33 @@ int main(int argc, char **argv)
                        for (j = 0; j < strlen(opt_arg); j++) {         
                                switch (opt_arg[j]) {
                                case 'a':
-                                       showdisassemble = true;
-                                       compileverbose=true;
+                                       opt_showdisassemble = true;
+                                       compileverbose = true;
                                        break;
                                case 'c':
                                        showconstantpool = true;
                                        break;
                                case 'd':
-                                       showddatasegment = true;
+                                       opt_showddatasegment = true;
+                                       break;
+                               case 'e':
+                                       opt_showexceptionstubs = true;
                                        break;
                                case 'i':
-                                       showintermediate = true;
+                                       opt_showintermediate = true;
                                        compileverbose = true;
                                        break;
                                case 'm':
                                        showmethods = true;
                                        break;
+                               case 'n':
+                                       opt_shownativestub = true;
+                                       break;
                                case 'u':
                                        showutf = true;
                                        break;
                                default:
-                                       print_usage();
-                                       exit(10);
+                                       usage();
                                }
                        }
                        break;
@@ -814,10 +962,17 @@ int main(int argc, char **argv)
                        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 */
+#ifdef INAFTERMAIN
+                                       useinliningm = true;
+                                       useinlining = false;
+#else
                                        useinlining = true;
+#endif
                                        break;
                                case 'v':
                                        inlinevirtuals = true;
+                                       opt_rt = true;
                                        break;
                                case 'e':
                                        inlineexceptions = true;
@@ -829,114 +984,292 @@ int main(int argc, char **argv)
                                        inlineoutsiders = true;
                                        break;
                                default:
-                                       print_usage();
-                                       exit(10);
+                                       usage();
                                }
                        }
                        break;
 
+#ifdef STATIC_ANALYSIS
                case OPT_RT:
-                       opt_rt = true;
+                       opt_rt = true; /* default for inlining */
                        break;
 
                case OPT_XTA:
-                       opt_xta = false; /**not yet **/
+                       opt_xta = true; /* in test currently */
                        break;
 
                case OPT_VTA:
+                       printf("\nVTA is not yet available\n");
+                       opt_vta = false;
                        /***opt_vta = true; not yet **/
                        break;
+#endif
+
+#ifdef LSRA
+               case OPT_LSRA:
+                       opt_lsra = true;
+                       break;
+#endif
+
+               case OPT_HELP:
+                       usage();
+                       break;
+
+               case OPT_X:
+                       Xusage();
+                       break;
+
+               case OPT_JIT:
+#if defined(ENABLE_JIT)
+                       opt_jit = true;
+#else
+                       printf("-Xjit option not enabled.\n");
+                       exit(1);
+#endif
+                       break;
+
+               case OPT_INTRP:
+#if defined(ENABLE_INTRP)
+                       opt_intrp = true;
+#else
+                       printf("-Xint option not enabled.\n");
+                       exit(1);
+#endif
+                       break;
+
+               case OPT_STATIC_SUPERS:
+                       opt_static_supers = atoi(opt_arg);
+                       break;
+
+               case OPT_TRACE:
+                       vm_debug = true;
+                       break;
 
                default:
-                       print_usage();
-                       exit(10);
+                       printf("Unknown option: %s\n", argv[opt_ind]);
+                       usage();
                }
        }
-   
-   
-       if (opt_ind >= argc) {
-               print_usage();
-               exit(10);
-       }
 
-       cp = argv[opt_ind++];
-       for (i = strlen(cp) - 1; i >= 0; i--) {     /* Transform dots into slashes */
-               if (cp[i] == '.') cp[i] = '/';          /* in the class name */
-       }
+       if (opt_ind >= argc)
+               usage();
+
+
+       /* transform dots into slashes in the class name */
 
-        strcpy(mainString,cp);
+       mainstring = argv[opt_ind++];
+
+       if (!jar) { 
+        /* do not mangle jar filename */
+
+               for (i = strlen(mainstring) - 1; i >= 0; i--) {
+                       if (mainstring[i] == '.') mainstring[i] = '/';
+               }
 
+       } else {
+               /* put jarfile in classpath */
+
+               cp = classpath;
+
+               classpath = MNEW(char, strlen(mainstring) + strlen(":") +
+                                                strlen(classpath) + strlen("0"));
+
+               strcpy(classpath, mainstring);
+               strcat(classpath, ":");
+               strcat(classpath, cp);
+               
+               MFREE(cp, char, strlen(cp));
+       }
 
        /**************************** Program start *****************************/
+
        log_init(logfilename);
-       if (verbose) {
+
+       if (opt_verbose)
                log_text("CACAO started -------------------------------------------------------");
-       }
 
-       heap_init(heapsize, heapstartsize, &dummy);
+       /* initialize JavaVM */
+
+       vm_args.version = 0x00010001; /* New in 1.1.2: VM version */
+
+       /* Get the default initialization arguments and set the class path */
+
+       JNI_GetDefaultJavaVMInitArgs(&vm_args);
+
+       vm_args.minHeapSize = heapstartsize;
+       vm_args.maxHeapSize = heapmaxsize;
+
+       vm_args.classpath = classpath;
+       /* load and initialize a Java VM, return a JNI interface pointer in env */
+
+       JNI_CreateJavaVM(&jvm, &env, &vm_args);
+
+#if defined(ENABLE_JVMTI)
+       set_jvmti_phase(JVMTI_PHASE_START);
+#endif
+
+       /* initialize the garbage collector */
+
+       gc_init(heapmaxsize, heapstartsize);
+
+#if defined(ENABLE_INTRP)
+       /* allocate main thread stack */
+
+       if (opt_intrp) {
+               intrp_main_stack = (u1 *) alloca(opt_stacksize);
+               MSET(intrp_main_stack, 0, u1, opt_stacksize);
+       }
+#endif
 
-       native_setclasspath(classpath);
-               
        tables_init();
-       suck_init(classpath);
+
+       /* initialize the loader with bootclasspath */
+
+       suck_init(bootclasspath);
+
+       cacao_initializing = true;
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       threads_preinit();
+#endif
+       initLocks();
+#endif
+
+       /* initialize the memory subsystem (must be done _after_
+       threads_preinit) */
+
+       if (!memory_init())
+               throw_main_exception_exit();
+
+       /* initialize the finalizer stuff: lock, linked list (must be done
+          _after_ threads_preinit) */
+
+       if (!finalizer_init())
+               throw_main_exception_exit();
+
+       /* install architecture dependent signal handler used for exceptions */
+
+       signal_init();
+
+       /* initialize the codegen subsystems */
+
+       codegen_init();
+
+       /* initializes jit compiler */
 
        jit_init();
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       initThreadsEarly();
+       /* machine dependent initialization */
+
+       md_init();
+
+       /* initialize some cacao subsystems */
+
+       utf8_init();
+
+       if (!loader_init((u1 *) &dummy))
+               throw_main_exception_exit();
+
+       if (!linker_init())
+               throw_main_exception_exit();
+
+       if (!native_init())
+               throw_main_exception_exit();
+
+       if (!exceptions_init())
+               throw_main_exception_exit();
+
+       if (!builtin_init())
+               throw_main_exception_exit();
+
+#if defined(USE_THREADS)
+       if (!threads_init((u1 *) &dummy))
+               throw_main_exception_exit();
 #endif
 
-       loader_init((u1 *) &dummy);
+       /* 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!!! */
 
-       native_loadclasses();
+       if (!initialize_class(class_java_lang_System))
+               throw_main_exception_exit();
 
-       /* initialize the garbage collector */
-       gc_init();
+       /* JNI init creates a Java object (this means running Java code) */
+
+       if (!jni_init())
+               throw_main_exception_exit();
 
 #if defined(USE_THREADS)
-       initThreads((u1*) &dummy);
+       /* finally, start the finalizer thread */
+
+       if (!finalizer_start_thread())
+               throw_main_exception_exit();
 #endif
 
-       /*********************** Load JAVA classes  ***************************/
-   
-       /*printf("-------------------->%s\n",cp);*/
-       topclass = loader_load(utf_new_char(cp));
-       /*class_showmethods(topclass);  */
-
-       if (*exceptionptr) {
-               printf("Exception in thread \"main\" ");
-               utf_display_classname((*exceptionptr)->vftbl->class->name);
-               printf(": ");
-               utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
-               printf("\n");
-
-               *exceptionptr = NULL;
-       }
+       cacao_initializing = false;
 
-       if (topclass == 0) {
-               /* should we print something out? we already have the exception */
-               exit(1);
-       }
 
-       /************************* Start worker routines ********************/
+       /* start worker routines **************************************************/
 
        if (startit) {
-               methodinfo *mainmethod;
+               classinfo        *mainclass;    /* java/lang/Class                    */
+               methodinfo       *m;
                java_objectarray *a; 
+               s4                status;
+
+               /* set return value to OK */
+
+               status = 0;
+
+               if (jar) {
+                       /* open jar file with java.util.jar.JarFile */
+                       mainstring = getmainclassnamefromjar(mainstring);
+               }
+
+               /* load the main class */
+
+               if (!(mainclass = load_class_from_sysloader(utf_new_char(mainstring))))
+                       throw_main_exception_exit();
 
-/*             heap_addreference((void**) &a); */
+               /* error loading class, clear exceptionptr for new exception */
 
-               mainmethod = class_findmethod(topclass,
-                                                                         utf_new_char("main"), 
-                                                                         utf_new_char("([Ljava/lang/String;)V")
-                                                                         );
+               if (*exceptionptr || !mainclass) {
+/*                     *exceptionptr = NULL; */
+
+/*                     *exceptionptr = */
+/*                             new_exception_message(string_java_lang_NoClassDefFoundError, */
+/*                                                                       mainstring); */
+                       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 (!mainmethod || !(mainmethod->flags & ACC_STATIC)) {
-                       printf("Exception in thread \"main\" java.lang.NoSuchMethodError: main\n");
-                       exit(1);
+
+               if (!m || !(m->flags & ACC_STATIC)) {
+                       *exceptionptr = NULL;
+
+                       *exceptionptr =
+                               new_exception_message(string_java_lang_NoSuchMethodError,
+                                                                         "main");
+                       throw_main_exception_exit();
                }
 
+               /* build argument array */
+
                a = builtin_anewarray(argc - opt_ind, class_java_lang_String);
                for (i = opt_ind; i < argc; i++) {
                        a->data[i - opt_ind] = 
@@ -949,46 +1282,127 @@ int main(int argc, char **argv)
 #endif
                /*class_showmethods(currentThread->group->header.vftbl->class); */
 
-               *threadrootmethod=mainmethod;
-               /* here we go... */
-               asm_calljavafunction(mainmethod, a, NULL, NULL, NULL);
-       
-               if (*exceptionptr) {
-                       methodinfo *main_unhandled_print=class_resolvemethod_approx((*exceptionptr)->vftbl->class,
-                               utf_new_char("printStackTrace"),
-                               utf_new_char("()V"));
-                       if (main_unhandled_print) {
-                               java_objectheader *exo=*exceptionptr;
-                               *exceptionptr=0;
-                               asm_calljavafunction(main_unhandled_print,exo,NULL,NULL,NULL);
+#if defined(ENABLE_JVMTI) && defined(NATIVE_THREADS)
+               if(dbg) {
+                       debuggee = fork();
+                       if (debuggee == (-1)) {
+                               log_text("fork error");
+                               exit(1);
                        } else {
-                               printf("Exception in thread \"main\" ");
-                               utf_display_classname((*exceptionptr)->vftbl->class->name);
+                               if (debuggee == 0) {
+                                       /* child: allow helper process to trace us  */
+                                       if (TRACEME != 0)  exit(0);
+                                       
+                                       /* give parent/helper debugger process control */
+                                       kill(0, SIGTRAP);  /* do we need this at this stage ? */
+
+                                       /* continue with normal startup */      
 
-                               /* do we have a detail message? */
-                               if (((java_lang_Throwable *) *exceptionptr)->detailMessage) {
-                                       printf(": ");
-                               utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
+                               } else {
+
+                                       /* parent/helper debugger process */
+                                       wait(&waitval);
+
+                                       remotedbgjvmtienv = new_jvmtienv();
+                                       /* set eventcallbacks */
+                                       if (JVMTI_ERROR_NONE == 
+                                               remotedbgjvmtienv->
+                                               SetEventCallbacks(remotedbgjvmtienv,
+                                                                                 &jvmti_jdwp_EventCallbacks,
+                                                                                 sizeof(jvmti_jdwp_EventCallbacks))){
+                                               log_text("unable to setup event callbacks");
+                                               cacao_exit(1);                                          
+                                       }
+
+                                       /* setup listening process (JDWP) */
+                                       setup_debugger_process(transport);
+
+                                       /* start to be debugged program */
+                                       CONT(debuggee);
+
+                    /* exit debugger process - todo: cleanup */
+                                       joinAllThreads();
+                                       cacao_exit(0);
                                }
-                               printf("\n");
                        }
                }
+               else 
+                       debuggee= -1;
+               
+#endif
+               /* here we go... */
+
+               asm_calljavafunction(m, a, NULL, NULL, NULL);
+
+               /* exception occurred? */
+               if (*exceptionptr) {
+                       throw_main_exception();
+                       status = 1;
+               }
 
 #if defined(USE_THREADS)
 #if defined(NATIVE_THREADS)
                joinAllThreads();
 #else
                killThread(currentThread);
-               fprintf(stderr, "still here\n");
 #endif
 #endif
-               exit(0);
+
+               /* now exit the JavaVM */
+
+/*             (*jvm)->DestroyJavaVM(jvm); */
+
+               cacao_exit(status);
        }
 
        /************* If requested, compile all methods ********************/
 
        if (compileall) {
-               class_compile_methods();
+               classinfo *c;
+               methodinfo *m;
+               u4 slot;
+               s4 i;
+               classcache_name_entry *nmen;
+               classcache_class_entry *clsen;
+
+               /* create all classes found in the classpath */
+               /* XXX currently only works with zip/jar's */
+
+               loader_load_all_classes();
+
+               /* link all classes */
+
+               for (slot = 0; slot < classcache_hash.size; slot++) {
+                       nmen = (classcache_name_entry *) classcache_hash.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)
+                                               continue;
+
+                                       assert(c);
+                                       assert(c->loaded);
+                                       /*utf_fprint_classname(stderr,c->name);fprintf(stderr,"\n");*/
+
+                                       if (!c->linked)
+                                               if (!link_class(c))
+                                                       throw_main_exception_exit();
+
+                                       /* compile all class methods */
+                                       for (i = 0; i < c->methodscount; i++) {
+                                               m = &(c->methods[i]);
+                                               if (m->jcode) {
+                                                       /*fprintf(stderr,"    compiling:");utf_fprint(stderr,m->name);fprintf(stderr,"\n");*/
+                                                       (void) jit_compile(m);
+                                               }
+                                       }
+                               }
+                       }
+               }
        }
 
 
@@ -996,49 +1410,170 @@ int main(int argc, char **argv)
 
        if (specificmethodname) {
                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 (specificsignature) {
-                       m = class_findmethod(topclass, 
-                                                                utf_new_char(specificmethodname),
-                                                                utf_new_char(specificsignature));
+                       m = class_resolveclassmethod(mainclass,
+                                                                                utf_new_char(specificmethodname),
+                                                                                utf_new_char(specificsignature),
+                                                                                mainclass,
+                                                                                false);
                } else {
-                       m = class_findmethod(topclass, 
-                                                                utf_new_char(specificmethodname),
-                                                                NULL);
+                       m = class_resolveclassmethod(mainclass,
+                                                                                utf_new_char(specificmethodname),
+                                                                                NULL,
+                                                                                mainclass,
+                                                                                false);
                }
 
-               if (!m)
-                       panic("Specific method not found");
+               if (!m) {
+                       char message[MAXLOGTEXT];
+                       sprintf(message, "%s%s", specificmethodname,
+                                       specificsignature ? specificsignature : "");
+
+                       *exceptionptr =
+                               new_exception_message(string_java_lang_NoSuchMethodException,
+                                                                         message);
+                                                                                
+                       throw_main_exception_exit();
+               }
                
                jit_compile(m);
        }
 
-       exit(0);
+       cacao_shutdown(0);
+
+       /* keep compiler happy */
+
+       return 0;
 }
 
 
+/* cacao_exit ******************************************************************
+
+   Calls java.lang.System.exit(I)V to exit the JavaVM correctly.
 
-/************************************ Shutdown function *********************************
+*******************************************************************************/
+
+void cacao_exit(s4 status)
+{
+       methodinfo *m;
+
+       assert(class_java_lang_System);
+       assert(class_java_lang_System->loaded);
+
+#if defined(ENABLE_JVMTI)
+       set_jvmti_phase(JVMTI_PHASE_DEAD);
+       agentunload();
+#endif
+
+       if (!link_class(class_java_lang_System))
+               throw_main_exception_exit();
+
+       /* signal that we are exiting */
+
+       cacao_exiting = true;
+
+       /* call java.lang.System.exit(I)V */
+
+       m = class_resolveclassmethod(class_java_lang_System,
+                                                                utf_new_char("exit"),
+                                                                utf_int__void,
+                                                                class_java_lang_Object,
+                                                                true);
+       
+       if (!m)
+               throw_main_exception_exit();
+
+       /* call the exit function with passed exit status */
+
+       /* both inlinevirtual and outsiders not allowed on exit */
+       /*   not sure if permanant or temp restriction          */
+       if (inlinevirtuals) inlineoutsiders = false; 
+
+       asm_calljavafunction(m, (void *) (ptrint) status, NULL, NULL, NULL);
+
+       /* this should never happen */
+
+       if (*exceptionptr)
+               throw_exception_exit();
+
+       throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                          "System.exit(I)V returned without exception");
+}
+
+
+/*************************** Shutdown function *********************************
 
        Terminates the system immediately without freeing memory explicitly (to be
        used only for abnormal termination)
        
-*****************************************************************************************/
+*******************************************************************************/
 
 void cacao_shutdown(s4 status)
 {
-       /**** RTAprint ***/
 
-       if (verbose || getcompilingtime || statistics) {
-               log_text ("CACAO terminated by shutdown");
-               if (statistics)
+#if defined(ENABLE_JVMTI)
+       agentunload();
+#endif
+
+       if (opt_verbose || getcompilingtime || opt_stat) {
+               log_text("CACAO terminated by shutdown");
+               dolog("Exit status: %d\n", (s4) status);
+       }
+
+       exit(status);
+}
+
+
+/* exit_handler ****************************************************************
+
+   The exit_handler function is called upon program termination.
+
+   ATTENTION: Don't free system resources here! Some threads may still
+   be running as this is called from VMRuntime.exit(). The OS does the
+   cleanup for us.
+
+*******************************************************************************/
+
+void exit_handler(void)
+{
+       /********************* Print debug tables ************************/
+                               
+       if (showmethods) class_showmethods(mainclass);
+       if (showconstantpool) class_showconstantpool(mainclass);
+       if (showutf) utf_show();
+
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
+       clear_thread_flags();           /* restores standard file descriptor
+                                      flags */
+#endif
+
+       if (opt_verbose || getcompilingtime || opt_stat) {
+               log_text("CACAO terminated");
+
+#if defined(STATISTICS)
+               if (opt_stat) {
                        print_stats();
+#ifdef TYPECHECK_STATISTICS
+                       typecheck_print_statistics(get_logfile());
+#endif
+               }
+
+               mem_usagelog(1);
+
                if (getcompilingtime)
                        print_times();
-               mem_usagelog(0);
-               dolog("Exit status: %d\n", (int) status);
+#endif
        }
-
-       exit(status);
+       /* vm_print_profile(stderr);*/
 }