Next save.
[cacao.git] / main.c
diff --git a/main.c b/main.c
index bb08526da2d1156e5d9dbbe956dab52f5631f8b6..75053d74c12311e553964129e3dc1a9742c6aa36 100644 (file)
--- a/main.c
+++ b/main.c
      - Calling the class loader
      - Running the main method
 
-   $Id: main.c 557 2003-11-02 22:51:59Z twisti $
+   $Id: main.c 1395 2004-08-03 18:47:19Z twisti $
 
 */
 
 
 #include <stdlib.h>
+#include <string.h>
+#include "exceptions.h"
+#include "main.h"
+#include "options.h"
 #include "global.h"
 #include "tables.h"
 #include "loader.h"
-#include "jit.h"
+#include "jit/jit.h"
 #include "asmpart.h"
 #include "builtin.h"
 #include "native.h"
+#include "statistics.h"
+#include "mm/boehm.h"
 #include "threads/thread.h"
-#include "toolbox/loging.h"
-#include "parseRTstats.h"
+#include "toolbox/logging.h"
+#include "toolbox/memory.h"
+#include "jit/parseRTstats.h"
+#include "nat/java_io_File.h"            /* required by java_lang_Runtime.h   */
+#include "nat/java_util_Properties.h"    /* required by java_lang_Runtime.h   */
+#include "nat/java_lang_Runtime.h"
+#include "nat/java_lang_Throwable.h"
+
+#ifdef TYPEINFO_DEBUG_TEST
+#include "typeinfo.h"
+#endif
 
 
-bool compileall = false;
-bool verbose =  false;
+bool cacao_initializing;
 
-static bool showmethods = false;
-static bool showconstantpool = false;
-static bool showutf = false;
-static classinfo *topclass;
+char *classpath;                        /* contains classpath                 */
+char *mainstring;
+static classinfo *mainclass;
 
-#ifndef USE_THREADS
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
 void **stackbottom = 0;
 #endif
 
@@ -101,45 +114,62 @@ void **stackbottom = 0;
 #define OPT_INLINING   25
 #define OPT_RT          26
 #define OPT_XTA         27 
-#define OPT_VTA         28 
+#define OPT_VTA         28
+#define OPT_VERBOSETC   29
+#define OPT_NOVERIFY    30
+#define OPT_LIBERALUTF  31
+#define OPT_VERBOSEEXCEPTION 32
+#define OPT_EAGER            33
 
 
 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_IGNORE},
-       {"oss",         true,   OPT_IGNORE},
-       {"ss",          true,   OPT_IGNORE},
-       {"v",           false,  OPT_VERBOSE1},
-       {"verbose",     false,  OPT_VERBOSE},
-       {"verbosegc",   false,  OPT_VERBOSEGC},
-       {"verbosecall", false,  OPT_VERBOSECALL},
-       {"noieee",      false,  OPT_NOIEEE},
-       {"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}
+       {"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},
+#endif
+#if defined(__ALPHA__)
+       {"noieee",           false,  OPT_NOIEEE},
+#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},
+    { "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},
+       {"rt",               false,  OPT_RT},
+       {"xta",              false,  OPT_XTA},
+       {"vta",              false,  OPT_VTA},
+       {NULL,               false,  0}
 };
 
 static int opt_ind = 1;
 static char *opt_arg;
 
-static int get_opt (int argc, char **argv) 
+
+static int get_opt(int argc, char **argv)
 {
        char *a;
        int i;
@@ -149,15 +179,15 @@ static int get_opt (int argc, char **argv)
        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 */
+       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 */
+
+               else {
+                       if (strcmp(a + 1, opts[i].name) == 0) { /* parameter option found */
                                opt_ind++;
                                if (opt_ind < argc) {
                                        opt_arg = argv[opt_ind];
@@ -165,13 +195,13 @@ static int get_opt (int argc, char **argv)
                                        return opts[i].value;
                                }
                                return OPT_ERROR;
-                       }
-                       else {
+
+                       else {
                                size_t l = strlen(opts[i].name);
-                               if (strlen(a+1) > l) {
-                                       if (memcmp (a+1, opts[i].name, l)==0) {
+                               if (strlen(a + 1) > l) {
+                                       if (memcmp(a + 1, opts[i].name, l) == 0) {
                                                opt_ind++;
-                                               opt_arg = a+1+l;
+                                               opt_arg = a + 1 + l;
                                                return opts[i].value;
                                        }
                                }
@@ -183,8 +213,6 @@ static int get_opt (int argc, char **argv)
 }
 
 
-
-
 /******************** interne Function: print_usage ************************
 
 Prints the correct usage syntax to stdout.
@@ -195,17 +223,26 @@ static void print_usage()
 {
        printf("USAGE: cacao [options] classname [program arguments]\n");
        printf("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("          -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("          -Xmx maxmem[kK|mM] ... specify the size for the heap\n");
+       printf("          -Xms initmem[kK|mM] .. specify the initial size for the heap\n");
+       printf("          -mx maxmem[kK|mM] .... specify the size for the heap\n");
+       printf("          -ms initmem[kK|mM] ... 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");
+#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");
        printf("          -stat ................ detailed compiler statistics\n");
@@ -214,6 +251,7 @@ static void print_usage()
        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");
@@ -234,229 +272,9 @@ static void print_usage()
 }   
 
 
-
-/***************************** Function: print_times *********************
-
-       Prints a summary of CPU time usage.
-
-**************************************************************************/
-
-static void print_times()
-{
-       long int totaltime = getcputime();
-       long int runtime = totaltime - loadingtime - compilingtime;
-
-       sprintf(logtext, "Time for loading classes: %ld secs, %ld millis",
-                       loadingtime / 1000000, (loadingtime % 1000000) / 1000);
-       dolog();
-       sprintf(logtext, "Time for compiling code:  %ld secs, %ld millis",
-                       compilingtime / 1000000, (compilingtime % 1000000) / 1000);
-       dolog();
-       sprintf(logtext, "Time for running program: %ld secs, %ld millis",
-                       runtime / 1000000, (runtime % 1000000) / 1000);
-       dolog();
-       sprintf(logtext, "Total time: %ld secs, %ld millis",
-                       totaltime / 1000000, (totaltime % 1000000) / 1000);
-       dolog();
-}
-
-
-
-
-
-
-/***************************** Function: print_stats *********************
-
-       outputs detailed compiler statistics
-
-**************************************************************************/
-
-static void print_stats()
-{
-       sprintf(logtext, "Number of JitCompiler Calls: %d", count_jit_calls);
-       dolog();
-       sprintf(logtext, "Number of compiled Methods: %d", count_methods);
-       dolog();
-       sprintf(logtext, "Number of max basic blocks per method: %d", count_max_basic_blocks);
-       dolog();
-       sprintf(logtext, "Number of compiled basic blocks: %d", count_basic_blocks);
-       dolog();
-       sprintf(logtext, "Number of max JavaVM-Instructions per method: %d", count_max_javainstr);
-       dolog();
-       sprintf(logtext, "Number of compiled JavaVM-Instructions: %d", count_javainstr);
-       dolog();
-       sprintf(logtext, "Size of compiled JavaVM-Instructions:   %d(%d)", count_javacodesize,
-                       count_javacodesize - count_methods * 18);
-       dolog();
-       sprintf(logtext, "Size of compiled Exception Tables:      %d", count_javaexcsize);
-       dolog();
-       sprintf(logtext, "Value of extended instruction set var:  %d", has_ext_instr_set);
-       dolog();
-       sprintf(logtext, "Number of Machine-Instructions: %d", count_code_len >> 2);
-       dolog();
-       sprintf(logtext, "Number of Spills: %d", count_spills);
-       dolog();
-       sprintf(logtext, "Number of Activ    Pseudocommands: %5d", count_pcmd_activ);
-       dolog();
-       sprintf(logtext, "Number of Drop     Pseudocommands: %5d", count_pcmd_drop);
-       dolog();
-       sprintf(logtext, "Number of Const    Pseudocommands: %5d (zero:%5d)", count_pcmd_load, count_pcmd_zero);
-       dolog();
-       sprintf(logtext, "Number of ConstAlu Pseudocommands: %5d (cmp: %5d, store:%5d)", count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
-       dolog();
-       sprintf(logtext, "Number of Move     Pseudocommands: %5d", count_pcmd_move);
-       dolog();
-       sprintf(logtext, "Number of Load     Pseudocommands: %5d", count_load_instruction);
-       dolog();
-       sprintf(logtext, "Number of Store    Pseudocommands: %5d (combined: %5d)", count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
-       dolog();
-       sprintf(logtext, "Number of OP       Pseudocommands: %5d", count_pcmd_op);
-       dolog();
-       sprintf(logtext, "Number of DUP      Pseudocommands: %5d", count_dup_instruction);
-       dolog();
-       sprintf(logtext, "Number of Mem      Pseudocommands: %5d", count_pcmd_mem);
-       dolog();
-       sprintf(logtext, "Number of Method   Pseudocommands: %5d", count_pcmd_met);
-       dolog();
-       sprintf(logtext, "Number of Branch   Pseudocommands: %5d (rets:%5d, Xrets: %5d)",
-                       count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
-       dolog();
-       sprintf(logtext, "Number of Table    Pseudocommands: %5d", count_pcmd_table);
-       dolog();
-       sprintf(logtext, "Number of Useful   Pseudocommands: %5d", count_pcmd_table +
-                       count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
-       dolog();
-       sprintf(logtext, "Number of Null Pointer Checks:     %5d", count_check_null);
-       dolog();
-       sprintf(logtext, "Number of Array Bound Checks:      %5d", count_check_bound);
-       dolog();
-       sprintf(logtext, "Number of Try-Blocks: %d", count_tryblocks);
-       dolog();
-       sprintf(logtext, "Maximal count of stack elements:   %d", count_max_new_stack);
-       dolog();
-       sprintf(logtext, "Upper bound of max stack elements: %d", count_upper_bound_new_stack);
-       dolog();
-       sprintf(logtext, "Distribution of stack sizes at block boundary");
-       dolog();
-       sprintf(logtext, "    0    1    2    3    4    5    6    7    8    9    >=10");
-       dolog();
-       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]);
-       dolog();
-       sprintf(logtext, "Distribution of store stack depth");
-       dolog();
-       sprintf(logtext, "    0    1    2    3    4    5    6    7    8    9    >=10");
-       dolog();
-       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]);
-       dolog();
-       sprintf(logtext, "Distribution of store creator chains first part");
-       dolog();
-       sprintf(logtext, "    0    1    2    3    4    5    6    7    8    9  ");
-       dolog();
-       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]);
-       dolog();
-       sprintf(logtext, "Distribution of store creator chains second part");
-       dolog();
-       sprintf(logtext, "   10   11   12   13   14   15   16   17   18   19  >=20");
-       dolog();
-       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]);
-       dolog();
-       sprintf(logtext, "Distribution of analysis iterations");
-       dolog();
-       sprintf(logtext, "    1    2    3    4    >=5");
-       dolog();
-       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]);
-       dolog();
-       sprintf(logtext, "Distribution of basic blocks per method");
-       dolog();
-       sprintf(logtext, " <= 5 <=10 <=15 <=20 <=30 <=40 <=50 <=75  >75");
-       dolog();
-       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]);
-       dolog();
-       sprintf(logtext, "Distribution of basic block sizes");
-       dolog();
-       sprintf(logtext,
-                        "  0    1    2    3    4   5   6   7   8   9 <13 <15 <17 <19 <21 <26 <31 >30");
-       dolog();
-       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]);
-       dolog();
-       sprintf(logtext, "Size of Code Area (Kb):  %10.3f", (float) count_code_len / 1024);
-       dolog();
-       sprintf(logtext, "Size of data Area (Kb):  %10.3f", (float) count_data_len / 1024);
-       dolog();
-       sprintf(logtext, "Size of Class Infos (Kb):%10.3f", (float) (count_class_infos) / 1024);
-       dolog();
-       sprintf(logtext, "Size of Const Pool (Kb): %10.3f", (float) (count_const_pool_len + count_utf_len) / 1024);
-       dolog();
-       sprintf(logtext, "Size of Vftbl (Kb):      %10.3f", (float) count_vftbl_len / 1024);
-       dolog();
-       sprintf(logtext, "Size of comp stub (Kb):  %10.3f", (float) count_cstub_len / 1024);
-       dolog();
-       sprintf(logtext, "Size of native stub (Kb):%10.3f", (float) count_nstub_len / 1024);
-       dolog();
-       sprintf(logtext, "Size of Utf (Kb):        %10.3f", (float) count_utf_len / 1024);
-       dolog();
-       sprintf(logtext, "Size of VMCode (Kb):     %10.3f(%d)", (float) count_vmcode_len / 1024,
-                       count_vmcode_len - 18 * count_all_methods);
-       dolog();
-       sprintf(logtext, "Size of ExTable (Kb):    %10.3f", (float) count_extable_len / 1024);
-       dolog();
-       sprintf(logtext, "Number of class loads:   %d", count_class_loads);
-       dolog();
-       sprintf(logtext, "Number of class inits:   %d", count_class_inits);
-       dolog();
-       sprintf(logtext, "Number of loaded Methods: %d\n\n", count_all_methods);
-       dolog();
-
-       sprintf(logtext, "Calls of utf_new: %22d", count_utf_new);
-       dolog();
-       sprintf(logtext, "Calls of utf_new (element found): %6d\n\n", count_utf_new_found);
-       dolog();
-}
-
-
-
-/********** Function: class_compile_methods   (debugging only) ********/
-
-void class_compile_methods ()
-{
-       int        i;
-       classinfo  *c;
-       methodinfo *m;
-       
-       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);
-       }
-}
-
+#ifdef TYPECHECK_STATISTICS
+void typecheck_print_statistics(FILE *file);
+#endif
 
 
 /*
@@ -469,36 +287,37 @@ void exit_handler(void)
 {
        /********************* Print debug tables ************************/
                                
-       if (showmethods) class_showmethods (topclass);
-       if (showconstantpool)  class_showconstantpool (topclass);
-       if (showutf)           utf_show ();
+       if (showmethods) class_showmethods(mainclass);
+       if (showconstantpool) class_showconstantpool(mainclass);
+       if (showutf) utf_show();
 
-#ifdef USE_THREADS
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        clear_thread_flags();           /* restores standard file descriptor
-                                                                  flags */
+                                      flags */
 #endif
 
        /************************ Free all resources *******************/
 
-       heap_close ();                          /* must be called before compiler_close and
-                                                                  loader_close because finalization occurs
-                                                                  here */
+       loader_close();
+       tables_close();
 
-       loader_close ();
-       tables_close ( literalstring_free );
+       MFREE(classpath, u1, strlen(classpath));
 
-       if (verbose || getcompilingtime || statistics) {
-               log_text ("CACAO terminated");
-               if (statistics)
-                       print_stats ();
+       if (verbose || getcompilingtime || opt_stat) {
+               log_text("CACAO terminated");
+               if (opt_stat) {
+                       print_stats();
+#ifdef TYPECHECK_STATISTICS
+                       typecheck_print_statistics(get_logfile());
+#endif
+               }
                if (getcompilingtime)
-                       print_times ();
+                       print_times();
                mem_usagelog(1);
        }
 }
 
 
-
 /************************** Function: main *******************************
 
    The main program.
@@ -507,33 +326,43 @@ void exit_handler(void)
 
 int main(int argc, char **argv)
 {
-       s4 i,j;
-       char *cp;
-       java_objectheader *local_exceptionptr = 0;
+       s4 i, j;
        void *dummy;
        
        /********** interne (nur fuer main relevante Optionen) **************/
    
        char logfilename[200] = "";
-       u4 heapsize = 64000000;
-       u4 heapstartsize = 200000;
-       char classpath[500] = ".:/usr/local/lib/java/classes";
+       u4 heapmaxsize = 64 * 1024 * 1024;
+       u4 heapstartsize = 200 * 1024;
+       char *cp;
        bool startit = true;
        char *specificmethodname = NULL;
        char *specificsignature = NULL;
 
-#ifndef USE_THREADS
+#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 an initial, minimal classpath */
+       classpath = MNEW(char, 2);
+       strcpy(classpath, ".");
+
+       /* get classpath environment */
        cp = getenv("CLASSPATH");
        if (cp) {
-               strcpy(classpath, cp);
+               classpath = MREALLOC(classpath,
+                                                        char,
+                                                        strlen(classpath),
+                                                        strlen(classpath) + 1 + strlen(cp) + 1);
+               strcat(classpath, ":");
+               strcat(classpath, cp);
        }
 
        /***************** Interpret the command line *****************/
@@ -541,13 +370,16 @@ int main(int argc, char **argv)
        checknull = false;
        opt_noieee = false;
 
-       while ((i = get_opt(argc,argv)) != OPT_DONE) {
+       while ((i = get_opt(argc, argv)) != OPT_DONE) {
                switch (i) {
                case OPT_IGNORE: break;
                        
-               case OPT_CLASSPATH:    
-                       strcpy (classpath + strlen(classpath), ":");
-                       strcpy (classpath + strlen(classpath), opt_arg);
+               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_D:
@@ -555,7 +387,7 @@ int main(int argc, char **argv)
                                int n;
                                int l = strlen(opt_arg);
                                for (n = 0; n < l; n++) {
-                                       if (opt_arg[n]=='=') {
+                                       if (opt_arg[n] == '=') {
                                                opt_arg[n] = '\0';
                                                attach_property(opt_arg, opt_arg + n + 1);
                                                goto didit;
@@ -567,35 +399,51 @@ int main(int argc, char **argv)
                        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);
+                       {
+                               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 heapstartsize = j;
                        }
-                       else j = atoi(opt_arg);
-                               
-                       if (i == OPT_MX) heapsize = j;
-                       else heapstartsize = j;
                        break;
 
                case OPT_VERBOSE1:
                        verbose = true;
                        break;
-                                                               
+
                case OPT_VERBOSE:
                        verbose = true;
                        loadverbose = true;
+                       linkverbose = true;
                        initverbose = true;
                        compileverbose = true;
                        break;
-                               
+
+               case OPT_VERBOSEEXCEPTION:
+                       verboseexception = true;
+                       break;
+
                case OPT_VERBOSEGC:
                        collectverbose = true;
                        break;
+
+#ifdef TYPECHECK_VERBOSE
+               case OPT_VERBOSETC:
+                       typecheckverbose = true;
+                       break;
+#endif
                                
                case OPT_VERBOSECALL:
                        runverbose = true;
@@ -605,6 +453,14 @@ int main(int argc, char **argv)
                        opt_noieee = true;
                        break;
 
+               case OPT_NOVERIFY:
+                       opt_verify = false;
+                       break;
+
+               case OPT_LIBERALUTF:
+                       opt_liberalutf = true;
+                       break;
+
                case OPT_SOFTNULL:
                        checknull = true;
                        break;
@@ -615,7 +471,7 @@ int main(int argc, char **argv)
                        break;
                                        
                case OPT_STAT:
-                       statistics = true;
+                       opt_stat = true;
                        break;
                                        
                case OPT_LOG:
@@ -643,18 +499,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;
@@ -664,7 +524,7 @@ int main(int argc, char **argv)
                                switch (opt_arg[j]) {
                                case 'a':
                                        showdisassemble = true;
-                                       compileverbose=true;
+                                       compileverbose = true;
                                        break;
                                case 'c':
                                        showconstantpool = true;
@@ -723,7 +583,7 @@ int main(int argc, char **argv)
                        break;
 
                case OPT_XTA:
-                       /***opt_xta = true; not yet **/
+                       opt_xta = false; /**not yet **/
                        break;
 
                case OPT_VTA:
@@ -742,100 +602,166 @@ int main(int argc, char **argv)
                exit(10);
        }
 
+       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 */
+       }
+
 
        /**************************** Program start *****************************/
 
        log_init(logfilename);
-       if (verbose) {
+       if (verbose)
                log_text("CACAO started -------------------------------------------------------");
-       }
-       
-       suck_init(classpath);
-       native_setclasspath(classpath);
-               
+
+       /* initialize the garbage collector */
+       gc_init(heapmaxsize, heapstartsize);
+
        tables_init();
-       heap_init(heapsize, heapstartsize, &dummy);
-       jit_init();
-       loader_init();
+       suck_init(classpath);
 
-       native_loadclasses();
+       cacao_initializing = true;
 
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       initThreadsEarly();
+#endif
+       initLocks();
 
-       /*********************** Load JAVA classes  ***************************/
-   
-       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 */
-       }
+       /* install architecture dependent signal handler used for exceptions */
+       init_exceptions();
 
-       topclass = loader_load( utf_new_char (cp) );
+       /* initializes jit compiler and codegen stuff */
+       jit_init();
 
-       if (exceptionptr != 0) {
-               printf("#### Class loader has thrown: ");
-               utf_display(exceptionptr->vftbl->class->name);
-               printf("\n");
+       loader_init((u1 *) &dummy);
 
-               exceptionptr = 0;
-       }
+       jit_init();
 
-       if (topclass == 0) {
-               printf("#### Could not find top class - exiting\n");
-               exit(1);
-       }
+       /* initialize exceptions used in the system */
+       init_system_exceptions();
 
-       gc_init();
+       native_loadclasses();
 
-#ifdef USE_THREADS
-       initThreads((u1*) &dummy);                   /* schani */
+#if defined(USE_THREADS)
+       initThreads((u1 *) &dummy);
 #endif
 
+       *threadrootmethod = NULL;
+
+       /*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_new(utf_new_char("java/lang/System"))))
+               throw_main_exception_exit();
+
+       cacao_initializing = false;
+
        /************************* Start worker routines ********************/
 
        if (startit) {
                methodinfo *mainmethod;
                java_objectarray *a; 
 
-               heap_addreference((void**) &a);
+               /* create, load and link the main class */
+               mainclass = class_new(utf_new_char(mainstring));
+
+               if (!class_load(mainclass))
+                       throw_main_exception_exit();
+
+               if (!class_link(mainclass))
+                       throw_main_exception_exit();
+
+               mainmethod = class_resolveclassmethod(mainclass,
+                                                                                         utf_new_char("main"), 
+                                                                                         utf_new_char("([Ljava/lang/String;)V"),
+                                                                                         mainclass,
+                                                                                         false);
+
+               /* problems with main method? */
+/*             if (*exceptionptr) */
+/*                     throw_exception_exit(); */
+
+               /* there is no main method or it isn't static */
+               if (!mainmethod || !(mainmethod->flags & ACC_STATIC)) {
+                       *exceptionptr =
+                               new_exception_message(string_java_lang_NoSuchMethodError,
+                                                                         "main");
+                       throw_main_exception_exit();
+               }
 
-               mainmethod = class_findmethod (
-                                                                          topclass,
-                                                                          utf_new_char ("main"), 
-                                                                          utf_new_char ("([Ljava/lang/String;)V")
-                                                                          );
-               if (!mainmethod) panic("Can not find method 'void main(String[])'");
-               if ((mainmethod->flags & ACC_STATIC) != ACC_STATIC) panic("main is not static!");
-                       
                a = builtin_anewarray(argc - opt_ind, class_java_lang_String);
                for (i = opt_ind; i < argc; i++) {
-                       a->data[i - opt_ind] = javastring_new(utf_new_char(argv[i]));
+                       a->data[i - opt_ind] = 
+                               (java_objectheader *) javastring_new(utf_new_char(argv[i]));
                }
-               local_exceptionptr = asm_calljavamethod(mainmethod, a, NULL, NULL, NULL);
-       
-               if (local_exceptionptr) {
-                       printf("#### Program has thrown: ");
-                       utf_display(local_exceptionptr->vftbl->class->name);
-                       printf("\n");
-               }
-               /*RTAprint*/ if ((pCallgraph >= 1) && (opt_rt)) {
-                       /*RTAprint*/    printCallgraph (); }
 
-               /*RTprint*/ if ((pClassHeir >= 1) && (opt_rt)) {
-                       /*RTprint*/     printf("Last RTA Info -");
-                       /*RTprint*/     printRThierarchyInfo(mainmethod); 
-                       /*RTprint*/     }
-               /*RTprint*/     printObjectClassHeirarchy1( );
+#ifdef TYPEINFO_DEBUG_TEST
+               /* test the typeinfo system */
+               typeinfo_test();
+#endif
+               /*class_showmethods(currentThread->group->header.vftbl->class); */
+
+               *threadrootmethod = mainmethod;
+
+
+               /* here we go... */
+               asm_calljavafunction(mainmethod, a, NULL, NULL, NULL);
 
+               /* exception occurred? */
+               if (*exceptionptr)
+                       throw_main_exception();
 
-#ifdef USE_THREADS
-               killThread(currentThread);
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+               joinAllThreads();
+#else
+               killThread(currentThread);
 #endif
-               fprintf(stderr, "still here\n");
+#endif
+
+               /* now exit the JavaVM */
+
+               cacao_exit(0);
        }
 
        /************* If requested, compile all methods ********************/
 
        if (compileall) {
-               class_compile_methods();
+               classinfo *c;
+               methodinfo *m;
+               u4 slot;
+               s4 i;
+
+               /* create all classes found in the classpath */
+               /* XXX currently only works with zip/jar's */
+               create_all_classes();
+
+               /* load and link all classes */
+               for (slot = 0; slot < class_hash.size; slot++) {
+                       c = class_hash.ptr[slot];
+
+                       while (c) {
+                               if (!c->loaded)
+                                       if (!class_load(c))
+                                               throw_main_exception_exit();
+
+                               if (!c->linked)
+                                       if (!class_link(c))
+                                               throw_main_exception_exit();
+
+                               /* compile all class methods */
+                               for (i = 0; i < c->methodscount; i++) {
+                                       m = &(c->methods[i]);
+                                       if (m->jcode) {
+                                               (void) jit_compile(m);
+                                       }
+                               }
+
+                               c = c->hashlink;
+                       }
+               }
        }
 
 
@@ -843,49 +769,136 @@ int main(int argc, char **argv)
 
        if (specificmethodname) {
                methodinfo *m;
-               if (specificsignature)
-                       m = class_findmethod(topclass, 
-                                                                utf_new_char(specificmethodname),
-                                                                utf_new_char(specificsignature));
-               else
-                       m = class_findmethod(topclass, 
-                                                                utf_new_char(specificmethodname), NULL);
-               if (!m) panic ("Specific method not found");
-               (void) jit_compile(m);
+
+               /* create, load and link the main class */
+               mainclass = class_new(utf_new_char(mainstring));
+
+               if (!class_load(mainclass))
+                       throw_main_exception_exit();
+
+               if (!class_link(mainclass))
+                       throw_main_exception_exit();
+
+               if (specificsignature) {
+                       m = class_resolveclassmethod(mainclass,
+                                                                                utf_new_char(specificmethodname),
+                                                                                utf_new_char(specificsignature),
+                                                                                mainclass,
+                                                                                false);
+               } else {
+                       m = class_resolveclassmethod(mainclass,
+                                                                                utf_new_char(specificmethodname),
+                                                                                NULL,
+                                                                                mainclass,
+                                                                                false);
+               }
+
+               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.Runtime.exit(I)V to exit the JavaVM correctly.
+
+*******************************************************************************/
+
+void cacao_exit(s4 status)
+{
+       classinfo *c;
+       methodinfo *m;
+       java_lang_Runtime *rt;
+
+       /* class should already be loaded, but who knows... */
+
+       c = class_new(utf_new_char("java/lang/Runtime"));
 
-/************************************ Shutdown function *********************************
+       if (!class_load(c))
+               throw_main_exception_exit();
+
+       if (!class_link(c))
+               throw_main_exception_exit();
+
+       /* first call Runtime.getRuntime()Ljava.lang.Runtime; */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_new_char("getRuntime"),
+                                                                utf_new_char("()Ljava/lang/Runtime;"),
+                                                                class_java_lang_Object,
+                                                                true);
+
+       if (!m)
+               throw_main_exception_exit();
+
+       rt = (java_lang_Runtime *) asm_calljavafunction(m,
+                                                                                                       (void *) 0,
+                                                                                                       NULL,
+                                                                                                       NULL,
+                                                                                                       NULL);
+
+       /* exception occurred? */
+
+       if (*exceptionptr)
+               throw_main_exception_exit();
+
+       /* then call Runtime.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();
+
+       asm_calljavafunction(m, rt, (void *) 0, NULL, NULL);
+
+       /* this should never happen */
+
+       throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                          "Problems with Runtime.exit(I)V");
+}
+
+
+/*************************** Shutdown function *********************************
 
        Terminates the system immediately without freeing memory explicitly (to be
        used only for abnormal termination)
        
-*****************************************************************************************/
+*******************************************************************************/
 
 void cacao_shutdown(s4 status)
 {
-       if ((pCallgraph >= 1) && (opt_rt)) {
-               printCallgraph(NULL);
-       }
-
-       if ((pClassHeir >= 1) && (opt_rt)) {
-               printf("RTA Information -");
-               printRThierarchyInfo(NULL);
-       }
+       /**** RTAprint ***/
 
-       if (verbose || getcompilingtime || statistics) {
-               log_text ("CACAO terminated by shutdown");
-               if (statistics)
+       if (verbose || getcompilingtime || opt_stat) {
+               log_text("CACAO terminated by shutdown");
+               if (opt_stat)
                        print_stats();
                if (getcompilingtime)
                        print_times();
                mem_usagelog(0);
-               sprintf(logtext, "Exit status: %d\n", (int) status);
-               dolog();
+               dolog("Exit status: %d\n", (int) status);
        }
 
        exit(status);