#ifdef STATISTICS statistics option.
[cacao.git] / src / cacao / cacao.c
index 03737d8941d513e219787d3daa691b151d88e6ff..3fb59b5b2ec9a5b3565ca1bb186f5ddaa6d6cd09 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 1032 2004-04-26 16:09:10Z twisti $
+   $Id: cacao.c 2022 2005-03-09 12:07:57Z twisti $
 
 */
 
 
 #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 "config.h"
+#include "cacao/cacao.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"
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "native/native.h"
+#include "toolbox/logging.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/stringlocal.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
 
 #ifdef TYPEINFO_DEBUG_TEST
-#include "typeinfo.h"
+#include "vm/jit/verify/typeinfo.h"
 #endif
 
-/* command line option */
-
-bool verbose = false;
-bool compileall = false;
-bool runverbose = false;       /* trace all method invocation                */
-bool verboseexception = false;
-bool collectverbose = false;
-
-bool loadverbose = false;
-bool linkverbose = false;
-bool initverbose = false;
-
-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       */
-
-bool showmethods = false;
-bool showconstantpool = false;
-bool showutf = false;
-
-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         */
 
-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 */
+/* define heap sizes **********************************************************/
 
-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           */
+#define HEAP_MAXSIZE      64 * 1024 * 1024; /* default 64MB                   */
+#define HEAP_STARTSIZE    2 * 1024 * 1024;  /* default 2MB                    */
 
-bool makeinitializations = true;
 
-bool getloadingtime = false;   /* to measure the runtime                     */
-s8 loadingtime = 0;
+/* Invocation API variables ***************************************************/
 
-bool getcompilingtime = false; /* compute compile time                       */
-s8 compilingtime = 0;          /* accumulated compile time                   */
+JavaVM *jvm;                        /* denotes a Java VM                      */
+JNIEnv *env;                        /* pointer to native method interface     */
+JDK1_1InitArgs vm_args;             /* JDK 1.1 VM initialization arguments    */
 
-int has_ext_instr_set = 0;     /* has instruction set extensions */
 
-bool statistics = false;
+bool cacao_initializing;
 
-bool opt_verify = true;        /* true if classfiles should be verified      */
+char *bootclasspath;                    /* contains the boot classpath        */
+char *classpath;                        /* contains the classpath             */
 
 char *mainstring;
 static classinfo *mainclass;
@@ -125,131 +94,109 @@ 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_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 STATIC_ANALYSIS
+#if defined(STATIC_ANALYSIS)
+# define OPT_RT              26
+# define OPT_XTA             27 
+# define OPT_VTA             28
+#endif /* 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 /* LSRA */
+
+#define OPT_JAR              35
+#define OPT_BOOTCLASSPATH    36
+#define OPT_BOOTCLASSPATH_A  37
+#define OPT_BOOTCLASSPATH_P  38
+#define OPT_VERSION          39
+
+
+opt_struct opts[] = {
+       { "classpath",         true,  OPT_CLASSPATH },
+       { "cp",                true,  OPT_CLASSPATH },
+       { "D",                 true,  OPT_D },
+       { "Xms",               true,  OPT_MS },
+       { "Xmx",               true,  OPT_MX },
+       { "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 },
 #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
-       {"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}
+       { "log",               true,  OPT_LOG },
+       { "c",                 true,  OPT_CHECK },
+       { "l",                 false, OPT_LOAD },
+    { "eager",             false, OPT_EAGER },
+       { "m",                 true,  OPT_METHOD },
+       { "sig",               true,  OPT_SIGNATURE },
+       { "s",                 true,  OPT_SHOW },
+       { "all",               false, OPT_ALL },
+       { "oloop",             false, OPT_OLOOP },
+       { "i",                 true,  OPT_INLINING },
+#ifdef STATIC_ANALYSIS
+       { "rt",                false, OPT_RT },
+       { "xta",               false, OPT_XTA },
+       { "vta",               false, OPT_VTA },
+#endif
+#ifdef LSRA
+       { "lsra",              false, OPT_LSRA },
+#endif
+       { "jar",               false, OPT_JAR },
+       { "Xbootclasspath:",   true,  OPT_BOOTCLASSPATH },
+       { "Xbootclasspath/a:", true,  OPT_BOOTCLASSPATH_A },
+       { "Xbootclasspath/p:", true,  OPT_BOOTCLASSPATH_P },
+       { "version",           false, OPT_VERSION },
+       { NULL,                false, 0 }
 };
 
-static int opt_ind = 1;
-static char *opt_arg;
-
-
-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;
-}
-
 
 /******************** interne Function: print_usage ************************
 
@@ -257,14 +204,22 @@ Prints the correct usage syntax to stdout.
 
 ***************************************************************************/
 
-static void print_usage()
+static void usage()
 {
-       printf("USAGE: cacao [options] classname [program arguments]\n");
+       printf("Usage: cacao [options] classname [program arguments]\n\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("    -cp <path>               specify a path to look for classes\n");
+       printf("    -classpath <path>        specify a path to look for classes\n");
+       printf("    -jar jarfile             execute a jar file\n");
+       printf("    -D<name>=<value>         add an entry to the property list\n");
+       printf("    -Xmx<size>[kK|mM]        specify the size for the heap\n");
+       printf("    -Xms<size>[kK|mM]        specify the initial size for the heap\n");
+       printf("    -mx<size>[kK|mM]         specify the size for the heap\n");
+       printf("    -ms<size>[kK|mM]         specify the initial size for the heap\n");
+       printf("    -Xbootclasspath:<path>   set search path for bootstrap classes and resources\n");
+       printf("    -Xbootclasspath/a:<path> append to end of bootstrap class path\n");
+       printf("    -Xbootclasspath/p:<path> prepend in front of bootstrap class path\n");
        printf("          -v ................... write state-information\n");
        printf("          -verbose ............. write more information\n");
        printf("          -verbosegc ........... write message for each GC\n");
@@ -273,6 +228,7 @@ static void print_usage()
 #ifdef TYPECHECK_VERBOSE
        printf("          -verbosetc ........... write debug messages while typechecking\n");
 #endif
+       printf("    -version                 print product version and exit\n");
 #if defined(__ALPHA__)
        printf("          -noieee .............. don't use ieee compliant arithmetic\n");
 #endif
@@ -280,12 +236,15 @@ static void print_usage()
        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");
@@ -297,237 +256,117 @@ static void print_usage()
        printf("                 u(tf) ......... show the utf - hash\n");
        printf("          -i     n ............. activate inlining\n");
        printf("                 v ............. inline virtual methods\n");
+       printf("                                 uses/turns rt option on\n");
        printf("                 e ............. inline methods with exceptions\n");
        printf("                 p ............. optimize argument renaming\n");
        printf("                 o ............. 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
+
+       /* exit with error code */
+
+       exit(1);
 }   
 
 
-/***************************** Function: print_times *********************
+/* version *********************************************************************
 
-       Prints a summary of CPU time usage.
+   Only prints cacao version information and exits.
 
-**************************************************************************/
+*******************************************************************************/
 
-static void print_times()
+static void version()
 {
-       s8 totaltime = getcputime();
-       s8 runtime = totaltime - loadingtime - compilingtime;
-       char logtext[MAXLOGTEXT];
-
-#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);
+       printf("cacao "VERSION"\n");
+       exit(0);
+}
 
-#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);
 
-#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",
+#ifdef TYPECHECK_STATISTICS
+void typecheck_print_statistics(FILE *file);
 #endif
-                       runtime / 1000000, (runtime % 1000000) / 1000);
-       log_text(logtext);
 
-#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);
-}
 
 
-/***************************** Function: print_stats *********************
+/* getmainclassfromjar ************************************************************
 
-       outputs detailed compiler statistics
+   gets the name of the main class form a jar's manifest file
 
-**************************************************************************/
+**********************************************************************************/
 
-static void print_stats()
+char *getmainclassnamefromjar(JNIEnv *env, char *mainstring)
 {
-       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);
-}
+       jclass class;
+       jmethodID mid;
+       jobject obj;
+               
+       class = (*env)->FindClass(env, "java/util/jar/JarFile");
+       if (class == NULL) {
+               log_text("unable to find java.util.jar.JarFile");
+               throw_main_exception_exit();
+       }
+       
+       mid = (*env)->GetMethodID(NULL, class, "<init>","(Ljava/lang/String;)V");
+       if (mid == NULL) {
+               log_text("unable to find constructor in java.util.jar.JarFile");
+               cacao_exit(1);
+       }
 
+       /* open jarfile */
+       obj = (*env)->NewObject(NULL,class,mid,((*env)->NewStringUTF(NULL,(char*)mainstring)));
+       if ((*env)->ExceptionOccurred(NULL) != NULL) {
+               (*env)->ExceptionDescribe(NULL);
+               cacao_exit(1);
+       }
+       
+       mid = (*env)->GetMethodID(NULL, class, "getManifest","()Ljava/util/jar/Manifest;");
+       if (mid == NULL) {
+               log_text("unable to find getMainfest method");
+               cacao_exit(1);
+       }
 
-#ifdef TYPECHECK_STATISTICS
-void typecheck_print_statistics(FILE *file);
-#endif
+       /* get manifest object */
+       obj = (*env)->CallObjectMethod(NULL,obj,mid);
+       if ((*env)->ExceptionOccurred(NULL) != NULL) {
+               (*env)->ExceptionDescribe(NULL);
+               cacao_exit(1);
+       }
+
+       mid = (*env)->GetMethodID(NULL, (jclass)((java_objectheader*) obj)->vftbl->class, "getMainAttributes","()Ljava/util/jar/Attributes;");
+       if (mid == NULL) {
+               log_text("unable to find getMainAttributes method");
+               cacao_exit(1);
+       }
+
+       /* get Main Attributes */
+       obj = (*env)->CallObjectMethod(NULL,obj,mid);
+       if ((*env)->ExceptionOccurred(NULL) != NULL) {
+               (*env)->ExceptionDescribe(NULL);
+               cacao_exit(1);
+       }
+
+
+       mid = (*env)->GetMethodID(NULL, (jclass)((java_objectheader*) obj)->vftbl->class, "getValue","(Ljava/lang/String;)Ljava/lang/String;");
+       if (mid == NULL) {
+               log_text("unable to find getValue method");
+               cacao_exit(1);
+       }
+
+       /* get property Main-Class */
+       obj = (*env)->CallObjectMethod(NULL,obj,mid,(*env)->NewStringUTF(NULL,"Main-Class"));
+       if ((*env)->ExceptionOccurred(NULL) != NULL) {
+               (*env)->ExceptionDescribe(NULL);
+               cacao_exit(1);
+       }
+       
+       return javastring_tochar((java_objectheader *) obj);
+}
 
 
 /*
@@ -551,24 +390,26 @@ void exit_handler(void)
 
        /************************ Free all resources *******************/
 
-       /*heap_close();*/               /* must be called before compiler_close and
-                                      loader_close because finalization occurs
-                                      here */
-
        loader_close();
-       tables_close(literalstring_free);
+       tables_close();
 
-       if (verbose || getcompilingtime || statistics) {
+       MFREE(classpath, u1, strlen(classpath));
+
+       if (opt_verbose || getcompilingtime || opt_stat) {
                log_text("CACAO terminated");
-               if (statistics) {
+
+#if defined(STATISTICS)
+               if (opt_stat) {
                        print_stats();
 #ifdef TYPECHECK_STATISTICS
                        typecheck_print_statistics(get_logfile());
 #endif
                }
+
                if (getcompilingtime)
                        print_times();
                mem_usagelog(1);
+#endif
        }
 }
 
@@ -587,55 +428,129 @@ int main(int argc, char **argv)
        /********** interne (nur fuer main relevante Optionen) **************/
    
        char logfilename[200] = "";
-       u4 heapmaxsize = 64000000;
-       u4 heapstartsize = 200000;
+       u4 heapmaxsize;
+       u4 heapstartsize;
        char *cp;
-       char classpath[500] = ".";
+       s4    cplen;
        bool startit = true;
        char *specificmethodname = NULL;
        char *specificsignature = NULL;
+       bool jar = false;
 
 #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");
+
 
        /************ Collect info from the environment ************************/
 
+       /* set the bootclasspath */
+
+       cp = getenv("BOOTCLASSPATH");
+       if (cp) {
+               bootclasspath = MNEW(char, strlen(cp) + 1);
+               strcpy(bootclasspath, cp);
+
+       } else {
+               cplen = strlen(CACAO_INSTALL_PREFIX) + strlen(CACAO_RT_JAR_PATH);
+
+               bootclasspath = MNEW(char, cplen + 1);
+               strcpy(bootclasspath, CACAO_INSTALL_PREFIX);
+               strcat(bootclasspath, CACAO_RT_JAR_PATH);
+       }
+
+
+       /* set the classpath */
+
        cp = getenv("CLASSPATH");
        if (cp) {
-               strcpy(classpath, cp);
+               classpath = MNEW(char, strlen(cp) + 1);
+               strcat(classpath, cp);
+
+       } else {
+               classpath = MNEW(char, 2);
+               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;
+
+
+       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) + 1);
+                       strcpy(bootclasspath, opt_arg);
                        break;
-                               
+
+               case OPT_BOOTCLASSPATH_A:
+                       /* append to end of bootclasspath */
+                       cplen = strlen(bootclasspath);
+
+                       bootclasspath = MREALLOC(bootclasspath,
+                                                                        char,
+                                                                        cplen,
+                                                                        cplen + 1 + strlen(opt_arg) + 1);
+
+                       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) + 1 + cplen + 1);
+
+                       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) + 1);
+                       strcpy(classpath, opt_arg);
+                       break;
+
+               case OPT_JAR:
+                       jar = true;
+                       break;
+                       
                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: ;
                        }       
@@ -643,24 +558,29 @@ int main(int argc, char **argv)
 
                case OPT_MS:
                case OPT_MX:
-                       if (opt_arg[strlen(opt_arg) - 1] == 'k') {
-                               j = 1024 * atoi(opt_arg);
+                       {
+                               char c;
+                               c = opt_arg[strlen(opt_arg) - 1];
 
-                       } else if (opt_arg[strlen(opt_arg) - 1] == 'm') {
-                               j = 1024 * 1024 * atoi(opt_arg);
+                               if (c == 'k' || c == 'K') {
+                                       j = 1024 * atoi(opt_arg);
 
-                       } else j = atoi(opt_arg);
+                               } else if (c == 'm' || c == 'M') {
+                                       j = 1024 * 1024 * atoi(opt_arg);
 
-                       if (i == OPT_MX) heapmaxsize = j;
-                       else heapstartsize = j;
+                               } else j = atoi(opt_arg);
+
+                               if (i == OPT_MX) heapmaxsize = 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;
@@ -684,7 +604,11 @@ int main(int argc, char **argv)
                case OPT_VERBOSECALL:
                        runverbose = true;
                        break;
-                               
+
+               case OPT_VERSION:
+                       version();
+                       break;
+
                case OPT_NOIEEE:
                        opt_noieee = true;
                        break;
@@ -706,9 +630,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);
@@ -724,8 +650,7 @@ int main(int argc, char **argv)
                                        checksync = false;
                                        break;
                                default:
-                                       print_usage();
-                                       exit(10);
+                                       usage();
                                }
                        }
                        break;
@@ -735,18 +660,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;
@@ -756,7 +685,7 @@ int main(int argc, char **argv)
                                switch (opt_arg[j]) {
                                case 'a':
                                        showdisassemble = true;
-                                       compileverbose=true;
+                                       compileverbose = true;
                                        break;
                                case 'c':
                                        showconstantpool = true;
@@ -775,8 +704,7 @@ int main(int argc, char **argv)
                                        showutf = true;
                                        break;
                                default:
-                                       print_usage();
-                                       exit(10);
+                                       usage();
                                }
                        }
                        break;
@@ -789,10 +717,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;
@@ -804,107 +739,221 @@ 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:
+#if defined(__I386__) || defined(__ALPHA__) || defined (__X86_64__) || defined(__POWERPC__)
+                       opt_lsra = true;
+#else
+                       printf("LSRA not available for this architecture\n");
+                       opt_lsra = false;
+#endif
+                       break;
+#endif
 
                default:
-                       print_usage();
-                       exit(10);
+                       printf("Unknown option: %s\n", argv[opt_ind]);
+                       usage();
                }
        }
-   
-   
-       if (opt_ind >= argc) {
-               print_usage();
-               exit(10);
-       }
+
+       if (opt_ind >= argc)
+               usage();
+
+
+       /* transform dots into slashes in the class name */
 
        mainstring = argv[opt_ind++];
-       for (i = strlen(mainstring) - 1; i >= 0; i--) {     /* Transform dots into slashes */
-               if (mainstring[i] == '.') mainstring[i] = '/';  /* in the class name */
-       }
+       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) + 1 + strlen(classpath) + 1);
+               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 -------------------------------------------------------");
-       }
+
+       /* 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.classpath = classpath;
+       /* load and initialize a Java VM, return a JNI interface pointer in env */
+
+       JNI_CreateJavaVM(&jvm, &env, &vm_args);
+
 
        /* initialize the garbage collector */
+
        gc_init(heapmaxsize, heapstartsize);
 
-       native_setclasspath(classpath);
-               
        tables_init();
+
+       /* initialize the loader with bootclasspath and append classpath entries */
+
+       suck_init(bootclasspath);
        suck_init(classpath);
 
-       jit_init();
+       cacao_initializing = true;
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
        initThreadsEarly();
 #endif
+       initLocks();
+#endif
+
+       /* install architecture dependent signal handler used for exceptions */
+       init_exceptions();
+
+       /* initializes jit compiler and codegen stuff */
+       jit_init();
+
+       /* initialize some cacao subsystems */
 
+       utf8_init();
+       class_init_foo();
        loader_init((u1 *) &dummy);
 
-       native_loadclasses();
+       if (!native_init())
+               throw_main_exception_exit();
+
+       if (!exceptions_init())
+               throw_main_exception_exit();
 
 #if defined(USE_THREADS)
-       initThreads((u1*) &dummy);
+       initThreads((u1 *) &dummy);
 #endif
 
+       *threadrootmethod = NULL;
 
-       /************************* Start worker routines ********************/
+       /*That's important, otherwise we get into trouble, if the Runtime static
+         initializer is called before (circular dependency. This is with
+         classpath 0.09. Another important thing is, that this has to happen
+         after initThreads!!! */
+
+       if (!class_init(class_java_lang_System))
+               throw_main_exception_exit();
+
+       cacao_initializing = false;
+
+
+       /* start worker routines **************************************************/
 
        if (startit) {
-               methodinfo *mainmethod;
+               classinfo        *cl;           /* java/lang/ClassLoader              */
+               classinfo        *mainclass;    /* java/lang/Class                    */
+               methodinfo       *m;
                java_objectarray *a; 
+               s4                status;
 
-               /* create, load and link the main class */
-               mainclass = class_new(utf_new_char(mainstring));
-               class_load(mainclass);
+               /* set return value to OK */
+
+               status = 0;
 
-               if (*exceptionptr)
-                       throw_exception_exit();
+               if (jar) {
+                       /* open jar file with java.util.jar.JarFile */
+                       mainstring = getmainclassnamefromjar((JNIEnv *) &env, mainstring);
+               }
+
+               /* get system classloader */
+
+               m = class_resolveclassmethod(class_java_lang_ClassLoader,
+                                                                        utf_new_char("getSystemClassLoader"),
+                                                                        utf_new_char("()Ljava/lang/ClassLoader;"),
+                                                                        class_java_lang_Object,
+                                                                        false);
+
+               cl = (classinfo *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
 
-               class_link(mainclass);
+               /* get `loadClass' method */
 
-               if (*exceptionptr)
-                       throw_exception_exit();
+               m = class_resolveclassmethod(cl->header.vftbl->class,
+                                                                        utf_new_char("loadClass"),
+                                                                        utf_new_char("(Ljava/lang/String;)Ljava/lang/Class;"),
+                                                                        class_java_lang_Object,
+                                                                        false);
 
-               mainmethod = class_resolveclassmethod(mainclass,
-                                                                                         utf_new_char("main"), 
-                                                                                         utf_new_char("([Ljava/lang/String;)V"),
-                                                                                         mainclass,
-                                                                                         true);
+               /* load the main class */
 
-               /* problems with main method? */
-               if (*exceptionptr)
-                       throw_exception_exit();
+               mainclass =
+                       (classinfo *) asm_calljavafunction(m,
+                                                                                          cl,
+                                                                                          javastring_new_char(mainstring),
+                                                                                          NULL,
+                                                                                          NULL);
+
+               /* 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();
+               }
+
+               /* 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);
 
                /* there is no main method or it isn't static */
-               if (!mainmethod || !(mainmethod->flags & ACC_STATIC)) {
+
+               if (*exceptionptr || !m || !(m->flags & ACC_STATIC)) {
+                       *exceptionptr = NULL;
+
                        *exceptionptr =
                                new_exception_message(string_java_lang_NoSuchMethodError,
                                                                          "main");
-                       throw_exception_exit();
+                       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] = 
@@ -917,24 +966,31 @@ int main(int argc, char **argv)
 #endif
                /*class_showmethods(currentThread->group->header.vftbl->class); */
 
-               *threadrootmethod = mainmethod;
+               *threadrootmethod = m;
 
                /* here we go... */
-               asm_calljavafunction(mainmethod, a, NULL, NULL, NULL);
+
+               asm_calljavafunction(m, a, NULL, NULL, NULL);
 
                /* exception occurred? */
-               if (*exceptionptr)
-                       throw_exception_exit();
+               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 ********************/
@@ -955,10 +1011,12 @@ int main(int argc, char **argv)
 
                        while (c) {
                                if (!c->loaded)
-                                       class_load(c);
+                                       if (!class_load(c))
+                                               throw_main_exception_exit();
 
                                if (!c->linked)
-                                       class_link(c);
+                                       if (!class_link(c))
+                                               throw_main_exception_exit();
 
                                /* compile all class methods */
                                for (i = 0; i < c->methodscount; i++) {
@@ -981,15 +1039,12 @@ int main(int argc, char **argv)
 
                /* create, load and link the main class */
                mainclass = class_new(utf_new_char(mainstring));
-               class_load(mainclass);
-
-               if (*exceptionptr)
-                       throw_exception_exit();
 
-               class_link(mainclass);
+               if (!class_load(mainclass))
+                       throw_main_exception_exit();
 
-               if (*exceptionptr)
-                       throw_exception_exit();
+               if (!class_link(mainclass))
+                       throw_main_exception_exit();
 
                if (specificsignature) {
                        m = class_resolveclassmethod(mainclass,
@@ -1008,22 +1063,75 @@ int main(int argc, char **argv)
                if (!m) {
                        char message[MAXLOGTEXT];
                        sprintf(message, "%s%s", specificmethodname,
-                                       specificmethodname ? specificmethodname : "");
+                                       specificsignature ? specificsignature : "");
 
                        *exceptionptr =
                                new_exception_message(string_java_lang_NoSuchMethodException,
                                                                          message);
                                                                                 
-                       throw_exception_exit();
+                       throw_main_exception_exit();
                }
                
                jit_compile(m);
        }
 
-       exit(0);
+       cacao_shutdown(0);
+
+       /* keep compiler happy */
+
+       return 0;
 }
 
 
+/* cacao_exit ******************************************************************
+
+   Calls java.lang.Runtime.exit(I)V to exit the JavaVM correctly.
+
+*******************************************************************************/
+
+void cacao_exit(s4 status)
+{
+       classinfo *c;
+       methodinfo *m;
+
+       /* class should already be loaded, but who knows... */
+
+       c = class_new(utf_new_char("java/lang/System"));
+
+       if (!class_load(c))
+               throw_main_exception_exit();
+
+       if (!class_link(c))
+               throw_main_exception_exit();
+
+       /* call System.exit(I)V */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_new_char("exit"),
+                                                                utf_new_char("(I)V"),
+                                                                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 *********************************
 
@@ -1034,16 +1142,9 @@ int main(int argc, char **argv)
 
 void cacao_shutdown(s4 status)
 {
-       /**** RTAprint ***/
-
-       if (verbose || getcompilingtime || statistics) {
-               log_text ("CACAO terminated by shutdown");
-               if (statistics)
-                       print_stats();
-               if (getcompilingtime)
-                       print_times();
-               mem_usagelog(0);
-               dolog("Exit status: %d\n", (int) status);
+       if (opt_verbose || getcompilingtime || opt_stat) {
+               log_text("CACAO terminated by shutdown");
+               dolog("Exit status: %d\n", (s4) status);
        }
 
        exit(status);