[profiler] log profiler: limit method instrumentation to selected methods (#5517)
[mono.git] / mono / mini / driver.c
index 7a64689897785245979c39f23330243fe86d3ee5..dbbb646297d7850c260d5732a98a05be25753627 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * driver.c: The new mono JIT compiler.
+/**
+ * \file
+ * The new mono JIT compiler.
  *
  * Author:
  *   Paolo Molaro (lupus@ximian.com)
@@ -35,7 +36,6 @@
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
-#include "mono/metadata/profiler.h"
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
@@ -52,6 +52,7 @@
 #include "mono/utils/mono-hwcap.h"
 #include "mono/utils/mono-logger-internals.h"
 #include "mono/metadata/w32handle.h"
+#include "mono/metadata/callspec.h"
 
 #include "mini.h"
 #include "jit.h"
@@ -120,10 +121,6 @@ opt_names [] = {
 
 #endif
 
-#ifdef __native_client__
-extern char *nacl_mono_path;
-#endif
-
 #define DEFAULT_OPTIMIZATIONS (        \
        MONO_OPT_PEEPHOLE |     \
        MONO_OPT_CFOLD |        \
@@ -272,6 +269,9 @@ mono_parse_graph_options (const char* p)
        exit (1);
 }
 
+/**
+ * mono_parse_default_optimizations:
+ */
 int
 mono_parse_default_optimizations (const char* p)
 {
@@ -513,6 +513,11 @@ mini_regression (MonoImage *image, int verbose, int *total_run)
                }
        } else {
                for (opt = 0; opt < G_N_ELEMENTS (opt_sets); ++opt) {
+                       /* builtin-types.cs needs OPT_INTRINS enabled */
+                       if (!strcmp ("builtin-types", image->assembly_name))
+                               if (!(opt_sets [opt] & MONO_OPT_INTRINS))
+                                       continue;
+
                        mini_regression_step (image, verbose, total_run, &total,
                                        opt_sets [opt] & ~exclude,
                                        timer, domain);
@@ -985,10 +990,9 @@ compile_all_methods (MonoAssembly *ass, int verbose, guint32 opts, guint32 recom
 
 /**
  * mono_jit_exec:
- * @assembly: reference to an assembly
- * @argc: argument count
- * @argv: argument vector
- *
+ * \param assembly reference to an assembly
+ * \param argc argument count
+ * \param argv argument vector
  * Start execution of a program.
  */
 int 
@@ -1153,8 +1157,11 @@ load_agent (MonoDomain *domain, char *desc)
 
        if (args) {
                main_args = (MonoArray*)mono_array_new_checked (domain, mono_defaults.string_class, 1, &error);
-               if (main_args)
-                       mono_array_set (main_args, MonoString*, 0, mono_string_new (domain, args));
+               if (main_args) {
+                       MonoString *str = mono_string_new_checked (domain, args, &error);
+                       if (str)
+                               mono_array_set (main_args, MonoString*, 0, str);
+               }
        } else {
                main_args = (MonoArray*)mono_array_new_checked (domain, mono_defaults.string_class, 0, &error);
        }
@@ -1187,6 +1194,7 @@ mini_usage_jitdeveloper (void)
        
        fprintf (stdout,
                 "Runtime and JIT debugging options:\n"
+                "    --apply-bindings=FILE  Apply assembly bindings from FILE (only for AOT)\n"
                 "    --breakonex            Inserts a breakpoint on exceptions\n"
                 "    --break METHOD         Inserts a breakpoint at METHOD entry\n"
                 "    --break-at-bb METHOD N Inserts a breakpoint in METHOD at BB N\n"
@@ -1359,11 +1367,11 @@ static const char info[] =
 
 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 ().
+ * Process the command line options in \p argv as done by the runtime executable.
+ * This should be called before \c mono_jit_init.
  */
 void
 mono_jit_parse_options (int argc, char * argv[])
@@ -1413,8 +1421,8 @@ mono_jit_parse_options (int argc, char * argv[])
                        opt->break_on_exc = TRUE;
                } else if (strcmp (argv [i], "--stats") == 0) {
                        mono_counters_enable (-1);
-                       mono_stats.enabled = TRUE;
-                       mono_jit_stats.enabled = TRUE;
+                       InterlockedWriteBool (&mono_stats.enabled, TRUE);
+                       InterlockedWriteBool (&mono_jit_stats.enabled, TRUE);
                } else if (strcmp (argv [i], "--break") == 0) {
                        if (i+1 >= argc){
                                fprintf (stderr, "Missing method name in --break command line option\n");
@@ -1447,7 +1455,7 @@ mono_jit_parse_options (int argc, char * argv[])
                 * 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);
+               mono_jit_trace_calls = mono_trace_set_options (trace_options);
                if (mono_jit_trace_calls == NULL)
                        exit (1);
        }
@@ -1549,11 +1557,20 @@ switch_arch (char* argv[], const char* target_arch)
 #define MONO_HANDLERS_ARGUMENT "--handlers="
 #define MONO_HANDLERS_ARGUMENT_LEN G_N_ELEMENTS(MONO_HANDLERS_ARGUMENT)-1
 
+static void
+apply_root_domain_configuration_file_bindings (MonoDomain *domain, char *root_domain_configuration_file)
+{
+       g_assert (domain->setup == NULL || domain->setup->configuration_file == NULL);
+       g_assert (!domain->assembly_bindings_parsed);
+
+       mono_domain_parse_assembly_bindings (domain, 0, 0, root_domain_configuration_file);
+
+}
+
 /**
  * mono_main:
- * @argc: number of arguments in the argv array
- * @argv: array of strings containing the startup arguments
- *
+ * \param argc number of arguments in the argv array
+ * \param 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.
  */
@@ -1573,22 +1590,18 @@ mono_main (int argc, char* argv[])
        guint32 opt, action = DO_EXEC, recompilation_times = 1;
        MonoGraphOptions mono_graph_options = (MonoGraphOptions)0;
        int mini_verbose = 0;
-       gboolean enable_profile = FALSE;
        char *trace_options = NULL;
-       char *profile_options = NULL;
        char *aot_options = NULL;
        char *forced_version = NULL;
        GPtrArray *agents = NULL;
        char *attach_options = NULL;
+       char *extra_bindings_config_file = NULL;
 #ifdef MONO_JIT_INFO_TABLE_TEST
        int test_jit_info_table = FALSE;
 #endif
 #ifdef HOST_WIN32
        int mixed_mode = FALSE;
 #endif
-#ifdef __native_client__
-       gboolean nacl_null_checks_off = FALSE;
-#endif
 
 #ifdef MOONLIGHT
 #ifndef HOST_WIN32
@@ -1605,7 +1618,7 @@ mono_main (int argc, char* argv[])
        darwin_change_default_file_handles ();
 #endif
 
-       if (g_getenv ("MONO_NO_SMP"))
+       if (g_hasenv ("MONO_NO_SMP"))
                mono_set_use_smp (FALSE);
        
        g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
@@ -1755,8 +1768,8 @@ mono_main (int argc, char* argv[])
                        mono_print_vtable = TRUE;
                } else if (strcmp (argv [i], "--stats") == 0) {
                        mono_counters_enable (-1);
-                       mono_stats.enabled = TRUE;
-                       mono_jit_stats.enabled = TRUE;
+                       InterlockedWriteBool (&mono_stats.enabled, TRUE);
+                       InterlockedWriteBool (&mono_jit_stats.enabled, TRUE);
 #ifndef DISABLE_AOT
                } else if (strcmp (argv [i], "--aot") == 0) {
                        error_if_aot_unsupported ();
@@ -1766,6 +1779,8 @@ mono_main (int argc, char* argv[])
                        mono_compile_aot = TRUE;
                        aot_options = &argv [i][6];
 #endif
+               } else if (strncmp (argv [i], "--apply-bindings=", 17) == 0) {
+                       extra_bindings_config_file = &argv[i][17];
                } else if (strncmp (argv [i], "--aot-path=", 11) == 0) {
                        char **splitted;
 
@@ -1786,11 +1801,9 @@ mono_main (int argc, char* argv[])
                } else if (strcmp (argv [i], "--jitmap") == 0) {
                        mono_enable_jit_map ();
                } else if (strcmp (argv [i], "--profile") == 0) {
-                       enable_profile = TRUE;
-                       profile_options = NULL;
+                       mini_add_profiler_argument (NULL);
                } else if (strncmp (argv [i], "--profile=", 10) == 0) {
-                       enable_profile = TRUE;
-                       profile_options = argv [i] + 10;
+                       mini_add_profiler_argument (argv [i] + 10);
                } else if (strncmp (argv [i], "--agent=", 8) == 0) {
                        if (agents == NULL)
                                agents = g_ptr_array_new ();
@@ -1905,17 +1918,27 @@ mono_main (int argc, char* argv[])
 #endif
                } else if (strcmp (argv [i], "--nollvm") == 0){
                        mono_use_llvm = FALSE;
+               } else if ((strcmp (argv [i], "--interpreter") == 0) || !strcmp (argv [i], "--interp")) {
 #ifdef ENABLE_INTERPRETER
-               } else if (strcmp (argv [i], "--interpreter") == 0) {
                        mono_use_interpreter = TRUE;
+#else
+                       fprintf (stderr, "Mono Warning: --interpreter not enabled in this runtime.\n");
 #endif
-
-#ifdef __native_client__
-               } else if (strcmp (argv [i], "--nacl-mono-path") == 0){
-                       nacl_mono_path = g_strdup(argv[++i]);
-               } else if (strcmp (argv [i], "--nacl-null-checks-off") == 0){
-                       nacl_null_checks_off = TRUE;
+               } else if (strncmp (argv [i], "--interp=", 9) == 0) {
+#ifdef ENABLE_INTERPRETER
+                       mono_use_interpreter = TRUE;
+                       mono_interp_parse_options (argv [i] + 9);
+#else
+                       fprintf (stderr, "Mono Warning: --interp= not enabled in this runtime.\n");
 #endif
+               } else if (strncmp (argv [i], "--assembly-loader=", strlen("--assembly-loader=")) == 0) {
+                       gchar *arg = argv [i] + strlen ("--assembly-loader=");
+                       if (strcmp (arg, "strict") == 0)
+                               mono_loader_set_strict_strong_names (TRUE);
+                       else if (strcmp (arg, "legacy") == 0)
+                               mono_loader_set_strict_strong_names (FALSE);
+                       else
+                               fprintf (stderr, "Warning: unknown argument to --assembly-loader. Should be \"strict\" or \"legacy\"\n");
                } else if (strncmp (argv [i], MONO_HANDLERS_ARGUMENT, MONO_HANDLERS_ARGUMENT_LEN) == 0) {
                        //Install specific custom handlers.
                        if (!mono_runtime_install_custom_handlers (argv[i] + MONO_HANDLERS_ARGUMENT_LEN)) {
@@ -1932,13 +1955,6 @@ mono_main (int argc, char* argv[])
                }
        }
 
-#ifdef __native_client_codegen__
-       if (!nacl_null_checks_off) {
-               MonoDebugOptions *opt = mini_get_debug_options ();
-               opt->explicit_null_checks = TRUE;
-       }
-#endif
-
 #if defined(DISABLE_HW_TRAPS) || defined(MONO_ARCH_DISABLE_HW_TRAPS)
        // Signal handlers not available
        {
@@ -1967,7 +1983,7 @@ mono_main (int argc, char* argv[])
        }
 #endif
 
-       if (g_getenv ("MONO_XDEBUG"))
+       if (g_hasenv ("MONO_XDEBUG"))
                enable_debugging = TRUE;
 
 #ifdef MONO_CROSS_COMPILE
@@ -1997,10 +2013,6 @@ mono_main (int argc, char* argv[])
        /* Set rootdir before loading config */
        mono_set_rootdir ();
 
-       if (enable_profile) {
-               mini_profiler_enable_with_options (profile_options);
-       }
-
        mono_attach_parse_options (attach_options);
 
        if (trace_options != NULL){
@@ -2008,7 +2020,7 @@ mono_main (int argc, char* argv[])
                 * 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);
+               mono_jit_trace_calls = mono_trace_set_options (trace_options);
                if (mono_jit_trace_calls == NULL)
                        exit (1);
        }
@@ -2038,9 +2050,6 @@ mono_main (int argc, char* argv[])
        }
 
        mono_set_defaults (mini_verbose, opt);
-#ifdef ENABLE_INTERPRETER
-       mono_interp_init ();
-#endif
        domain = mini_init (argv [i], forced_version);
 
        mono_gc_set_stack_end (&domain);
@@ -2121,6 +2130,10 @@ mono_main (int argc, char* argv[])
                jit_info_table_test (domain);
 #endif
 
+       if (mono_compile_aot && extra_bindings_config_file != NULL) {
+               apply_root_domain_configuration_file_bindings (domain, extra_bindings_config_file);
+       }
+
        assembly = mono_assembly_open_predicate (aname, FALSE, FALSE, NULL, NULL, &open_status);
        if (!assembly) {
                fprintf (stderr, "Cannot open assembly '%s': %s.\n", aname, mono_image_strerror (open_status));
@@ -2128,8 +2141,7 @@ mono_main (int argc, char* argv[])
                return 2;
        }
 
-       if (trace_options != NULL)
-               mono_trace_set_assembly (assembly);
+       mono_callspec_set_assembly (assembly);
 
        if (mono_compile_aot || action == DO_EXEC) {
                const char *error;
@@ -2287,6 +2299,9 @@ mono_main (int argc, char* argv[])
        return 0;
 }
 
+/**
+ * mono_jit_init:
+ */
 MonoDomain * 
 mono_jit_init (const char *file)
 {
@@ -2295,22 +2310,22 @@ mono_jit_init (const char *file)
 
 /**
  * mono_jit_init_version:
- * @domain_name: the name of the root domain
- * @runtime_version: the version of the runtime to load
+ * \param domain_name the name of the root domain
+ * \param runtime_version the version of the runtime to load
  *
  * Use this version when you want to force a particular runtime
  * version to be used.  By default Mono will pick the runtime that is
- * referenced by the initial assembly (specified in @file), this
+ * referenced by the initial assembly (specified in \p file), this
  * routine allows programmers to specify the actual runtime to be used
  * as the initial runtime is inherited by all future assemblies loaded
  * (since Mono does not support having more than one mscorlib runtime
  * loaded at once).
  *
- * The @runtime_version can be one of these strings: "v4.0.30319" for
+ * The \p runtime_version can be one of these strings: "v4.0.30319" for
  * desktop, "mobile" for mobile or "moonlight" for Silverlight compat.
  * If an unrecognized string is input, the vm will default to desktop.
  *
- * Returns: the MonoDomain representing the domain where the assembly
+ * \returns the \c MonoDomain representing the domain where the assembly
  * was loaded.
  */
 MonoDomain * 
@@ -2319,6 +2334,9 @@ mono_jit_init_version (const char *domain_name, const char *runtime_version)
        return mini_init (domain_name, runtime_version);
 }
 
+/**
+ * mono_jit_cleanup:
+ */
 void        
 mono_jit_cleanup (MonoDomain *domain)
 {
@@ -2333,6 +2351,9 @@ mono_jit_set_aot_only (gboolean val)
        mono_aot_only = val;
 }
 
+/**
+ * mono_jit_set_aot_mode:
+ */
 void
 mono_jit_set_aot_mode (MonoAotMode mode)
 {
@@ -2351,21 +2372,35 @@ mono_jit_set_aot_mode (MonoAotMode mode)
                mono_set_generic_sharing_vt_supported (TRUE);
                mono_set_partial_sharing_supported (TRUE);
        }
+       if (mono_aot_mode == MONO_AOT_MODE_INTERP) {
+               mono_aot_only = TRUE;
+               mono_use_interpreter = TRUE;
+       }
+       if (mono_aot_mode == MONO_AOT_MODE_INTERP_LLVMONLY) {
+               mono_aot_only = TRUE;
+               mono_use_interpreter = TRUE;
+               mono_llvm_only = TRUE;
+       }
+}
+
+mono_bool
+mono_jit_aot_compiling (void)
+{
+       return mono_compile_aot;
 }
 
 /**
  * mono_jit_set_trace_options:
- * @options: string representing the trace options
- *
+ * \param options string representing the trace options
  * Set the options of the tracing engine. This function can be called before initializing
  * the mono runtime. See the --trace mono(1) manpage for the options format.
  *
- * Returns: #TRUE if the options where parsed and set correctly, #FALSE otherwise.
+ * \returns TRUE if the options were parsed and set correctly, FALSE otherwise.
  */
 gboolean
 mono_jit_set_trace_options (const char* options)
 {
-       MonoTraceSpec *trace_opt = mono_trace_parse_options (options);
+       MonoCallSpec *trace_opt = mono_trace_set_options (options);
        if (trace_opt == NULL)
                return FALSE;
        mono_jit_trace_calls = trace_opt;
@@ -2375,14 +2410,14 @@ mono_jit_set_trace_options (const char* options)
 /**
  * mono_set_signal_chaining:
  *
- *   Enable/disable signal chaining. This should be called before mono_jit_init ().
+ * Enable/disable signal chaining. This should be called before \c mono_jit_init.
  * If signal chaining is enabled, the runtime saves the original signal handlers before
  * installing its own handlers, and calls the original ones in the following cases:
- * - a SIGSEGV/SIGABRT signal received while executing native (i.e. not JITted) code.
- * - SIGPROF
- * - SIGFPE
- * - SIGQUIT
- * - SIGUSR2
+ * - a \c SIGSEGV / \c SIGABRT signal received while executing native (i.e. not JITted) code.
+ * - \c SIGPROF
+ * - \c SIGFPE
+ * - \c SIGQUIT
+ * - \c SIGUSR2
  * Signal chaining only works on POSIX platforms.
  */
 void
@@ -2406,14 +2441,14 @@ mono_set_crash_chaining (gboolean chain_crashes)
 
 /**
  * mono_parse_options_from:
- * @options: string containing strings 
- * @ref_argc: pointer to the argc variable that might be updated 
- * @ref_argv: pointer to the argv string vector variable that might be updated
+ * \param options string containing strings 
+ * \param ref_argc pointer to the \c argc variable that might be updated 
+ * \param ref_argv pointer to the \c argv string vector variable that might be updated
  *
- * This function parses the contents of the `MONO_ENV_OPTIONS`
+ * This function parses the contents of the \c MONO_ENV_OPTIONS
  * environment variable as if they were parsed by a command shell
  * splitting the contents by spaces into different elements of the
- * @argv vector.  This method supports quoting with both the " and '
+ * \p argv vector.  This method supports quoting with both the " and '
  * characters.  Inside quoting, spaces and tabs are significant,
  * otherwise, they are considered argument separators.
  *
@@ -2422,14 +2457,14 @@ mono_set_crash_chaining (gboolean chain_crashes)
  * inside quotes.   If the quotes are not balanced, this method 
  *
  * If the environment variable is empty, no changes are made
- * to the values pointed by @ref_argc and @ref_argv.
+ * to the values pointed by \p ref_argc and \p ref_argv.
  *
- * Otherwise the @ref_argv is modified to point to a new array that contains
+ * Otherwise the \p ref_argv is modified to point to a new array that contains
  * all the previous elements contained in the vector, plus the values parsed.
- * The @argc is updated to match the new number of parameters.
+ * The \p argc is updated to match the new number of parameters.
  *
- * Returns: The value NULL is returned on success, otherwise a g_strdup allocated
- * string is returned (this is an alias to malloc under normal circumstances) that
+ * \returns The value NULL is returned on success, otherwise a \c g_strdup allocated
+ * string is returned (this is an alias to \c malloc under normal circumstances) that
  * contains the error message that happened during parsing.
  */
 char *
@@ -2513,13 +2548,13 @@ mono_parse_options_from (const char *options, int *ref_argc, char **ref_argv [])
 
 /**
  * mono_parse_env_options:
- * @ref_argc: pointer to the argc variable that might be updated 
- * @ref_argv: pointer to the argv string vector variable that might be updated
+ * \param ref_argc pointer to the \c argc variable that might be updated 
+ * \param ref_argv pointer to the \c argv string vector variable that might be updated
  *
- * This function parses the contents of the `MONO_ENV_OPTIONS`
+ * This function parses the contents of the \c MONO_ENV_OPTIONS
  * environment variable as if they were parsed by a command shell
  * splitting the contents by spaces into different elements of the
- * @argv vector.  This method supports quoting with both the " and '
+ * \p argv vector.  This method supports quoting with both the " and '
  * characters.  Inside quoting, spaces and tabs are significant,
  * otherwise, they are considered argument separators.
  *
@@ -2528,11 +2563,11 @@ mono_parse_options_from (const char *options, int *ref_argc, char **ref_argv [])
  * inside quotes.   If the quotes are not balanced, this method 
  *
  * If the environment variable is empty, no changes are made
- * to the values pointed by @ref_argc and @ref_argv.
+ * to the values pointed by \p ref_argc and \p ref_argv.
  *
- * Otherwise the @ref_argv is modified to point to a new array that contains
+ * Otherwise the \p ref_argv is modified to point to a new array that contains
  * all the previous elements contained in the vector, plus the values parsed.
- * The @argc is updated to match the new number of parameters.
+ * The \p argc is updated to match the new number of parameters.
  *
  * If there is an error parsing, this method will terminate the process by
  * calling exit(1).
@@ -2545,10 +2580,11 @@ mono_parse_env_options (int *ref_argc, char **ref_argv [])
 {
        char *ret;
        
-       const char *env_options = g_getenv ("MONO_ENV_OPTIONS");
+       char *env_options = g_getenv ("MONO_ENV_OPTIONS");
        if (env_options == NULL)
                return;
        ret = mono_parse_options_from (env_options, ref_argc, ref_argv);
+       g_free (env_options);
        if (ret == NULL)
                return;
        fprintf (stderr, "%s", ret);