2005-07-21 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mono / mini / driver.c
index 5090958e825ea380d5e05f05fd9a4dfc511e57b4..08dbd2f6c61338870b55a21e00db35f7e5b3abec 100644 (file)
@@ -5,7 +5,8 @@
  *   Paolo Molaro (lupus@ximian.com)
  *   Dietmar Maurer (dietmar@ximian.com)
  *
- * (C) 2002 Ximian, Inc.
+ * (C) 2002-2003 Ximian, Inc.
+ * (C) 2003-2004 Novell, Inc.
  */
 
 #include <config.h>
@@ -36,6 +37,8 @@
 #include <mono/metadata/verify.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/security-manager.h>
+#include <mono/os/gc_wrapper.h>
 
 #include "mini.h"
 #include "jit.h"
@@ -48,6 +51,11 @@ static FILE *mini_stats_fd = NULL;
 
 static void mini_usage (void);
 
+/* This turns off command line globbing under win32 */
+#ifdef PLATFORM_WIN32
+int _CRT_glob = 0;
+#endif
+
 typedef void (*OptFunc) (const char *p);
 
 /* keep in sync with enum in mini.h */
@@ -76,7 +84,9 @@ opt_names [] = {
        {"fcmov",    "Fast x86 FP compares"},
        {"leaf",     "Leaf procedures optimizations"},
        {"aot",      "Usage of Ahead Of Time compiled code"},
-       {"precomp",  "Precompile all methods before executing Main"}
+       {"precomp",  "Precompile all methods before executing Main"},
+       {"abcrem",   "Array bound checks removal"},     
+       {"ssapre",   "SSA based Partial Redundancy Elimination"}
 };
 
 #define DEFAULT_OPTIMIZATIONS (        \
@@ -85,7 +95,10 @@ opt_names [] = {
        MONO_OPT_BRANCH |       \
        MONO_OPT_LINEARS |      \
        MONO_OPT_INTRINS |  \
-    MONO_OPT_AOT)
+       MONO_OPT_LOOP |  \
+       MONO_OPT_AOT)
+
+#define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP)
 
 static guint32
 parse_optimizations (const char* p)
@@ -137,7 +150,7 @@ parse_optimizations (const char* p)
                                if (invert)
                                        opt = 0;
                                else
-                                       opt = ~(MONO_OPT_SHARED | MONO_OPT_PRECOMP | exclude);
+                                       opt = ~(EXCLUDED_FROM_ALL | exclude);
                                p += 3;
                                if (*p == ',')
                                        p++;
@@ -220,7 +233,10 @@ opt_sets [] = {
        MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP,
        MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_CFOLD,
        MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE,
-       MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS
+       MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS,
+       MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_ABCREM,
+       MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_SSAPRE,
+       MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_ABCREM | MONO_OPT_SHARED
 };
 
 typedef int (*TestMethod) (void);
@@ -265,7 +281,7 @@ mini_regression (MonoImage *image, int verbose, int *total_run) {
        }
 
        /* load the metadata */
-       for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+       for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
                        method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
                mono_class_init (method->klass);
 
@@ -286,34 +302,34 @@ mini_regression (MonoImage *image, int verbose, int *total_run) {
                opt_flags = opt_sets [opt];
                mono_set_defaults (verbose, opt_flags);
                n = opt_descr (opt_flags);
-               g_print ("Test run: image=%s, opts=%s\n", image->name, n);
+               g_print ("Test run: image=%s, opts=%s\n", mono_image_get_filename (image), n);
                g_free (n);
                cfailed = failed = run = code_size = 0;
                comp_time = elapsed = 0.0;
 
                /* fixme: ugly hack - delete all previously compiled methods */
-               for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
-                       method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
-                       method->info = NULL;
-               }
+               g_hash_table_destroy (mono_domain_get ()->jit_trampoline_hash);
+               mono_domain_get ()->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+               g_hash_table_destroy (mono_domain_get ()->jit_code_hash);
+               mono_domain_get ()->jit_code_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
 
                g_timer_start (timer);
                if (mini_stats_fd)
                        fprintf (mini_stats_fd, "[");
-               for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+               for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
                        method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
                        if (strncmp (method->name, "test_", 5) == 0) {
                                expected = atoi (method->name + 5);
                                run++;
                                start_time = g_timer_elapsed (timer, NULL);
                                comp_time -= start_time; 
-                               cfg = mini_method_compile (method, opt_flags, mono_root_domain, 0);
+                               cfg = mini_method_compile (method, opt_flags, mono_get_root_domain (), TRUE, FALSE, 0);
                                comp_time += g_timer_elapsed (timer, NULL);
                                if (cfg) {
                                        if (verbose >= 2)
                                                g_print ("Running '%s' ...\n", method->name);
 #ifdef MONO_USE_AOT_COMPILER
-                                       if ((jinfo = mono_aot_get_method (mono_root_domain, method)))
+                                       if ((jinfo = mono_aot_get_method (mono_get_root_domain (), method)))
                                                func = jinfo->code_start;
                                        else
 #endif
@@ -321,8 +337,7 @@ mini_regression (MonoImage *image, int verbose, int *total_run) {
                                        result = func ();
                                        if (result != expected) {
                                                failed++;
-                                               if (verbose)
-                                                       g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
+                                               g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
                                        }
                                        code_size += cfg->code_len;
                                        mono_destroy_compile (cfg);
@@ -371,12 +386,11 @@ mini_regression_list (int verbose, int count, char *images [])
                        g_warning ("failed to load assembly: %s", images [i]);
                        continue;
                }
-               total += mini_regression (ass->image, verbose, &run);
+               total += mini_regression (mono_assembly_get_image (ass), verbose, &run);
                total_run += run;
-               mono_assembly_close (ass);
        }
        g_print ("Overall results: tests: %d, failed: %d, opt combinations: %d (pass: %.2f%%)\n", 
-               total_run, total, G_N_ELEMENTS (opt_sets), 100.0*(total_run-total)/total_run);
+               total_run, total, (int)G_N_ELEMENTS (opt_sets), 100.0*(total_run-total)/total_run);
        return total;
 }
 
@@ -385,7 +399,7 @@ enum {
        DO_REGRESSION,
        DO_COMPILE,
        DO_EXEC,
-       DO_DRAW,
+       DO_DRAW
 };
 
 typedef struct CompileAllThreadArgs {
@@ -398,15 +412,29 @@ compile_all_methods_thread_main (CompileAllThreadArgs *args)
 {
        MonoAssembly *ass = args->ass;
        int verbose = args->verbose;
-       MonoImage *image = ass->image;
+       MonoImage *image = mono_assembly_get_image (ass);
        MonoMethod *method;
+       MonoCompile *cfg;
        int i, count = 0;
 
-       for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
-               method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
-               if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
+       for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
+               guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
+               MonoMethodSignature *sig;
+
+               if (mono_metadata_has_generic_params (image, token))
                        continue;
-               if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
+
+               method = mono_get_method (image, token, NULL);
+               if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+                   (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+                   (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
+                   (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
+                       continue;
+
+               if (method->klass->generic_container)
+                       continue;
+               sig = mono_method_signature (method);
+               if (sig->has_type_parameters)
                        continue;
 
                count++;
@@ -415,7 +443,8 @@ compile_all_methods_thread_main (CompileAllThreadArgs *args)
                        g_print ("Compiling %d %s\n", count, desc);
                        g_free (desc);
                }
-               mono_compile_method (method);
+               cfg = mini_method_compile (method, DEFAULT_OPTIMIZATIONS, mono_get_root_domain (), FALSE, FALSE, 0);
+               mono_destroy_compile (cfg);
        }
 
 }
@@ -448,12 +477,12 @@ compile_all_methods (MonoAssembly *ass, int verbose)
 int 
 mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
 {
-       MonoImage *image = assembly->image;
+       MonoImage *image = mono_assembly_get_image (assembly);
        MonoMethod *method;
        guint32 entry = mono_image_get_entry_point (image);
 
        if (!entry) {
-               g_print ("Assembly '%s' doesn't have an entry point.\n", image->name);
+               g_print ("Assembly '%s' doesn't have an entry point.\n", mono_image_get_filename (image));
                /* FIXME: remove this silly requirement. */
                mono_environment_exitcode_set (1);
                return 1;
@@ -471,6 +500,7 @@ typedef struct
        int argc;
        char **argv;
        guint32 opts;
+       char *aot_options;
 } MainThreadArgs;
 
 static void main_thread_handler (gpointer user_data)
@@ -485,7 +515,7 @@ static void main_thread_handler (gpointer user_data)
        }
 
        if (mono_compile_aot) {
-               int res = mono_compile_assembly (assembly, main_args->opts);
+               int res = mono_compile_assembly (assembly, main_args->opts, main_args->aot_options);
                printf ("AOT RESULT %d\n", res);
        } else {
                /* 
@@ -500,51 +530,66 @@ static void main_thread_handler (gpointer user_data)
 }
 
 static void
-mini_usage (void)
+mini_usage_jitdeveloper (void)
 {
        int i;
+       
+       fprintf (stdout,
+                "Runtime and JIT debugging options:\n"
+                "    --breakonex            Inserts a breakpoint on exceptions\n"
+                "    --break METHOD         Inserts a breakpoint at METHOD entry\n"
+                "    --compile METHOD       Just compile METHOD in assembly\n"
+                "    --compile-all          Compiles all the methods in the assembly\n"
+                "    --ncompile N           Number of times to compile METHOD (default: 1)\n"
+                "    --print-vtable         Print the vtable of all used classes\n"
+                "    --regression           Runs the regression test contained in the assembly\n"
+                "    --statfile FILE        Sets the stat file to FILE\n"
+                "    --stats                Print statistics about the JIT operations\n"
+                "\n"
+                "Other options:\n" 
+                "    --graph[=TYPE] METHOD  Draws a graph of the specified method:\n");
+       
+       for (i = 0; i < G_N_ELEMENTS (graph_names); ++i) {
+               fprintf (stdout, "                           %-10s %s\n", graph_names [i].name, graph_names [i].desc);
+       }
+}
 
-       fprintf (stderr,
-               "Usage is: mono [options] assembly\n\n"
-               "Runtime and JIT debugging:\n"
-               "    --compile METHOD       Just compile METHOD in assembly\n"
-               "    --ncompile N           Number of times to compile METHOD (default: 1)\n"
-               "    --regression           Runs the regression test contained in the assembly\n"
-               "    --print-vtable         Print the vtable of all used classes\n"
-               "    --trace[=EXPR]         Enable tracing, use --help-trace for details\n"
-               "    --compile-all          Compiles all the methods in the assembly\n"
-               "    --breakonex            Inserts a breakpoint on exceptions\n"
-               "    --break METHOD         Inserts a breakpoint at METHOD entry\n"
-               "    --debug                Enable debugging support\n"
-           "    --stats                Print statistics about the JIT operations\n"
+static void
+mini_usage_list_opt (void)
+{
+       int i;
+       
+       for (i = 0; i < G_N_ELEMENTS (opt_names); ++i)
+               fprintf (stdout, "                           %-10s %s\n", opt_names [i].name, opt_names [i].desc);
+}
+
+static void
+mini_usage (void)
+{
+       fprintf (stdout,
+               "Usage is: mono [options] program [program-options]\n"
                "\n"
                "Development:\n"
-               "    --statfile FILE        Sets the stat file to FILE\n"
                "    --aot                  Compiles the assembly to native code\n"
+               "    --debug                Enable debugging support\n"
                "    --profile[=profiler]   Runs in profiling mode with the specified profiler module\n"
-               "    --graph[=TYPE] METHOD  Draws a graph of the specified method:\n");
-       
-       for (i = 0; i < G_N_ELEMENTS (graph_names); ++i) {
-               fprintf (stderr, "                           %-10s %s\n", graph_names [i].name, graph_names [i].desc);
-       }
-
-       fprintf (stderr,
+               "    --trace[=EXPR]         Enable tracing, use --help-trace for details\n"
+               "    --help-devel           Shows more options available to developers\n"
                "\n"
                "Runtime:\n"
                "    --config FILE          Loads FILE as the Mono config\n"
                "    --verbose, -v          Increases the verbosity level\n"
                "    --help, -h             Show usage information\n"
                "    --version, -V          Show version information\n"
-               "    --optimize=OPT         Turns on a specific optimization:\n");
-
-       for (i = 0; i < G_N_ELEMENTS (opt_names); ++i)
-               fprintf (stderr, "                           %-10s %s\n", opt_names [i].name, opt_names [i].desc);
+               "    --optimize=OPT         Turns on or off a specific optimization\n"
+               "                           Use --list-opt to get a list of optimizations\n"
+               "    --security             Turns on the security manager (unsupported, default is off)\n");
 }
 
 static void
 mini_trace_usage (void)
 {
-       fprintf (stderr,
+       fprintf (stdout,
                 "Tracing options:\n"
                 "   --trace[=EXPR]        Trace every call, optional EXPR controls the scope\n"
                 "\n"
@@ -557,9 +602,41 @@ mini_trace_usage (void)
                 "    N:Namespace          Specifies a namespace\n"
                 "    T:Type               Specifies a type\n"
                 "    +EXPR                Includes expression\n"
-                "    -EXPR                Excludes expression\n");
+                "    -EXPR                Excludes expression\n"
+                "    disabled             Don't print any output until toggled via SIGUSR2\n");
 }
 
+static const char *info = ""
+#ifdef HAVE_KW_THREAD
+       "\tTLS:           __thread\n"
+#else
+       "\tTLS:           normal\n"
+#endif /* HAVE_KW_THREAD */
+#ifdef HAVE_BOEHM_GC
+#ifdef USE_INCLUDED_LIBGC
+       "\tGC:            Included Boehm (with typed GC)\n"
+#else
+#if HAVE_GC_GCJ_MALLOC
+       "\tGC:            System Boehm (with typed GC)\n"
+#else
+       "\tGC:            System Boehm (no typed GC available)\n"
+#endif
+#endif
+#else
+       "\tGC:            none\n"
+#endif /* HAVE_BOEHM_GC */
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
+    "\tSIGSEGV      : altstack\n"
+#else
+    "\tSIGSEGV      : normal\n"
+#endif
+#ifdef HAVE_ICU
+       "\tGlobalization: ICU (unsupported, don't use)\n"
+#else
+       "\tGlobalization: normal\n"
+#endif /* HAVE_ICU */
+       "";
+
 int
 mono_main (int argc, char* argv[])
 {
@@ -576,12 +653,32 @@ mono_main (int argc, char* argv[])
        guint32 opt, action = DO_EXEC;
        MonoGraphOptions mono_graph_options = 0;
        int mini_verbose = 0;
+       gboolean enable_profile = FALSE;
        char *trace_options = NULL;
+       char *profile_options = NULL;
+       char *aot_options = NULL;
 
        setlocale (LC_ALL, "");
+
+       if (mono_running_on_valgrind () && getenv ("MONO_VALGRIND_LEAK_CHECK")) {
+               GMemVTable mem_vtable;
+
+               /* 
+                * Instruct glib to use the system allocation functions so valgrind
+                * can track the memory allocated by the g_... functions.
+                */
+               memset (&mem_vtable, 0, sizeof (mem_vtable));
+               mem_vtable.malloc = malloc;
+               mem_vtable.realloc = realloc;
+               mem_vtable.free = free;
+               mem_vtable.calloc = calloc;
+
+               g_mem_set_vtable (&mem_vtable);
+       }
+
        g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
        g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
-       
+
        opt = parse_optimizations (NULL);
 
        for (i = 1; i < argc; ++i) {
@@ -592,7 +689,21 @@ mono_main (int argc, char* argv[])
                } else if (strcmp (argv [i], "--verbose") == 0 || strcmp (argv [i], "-v") == 0) {
                        mini_verbose++;
                } else if (strcmp (argv [i], "--version") == 0 || strcmp (argv [i], "-V") == 0) {
-                       g_print ("Mono JIT compiler version %s, (C) 2002, 2003 Ximian, Inc.\n", VERSION);
+                       g_print ("Mono JIT compiler version %s, (C) 2002-2005 Novell, Inc and Contributors. www.mono-project.com\n", VERSION);
+                       g_print (info);
+                       if (mini_verbose) {
+                               const char *cerror;
+                               const char *clibpath;
+                               mono_init ("mono");
+                               cerror = mono_check_corlib_version ();
+                               clibpath = mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown";
+                               if (cerror) {
+                                       g_print ("The currently installed mscorlib doesn't match this runtime version.\n");
+                                       g_print ("The error is: %s\n", cerror);
+                                       g_print ("mscorlib.dll loaded at: %s\n", clibpath);
+                                       return 1;
+                               }
+                       }
                        return 0;
                } else if (strcmp (argv [i], "--help") == 0 || strcmp (argv [i], "-h") == 0) {
                        mini_usage ();
@@ -600,51 +711,100 @@ mono_main (int argc, char* argv[])
                } else if (strcmp (argv [i], "--help-trace") == 0){
                        mini_trace_usage ();
                        return 0;
+               } else if (strcmp (argv [i], "--help-devel") == 0){
+                       mini_usage_jitdeveloper ();
+                       return 0;
+               } else if (strcmp (argv [i], "--list-opt") == 0){
+                       mini_usage_list_opt ();
+                       return 0;
                } else if (strncmp (argv [i], "--statfile", 10) == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --statfile requires a filename argument\n");
+                               return 1;
+                       }
                        mini_stats_fd = fopen (argv [++i], "w+");
                } else if (strncmp (argv [i], "--optimize=", 11) == 0) {
                        opt = parse_optimizations (argv [i] + 11);
                } else if (strncmp (argv [i], "-O=", 3) == 0) {
                        opt = parse_optimizations (argv [i] + 3);
                } else if (strcmp (argv [i], "--config") == 0) {
+                       if (i +1 >= argc){
+                               fprintf (stderr, "error: --config requires a filename argument\n");
+                               return 1;
+                       }
                        config_file = argv [++i];
                } else if (strcmp (argv [i], "--ncompile") == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --ncompile requires an argument\n");
+                               return 1;
+                       }
                        count = atoi (argv [++i]);
                        action = DO_BENCH;
                } else if (strcmp (argv [i], "--trace") == 0) {
-                       trace_options = "";
+                       trace_options = (char*)"";
                } else if (strncmp (argv [i], "--trace=", 8) == 0) {
                        trace_options = &argv [i][8];
                } else if (strcmp (argv [i], "--breakonex") == 0) {
                        mono_break_on_exc = TRUE;
                } else if (strcmp (argv [i], "--break") == 0) {
+                       if (i+1 >= argc){
+                               fprintf (stderr, "Missing method name in --break command line option\n");
+                               return 1;
+                       }
+                       
                        if (!mono_debugger_insert_breakpoint (argv [++i], FALSE))
-                               g_error ("Invalid method name '%s'", argv [i]);
+                               fprintf (stderr, "Error: invalid method name '%s'\n", argv [i]);
                } else if (strcmp (argv [i], "--print-vtable") == 0) {
                        mono_print_vtable = TRUE;
                } else if (strcmp (argv [i], "--stats") == 0) {
+                       mono_stats.enabled = TRUE;
                        mono_jit_stats.enabled = TRUE;
+#ifndef DISABLE_AOT
                } else if (strcmp (argv [i], "--aot") == 0) {
                        mono_compile_aot = TRUE;
+               } else if (strncmp (argv [i], "--aot=", 6) == 0) {
+                       mono_compile_aot = TRUE;
+                       aot_options = &argv [i][6];
+#endif
                } else if (strcmp (argv [i], "--compile-all") == 0) {
                        action = DO_COMPILE;
                } else if (strcmp (argv [i], "--profile") == 0) {
-                       mono_profiler_load (NULL);
+                       enable_profile = TRUE;
+                       profile_options = NULL;
                } else if (strncmp (argv [i], "--profile=", 10) == 0) {
-                       mono_profiler_load (argv [i] + 10);
+                       enable_profile = TRUE;
+                       profile_options = argv [i] + 10;
                } else if (strcmp (argv [i], "--compile") == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --compile option requires a method name argument\n");
+                               return 1;
+                       }
+                       
                        mname = argv [++i];
                        action = DO_BENCH;
                } else if (strncmp (argv [i], "--graph=", 8) == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --graph option requires a method name argument\n");
+                               return 1;
+                       }
+                       
                        mono_graph_options = mono_parse_graph_options (argv [i] + 8);
                        mname = argv [++i];
                        action = DO_DRAW;
                } else if (strcmp (argv [i], "--graph") == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --graph option requires a method name argument\n");
+                               return 1;
+                       }
+                       
                        mname = argv [++i];
                        mono_graph_options = MONO_GRAPH_CFG;
                        action = DO_DRAW;
                } else if (strcmp (argv [i], "--debug") == 0) {
                        enable_debugging = TRUE;
+               } else if (strcmp (argv [i], "--security") == 0) {
+                       mono_use_security_manager = TRUE;
+                       mono_activate_security_manager ();
                } else {
                        fprintf (stderr, "Unknown command line option: '%s'\n", argv [i]);
                        return 1;
@@ -660,6 +820,22 @@ mono_main (int argc, char* argv[])
                g_set_prgname (argv[i]);
        }
 
+       if (enable_profile) {
+               /* Needed because of TLS accesses in mono_profiler_load () */
+               MONO_GC_PRE_INIT ();
+               mono_profiler_load (profile_options);
+       }
+
+       if (trace_options != NULL){
+               /* 
+                * Need to call this before mini_init () so we can trace methods 
+                * compiled there too.
+                */
+               mono_jit_trace_calls = mono_trace_parse_options (trace_options);
+               if (mono_jit_trace_calls == NULL)
+                       exit (1);
+       }
+
        mono_set_defaults (mini_verbose, opt);
        domain = mini_init (argv [i]);
        
@@ -706,8 +882,15 @@ mono_main (int argc, char* argv[])
                break;
        }
 
-       if (enable_debugging)
-               mono_debug_init (domain, MONO_DEBUG_FORMAT_MONO);
+       if (enable_debugging) {
+               mono_debug_init (MONO_DEBUG_FORMAT_MONO);
+               mono_debug_init_1 (domain);
+       }
+
+       /* Parse gac loading options before loading assemblies. */
+       if (mono_compile_aot || action == DO_EXEC) {
+               mono_config_parse (config_file);
+       }
 
        assembly = mono_assembly_open (aname, NULL);
        if (!assembly) {
@@ -716,41 +899,42 @@ mono_main (int argc, char* argv[])
                return 2;
        }
 
-       if (trace_options != NULL){
-               mono_jit_trace_calls = mono_trace_parse_options (assembly, trace_options);
-               if (mono_jit_trace_calls == NULL)
-                       exit (1);
-       }
+       if (trace_options != NULL)
+               mono_trace_set_assembly (assembly);
 
        if (enable_debugging)
                mono_debug_init_2 (assembly);
 
        if (mono_compile_aot || action == DO_EXEC) {
-               guint32 error;
+               const char *error;
 
-               mono_config_parse (config_file);
                //mono_set_rootdir ();
 
-               error = mono_verify_corlib ();
-               if (error) {
-                       fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
-                       exit (1);
-               }
-
                error = mono_check_corlib_version ();
                if (error) {
                        fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
-                       fprintf (stderr, "Download a newer corlib at http://go-mono/daily.\n");
+                       fprintf (stderr, "Download a newer corlib or a newer runtime at http://www.go-mono.com/daily.\n");
                        exit (1);
                }
 
+#ifdef PLATFORM_WIN32
+               /* Detach console when executing IMAGE_SUBSYSTEM_WINDOWS_GUI on win32 */
+               if (!mono_compile_aot && ((MonoCLIImageInfo*)(mono_assembly_get_image (assembly)->image_info))->cli_header.nt.pe_subsys_required == IMAGE_SUBSYSTEM_WINDOWS_GUI)
+                       FreeConsole ();
+#endif
+
                main_args.domain = domain;
                main_args.file = aname;         
                main_args.argc = argc - i;
                main_args.argv = argv + i;
                main_args.opts = opt;
-            
+               main_args.aot_options = aot_options;
+#if RUN_IN_SUBTHREAD
                mono_runtime_exec_managed_code (domain, main_thread_handler, &main_args);
+#else
+               main_thread_handler (&main_args);
+               mono_thread_manage ();
+#endif
                mini_cleanup (domain);
 
                /* Look up return value from System.Environment.ExitCode */
@@ -767,7 +951,7 @@ mono_main (int argc, char* argv[])
                mini_cleanup (domain);
                return 3;
        }
-       method = mono_method_desc_search_in_image (desc, assembly->image);
+       method = mono_method_desc_search_in_image (desc, mono_assembly_get_image (assembly));
        if (!method) {
                g_print ("Cannot find method %s\n", mname);
                mini_cleanup (domain);
@@ -795,7 +979,14 @@ mono_main (int argc, char* argv[])
                        break;
                }
 
-               cfg = mini_method_compile (method, opt, mono_root_domain, part);
+               if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+                       (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
+                       MonoMethod *nm;
+                       nm = mono_marshal_get_native_wrapper (method);
+                       cfg = mini_method_compile (nm, opt, mono_get_root_domain (), FALSE, FALSE, part);
+               }
+               else
+                       cfg = mini_method_compile (method, opt, mono_get_root_domain (), FALSE, FALSE, part);
                if ((mono_graph_options & MONO_GRAPH_CFG_SSA) && !(cfg->comp_done & MONO_COMP_SSA)) {
                        g_warning ("no SSA info available (use -O=deadce)");
                        return 1;
@@ -827,7 +1018,7 @@ mono_main (int argc, char* argv[])
                                opt = opt_sets [i];
                                g_timer_start (timer);
                                for (j = 0; j < count; ++j) {
-                                       cfg = mini_method_compile (method, opt, mono_root_domain, 0);
+                                       cfg = mini_method_compile (method, opt, mono_get_root_domain (), FALSE, FALSE, 0);
                                        mono_destroy_compile (cfg);
                                }
                                g_timer_stop (timer);
@@ -850,12 +1041,12 @@ mono_main (int argc, char* argv[])
                                        (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
                                        method = mono_marshal_get_native_wrapper (method);
 
-                               cfg = mini_method_compile (method, opt, mono_root_domain, 0);
+                               cfg = mini_method_compile (method, opt, mono_get_root_domain (), FALSE, FALSE, 0);
                                mono_destroy_compile (cfg);
                        }
                }
        } else {
-               cfg = mini_method_compile (method, opt, mono_root_domain, 0);
+               cfg = mini_method_compile (method, opt, mono_get_root_domain (), FALSE, FALSE, 0);
                mono_destroy_compile (cfg);
        }
 
@@ -874,5 +1065,3 @@ mono_jit_cleanup (MonoDomain *domain)
 {
        mini_cleanup (domain);
 }
-
-