Update copyrights
[mono.git] / mono / mini / driver.c
index fcebec33f3c362231137bd03922acf9ccd04d8ae..0683946becaba47ec5da70ab9d3f536c1d805802 100644 (file)
@@ -47,7 +47,6 @@
 #include <mono/metadata/coree.h>
 #include <mono/metadata/attach.h>
 #include "mono/utils/mono-counters.h"
-#include <mono/utils/gc_wrapper.h>
 
 #include "mini.h"
 #include "jit.h"
 #include <ctype.h>
 #include <locale.h>
 #include "version.h"
+#include "debugger-agent.h"
 
 static FILE *mini_stats_fd = NULL;
 
 static void mini_usage (void);
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
 /* Need this to determine whether to detach console */
 #include <mono/metadata/cil-coff.h>
 /* This turns off command line globbing under win32 */
@@ -114,6 +114,12 @@ opt_funcs [sizeof (int) * 8] = {
        NULL
 };
 
+#ifdef __native_client_codegen__
+extern gint8 nacl_align_byte;
+#endif
+#ifdef __native_client__
+extern char *nacl_mono_path;
+#endif
 
 #define DEFAULT_OPTIMIZATIONS (        \
        MONO_OPT_PEEPHOLE |     \
@@ -132,7 +138,7 @@ opt_funcs [sizeof (int) * 8] = {
        MONO_OPT_SIMD | \
        MONO_OPT_AOT)
 
-#define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP)
+#define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP | MONO_OPT_UNSAFE)
 
 static guint32
 parse_optimizations (const char* p)
@@ -214,6 +220,9 @@ parse_debug_options (const char* p)
                } else if (!strncmp (p, "mdb-optimizations", 17)) {
                        opt->mdb_optimizations = TRUE;
                        p += 17;
+               } else if (!strncmp (p, "gdb", 3)) {
+                       opt->gdb = TRUE;
+                       p += 3;
                } else {
                        fprintf (stderr, "Invalid debug option `%s', use --help-debug for details\n", p);
                        return FALSE;
@@ -307,6 +316,7 @@ opt_sets [] = {
        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_TAILC,
        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_SSA,
        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_EXCEPTION,
        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_EXCEPTION | MONO_OPT_CMOV,
@@ -855,6 +865,14 @@ compile_all_methods_thread_main (CompileAllThreadArgs *args)
                if (method->klass->generic_container)
                        continue;
                sig = mono_method_signature (method);
+               if (!sig) {
+                       char * desc = mono_method_full_name (method, TRUE);
+                       g_print ("Could not retrieve method signature for %s\n", desc);
+                       g_free (desc);
+                       fail_count ++;
+                       continue;
+               }
+
                if (sig->has_type_parameters)
                        continue;
 
@@ -1071,7 +1089,7 @@ mini_usage_jitdeveloper (void)
                 "    --stats                Print statistics about the JIT operations\n"
                 "    --wapi=hps|semdel|seminfo IO-layer maintenance\n"
                 "    --inject-async-exc METHOD OFFSET Inject an asynchronous exception at METHOD\n"
-                "    --verify-all           Run the verifier on all methods\n"
+                "    --verify-all           Run the verifier on all assemblies and methods\n"
                 "    --full-aot             Avoid JITting any code\n"
                 "    --agent=ASSEMBLY[:ARG] Loads the specific agent assembly and executes its Main method with the given argument before loading the main assembly.\n"
                 "    --no-x86-stack-align   Don't align stack on x86\n"
@@ -1100,11 +1118,16 @@ mini_usage (void)
                "Usage is: mono [options] program [program-options]\n"
                "\n"
                "Development:\n"
-               "    --aot                  Compiles the assembly to native code\n"
+               "    --aot[=<options>]      Compiles the assembly to native code\n"
                "    --debug[=<options>]    Enable debugging support, use --help-debug for details\n"
+               "    --debugger-agent=options Enable the debugger agent\n"
                "    --profile[=profiler]   Runs in profiling mode with the specified profiler module\n"
                "    --trace[=EXPR]         Enable tracing, use --help-trace for details\n"
+               "    --jitmap               Output a jit method map to /tmp/perf-PID.map\n"
                "    --help-devel           Shows more options available to developers\n"
+#ifdef __native_client_codegen__
+               "    --nacl-align-mask-off  Turn off Native Client 32-byte alignment mask (for debug only)\n"
+#endif
                "\n"
                "Runtime:\n"
                "    --config FILE          Loads FILE as the Mono config\n"
@@ -1118,6 +1141,11 @@ mini_usage (void)
                "                           mode is one of cas, core-clr, verifiable or validil\n"
                "    --attach=OPTIONS       Pass OPTIONS to the attach agent in the runtime.\n"
                "                           Currently the only supported option is 'disable'.\n"
+               "    --llvm, --nollvm       Controls whenever the runtime uses LLVM to compile code.\n"
+               "    --gc=[sgen,boehm]      Select SGen or Boehm GC (runs mono or mono-sgen)\n"
+#ifdef HOST_WIN32
+               "    --mixed-mode           Enable mixed-mode image support.\n"
+#endif
          );
 }
 
@@ -1170,7 +1198,6 @@ static const char info[] =
 #else
        "\tTLS:           normal\n"
 #endif /* HAVE_KW_THREAD */
-       "\tGC:            " USED_GC_NAME "\n"
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
     "\tSIGSEGV:       altstack\n"
 #else
@@ -1178,11 +1205,34 @@ static const char info[] =
 #endif
 #ifdef HAVE_EPOLL
     "\tNotifications: epoll\n"
+#elif defined(HAVE_KQUEUE)
+    "\tNotification:  kqueue\n"
 #else
     "\tNotification:  Thread + polling\n"
 #endif
         "\tArchitecture:  " ARCHITECTURE "\n"
        "\tDisabled:      " DISABLED_FEATURES "\n"
+       "\tMisc:          "
+#ifdef MONO_SMALL_CONFIG
+       "smallconfig "
+#endif
+#ifdef MONO_BIG_ARRAYS
+       "bigarrays "
+#endif
+#ifdef MONO_DEBUGGER_SUPPORTED
+       "debugger "
+#endif
+#if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && !defined(DISABLE_SOFT_DEBUG)
+       "softdebug "
+#endif
+               "\n"
+#ifdef MONO_ARCH_LLVM_SUPPORTED
+#ifdef ENABLE_LLVM
+       "\tLLVM:          yes(" LLVM_VERSION ")\n"
+#else
+       "\tLLVM:          supported, not enabled.\n"
+#endif
+#endif
        "";
 
 #ifndef MONO_ARCH_AOT_SUPPORTED
@@ -1191,10 +1241,11 @@ static const char info[] =
 #define error_if_aot_unsupported()
 #endif
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
 BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved)
 {
-       if (!GC_DllMain (module_handle, reason, reserved))
+       int dummy;
+       if (!mono_gc_dllmain (module_handle, reason, reserved))
                return FALSE;
 
        switch (reason)
@@ -1206,11 +1257,82 @@ BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved)
                if (coree_module_handle)
                        FreeLibrary (coree_module_handle);
                break;
+       case DLL_THREAD_ATTACH:
+               mono_thread_info_attach (&dummy);
+               break;
+       case DLL_THREAD_DETACH:
+               mono_thread_info_dettach ();
+               break;
+       
        }
        return TRUE;
 }
 #endif
 
+static gboolean enable_debugging;
+
+/*
+ * mono_jit_parse_options:
+ *
+ *   Process the command line options in ARGV as done by the runtime executable. 
+ * This should be called before mono_jit_init ().
+ */
+void
+mono_jit_parse_options (int argc, char * argv[])
+{
+       int i;
+
+       /* 
+        * Some options have no effect here, since they influence the behavior of 
+        * mono_main ().
+        */
+
+       /* FIXME: Avoid code duplication */
+       for (i = 0; i < argc; ++i) {
+               if (argv [i] [0] != '-')
+                       break;
+               if (strncmp (argv [i], "--debugger-agent=", 17) == 0) {
+                       MonoDebugOptions *opt = mini_get_debug_options ();
+
+                       mono_debugger_agent_parse_options (argv [i] + 17);
+                       opt->mdb_optimizations = TRUE;
+                       enable_debugging = TRUE;
+               } else if (!strcmp (argv [i], "--soft-breakpoints")) {
+                       MonoDebugOptions *opt = mini_get_debug_options ();
+
+                       opt->soft_breakpoints = TRUE;
+                       opt->explicit_null_checks = TRUE;
+               } else {
+                       fprintf (stderr, "Unsupported command line option: '%s'\n", argv [i]);
+                       exit (1);
+               }
+       }
+}
+
+static void
+mono_set_use_smp (int use_smp)
+{
+#if HAVE_SCHED_SETAFFINITY
+       if (!use_smp) {
+               unsigned long proc_mask = 1;
+#ifdef GLIBC_BEFORE_2_3_4_SCHED_SETAFFINITY
+               sched_setaffinity (getpid(), (gpointer)&proc_mask);
+#else
+               sched_setaffinity (getpid(), sizeof (unsigned long), (gpointer)&proc_mask);
+#endif
+       }
+#endif
+}
+       
+
+/**
+ * mono_main:
+ * @argc: number of arguments in the argv array
+ * @argv: array of strings containing the startup arguments
+ *
+ * Launches the Mono JIT engine and parses all the command line options
+ * in the same way that the mono command line VM would.
+ */
 int
 mono_main (int argc, char* argv[])
 {
@@ -1224,7 +1346,6 @@ mono_main (int argc, char* argv[])
        const char* aname, *mname = NULL;
        char *config_file = NULL;
        int i, count = 1;
-       int enable_debugging = FALSE;
        guint32 opt, action = DO_EXEC;
        MonoGraphOptions mono_graph_options = 0;
        int mini_verbose = 0;
@@ -1237,16 +1358,25 @@ mono_main (int argc, char* argv[])
        char *attach_options = NULL;
 #ifdef MONO_JIT_INFO_TABLE_TEST
        int test_jit_info_table = FALSE;
+#endif
+#ifdef HOST_WIN32
+       int mixed_mode = FALSE;
+#endif
+
+#ifdef MOONLIGHT
+#ifndef HOST_WIN32
+       /* stdout defaults to block buffering if it's not writing to a terminal, which
+        * happens with our test harness: we redirect stdout to capture it. Force line
+        * buffering in all cases. */
+       setlinebuf (stdout);
+#endif
 #endif
 
        setlocale (LC_ALL, "");
 
-#if HAVE_SCHED_SETAFFINITY
-       if (getenv ("MONO_NO_SMP")) {
-               unsigned long proc_mask = 1;
-               sched_setaffinity (getpid(), sizeof (unsigned long), (gpointer)&proc_mask);
-       }
-#endif
+       if (getenv ("MONO_NO_SMP"))
+               mono_set_use_smp (FALSE);
+       
        if (!g_thread_supported ())
                g_thread_init (NULL);
 
@@ -1280,9 +1410,14 @@ mono_main (int argc, char* argv[])
                        mini_verbose++;
                } else if (strcmp (argv [i], "--version") == 0 || strcmp (argv [i], "-V") == 0) {
                        char *build = mono_get_runtime_build_info ();
-                       g_print ("Mono JIT compiler version %s (%s)\nCopyright (C) 2002-2008 Novell, Inc and Contributors. www.mono-project.com\n", VERSION, build);
+                       char *gc_descr;
+
+                       g_print ("Mono JIT compiler version %s\nCopyright (C) 2002-2011 Novell, Inc, Xamarin, Inc and Contributors. www.mono-project.com\n", build);
                        g_free (build);
                        g_print (info);
+                       gc_descr = mono_gc_get_description ();
+                       g_print ("\tGC:            %s\n", gc_descr);
+                       g_free (gc_descr);
                        if (mini_verbose) {
                                const char *cerror;
                                const char *clibpath;
@@ -1322,12 +1457,43 @@ mono_main (int argc, char* argv[])
                        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], "--gc=sgen") == 0) {
+                       if (!strcmp (mono_gc_get_gc_name (), "boehm")) {
+                               GString *path = g_string_new (argv [0]);
+                               g_string_append (path, "-sgen");
+                               argv [0] = path->str;
+#ifdef HAVE_EXECVP
+                               execvp (path->str, argv);
+#else
+                               fprintf (stderr, "Error: --gc=<NAME> option not supported on this platform.\n");
+#endif
+                       }
+               } else if (strcmp (argv [i], "--gc=boehm") == 0) {
+                       if (!strcmp (mono_gc_get_gc_name (), "sgen")) {
+                               char *copy = g_strdup (argv [0]);
+                               char *p = strstr (copy, "-sgen");
+                               if (p == NULL){
+                                       fprintf (stderr, "Error, this process is not named mono-sgen and the command line option --boehm was passed");
+                                       exit (1);
+                               }
+                               *p = 0;
+                               argv [0] = p;
+#ifdef HAVE_EXECVP
+                               execvp (p, argv);
+#else
+                               fprintf (stderr, "Error: --gc=<NAME> option not supported on this platform.\n");
+#endif
+                       }
                } 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];
+#ifdef HOST_WIN32
+               } else if (strcmp (argv [i], "--mixed-mode") == 0) {
+                       mixed_mode = TRUE;
+#endif
                } else if (strcmp (argv [i], "--ncompile") == 0) {
                        if (i + 1 >= argc){
                                fprintf (stderr, "error: --ncompile requires an argument\n");
@@ -1394,6 +1560,8 @@ mono_main (int argc, char* argv[])
                        action = DO_COMPILE;
                } else if (strncmp (argv [i], "--runtime=", 10) == 0) {
                        forced_version = &argv [i][10];
+               } else if (strcmp (argv [i], "--jitmap") == 0) {
+                       mono_enable_jit_map ();
                } else if (strcmp (argv [i], "--profile") == 0) {
                        enable_profile = TRUE;
                        profile_options = NULL;
@@ -1438,6 +1606,12 @@ mono_main (int argc, char* argv[])
                        enable_debugging = TRUE;
                        if (!parse_debug_options (argv [i] + 8))
                                return 1;
+               } else if (strncmp (argv [i], "--debugger-agent=", 17) == 0) {
+                       MonoDebugOptions *opt = mini_get_debug_options ();
+
+                       mono_debugger_agent_parse_options (argv [i] + 17);
+                       opt->mdb_optimizations = TRUE;
+                       enable_debugging = TRUE;
                } else if (strcmp (argv [i], "--security") == 0) {
                        mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE);
                        mono_security_set_mode (MONO_SECURITY_MODE_CAS);
@@ -1465,9 +1639,7 @@ mono_main (int argc, char* argv[])
                                return 1;
                        }
                } else if (strcmp (argv [i], "--desktop") == 0) {
-#if defined (HAVE_BOEHM_GC)
-                       GC_dont_expand = 1;
-#endif
+                       mono_gc_set_desktop_mode ();
                        /* Put desktop-specific optimizations here */
                } else if (strcmp (argv [i], "--server") == 0){
                        /* Put server-specific optimizations here */
@@ -1489,6 +1661,22 @@ mono_main (int argc, char* argv[])
 #ifdef MONO_JIT_INFO_TABLE_TEST
                } else if (strcmp (argv [i], "--test-jit-info-table") == 0) {
                        test_jit_info_table = TRUE;
+#endif
+               } else if (strcmp (argv [i], "--llvm") == 0) {
+#ifndef MONO_ARCH_LLVM_SUPPORTED
+                       fprintf (stderr, "Mono Warning: --llvm not supported on this platform.\n");
+#else
+                       mono_use_llvm = TRUE;
+#endif
+               } else if (strcmp (argv [i], "--nollvm") == 0){
+                       mono_use_llvm = FALSE;
+#ifdef __native_client_codegen__
+               } else if (strcmp (argv [i], "--nacl-align-mask-off") == 0){
+                       nacl_align_byte = -1; /* 0xff */
+#endif
+#ifdef __native_client__
+               } else if (strcmp (argv [i], "--nacl-mono-path") == 0){
+                       nacl_mono_path = g_strdup(argv[++i]);
 #endif
                } else {
                        fprintf (stderr, "Unknown command line option: '%s'\n", argv [i]);
@@ -1496,6 +1684,13 @@ mono_main (int argc, char* argv[])
                }
        }
 
+#ifdef __native_client_codegen__
+       if (getenv ("MONO_NACL_ALIGN_MASK_OFF"))
+       {
+               nacl_align_byte = -1; /* 0xff */
+       }
+#endif
+
        if (!argv [i]) {
                mini_usage ();
                return 1;
@@ -1506,9 +1701,13 @@ mono_main (int argc, char* argv[])
 
 #ifdef MONO_CROSS_COMPILE
        if (!mono_compile_aot) {
-                  fprintf (stderr, "This mono runtime is compiled for cross-compiling. Only the --aot option is supported.");
+                  fprintf (stderr, "This mono runtime is compiled for cross-compiling. Only the --aot option is supported.\n");
                   exit (1);
        }
+#if SIZEOF_VOID_P == 8 && defined(TARGET_ARM)
+       fprintf (stderr, "Can't cross-compile on 64 bit platforms to arm.\n");
+       exit (1);
+#endif
 #endif
 
        if ((action == DO_EXEC) && mono_debug_using_mono_debugger ())
@@ -1559,8 +1758,12 @@ mono_main (int argc, char* argv[])
        }
 #endif
 
+#ifdef HOST_WIN32
+       if (mixed_mode)
+               mono_load_coree (argv [i]);
+#endif
+
        mono_set_defaults (mini_verbose, opt);
-       mono_setup_vtable_in_class_init = FALSE;
        domain = mini_init (argv [i], forced_version);
 
        if (agents) {
@@ -1655,7 +1858,7 @@ mono_main (int argc, char* argv[])
                        exit (1);
                }
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                /* Detach console when executing IMAGE_SUBSYSTEM_WINDOWS_GUI on win32 */
                if (!enable_debugging && !mono_compile_aot && ((MonoCLIImageInfo*)(mono_assembly_get_image (assembly)->image_info))->cli_header.nt.pe_subsys_required == IMAGE_SUBSYSTEM_WINDOWS_GUI)
                        FreeConsole ();
@@ -1683,6 +1886,7 @@ mono_main (int argc, char* argv[])
         * shut down), it will crash:
         * http://mail-archives.apache.org/mod_mbox/harmony-dev/200801.mbox/%3C200801130327.41572.gshimansky@apache.org%3E
         * Testcase: tests/main-exit-background-change.exe.
+        * Testcase: test/main-returns-background-abort-resetabort.exe.
         * To make this race less frequent, we avoid freeing the global code manager.
         * Since mono_main () is hopefully only used by the runtime executable, this 
         * will only cause a shutdown leak. This workaround also has the advantage
@@ -1690,8 +1894,11 @@ mono_main (int argc, char* argv[])
         * FIXME: Fix this properly by waiting for threads to really exit using 
         * pthread_join (). This cannot be done currently as the io-layer calls
         * pthread_detach ().
+        *
+        * This used to be an amd64 only crash, but it looks like now most glibc targets do unwinding
+        * that requires reading the target code.
         */
-#ifdef __x86_64__
+#ifdef __linux__
                mono_dont_free_global_codeman = TRUE;
 #endif
 
@@ -1735,6 +1942,7 @@ mono_main (int argc, char* argv[])
                return 3;
        }
 
+#ifndef DISABLE_JIT
        if (action == DO_DRAW) {
                int part = 0;
 
@@ -1826,6 +2034,7 @@ mono_main (int argc, char* argv[])
                cfg = mini_method_compile (method, opt, mono_get_root_domain (), FALSE, FALSE, 0);
                mono_destroy_compile (cfg);
        }
+#endif
 
        mini_cleanup (domain);
        return 0;