X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fdriver.c;h=674cea09a6c13f19b3796eb19b84ee3a26ae9cee;hb=2fd0ba2813d04d6ddf46e9d85398a7622a45a9da;hp=00191a1598084fb848fe66d7074f45d35567b37a;hpb=75d41985862bf668ade2c2a1c9f666ded4177721;p=mono.git diff --git a/mono/mini/driver.c b/mono/mini/driver.c index 00191a15980..674cea09a6c 100644 --- a/mono/mini/driver.c +++ b/mono/mini/driver.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "mono/utils/mono-counters.h" #include @@ -52,7 +53,6 @@ #include "jit.h" #include #include -#include "inssel.h" #include #include "version.h" @@ -114,6 +114,7 @@ opt_funcs [sizeof (int) * 8] = { NULL }; + #define DEFAULT_OPTIMIZATIONS ( \ MONO_OPT_PEEPHOLE | \ MONO_OPT_CFOLD | \ @@ -129,6 +130,7 @@ opt_funcs [sizeof (int) * 8] = { MONO_OPT_EXCEPTION | \ MONO_OPT_CMOV | \ MONO_OPT_GSHARED | \ + MONO_OPT_SIMD | \ MONO_OPT_AOT) #define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP) @@ -295,6 +297,11 @@ opt_sets [] = { MONO_OPT_BRANCH, MONO_OPT_CFOLD, MONO_OPT_FCMOV, +#ifdef MONO_ARCH_SIMD_INTRINSICS + MONO_OPT_SIMD, + MONO_OPT_SSE2, + MONO_OPT_SIMD | MONO_OPT_SSE2, +#endif MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_INTRINS, MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS, MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP, @@ -309,7 +316,8 @@ opt_sets [] = { 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_TREEPROP, 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 + 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, + DEFAULT_OPTIMIZATIONS, }; typedef int (*TestMethod) (void); @@ -323,7 +331,8 @@ domain_dump_native_code (MonoDomain *domain) { #endif static int -mini_regression (MonoImage *image, int verbose, int *total_run) { +mini_regression (MonoImage *image, int verbose, int *total_run) +{ guint32 i, opt, opt_flags; MonoMethod *method; MonoCompile *cfg; @@ -331,6 +340,7 @@ mini_regression (MonoImage *image, int verbose, int *total_run) { int result, expected, failed, cfailed, run, code_size, total; TestMethod func; GTimer *timer = g_timer_new (); + MonoDomain *domain = mono_domain_get (); if (mini_stats_fd) { fprintf (mini_stats_fd, "$stattitle = \'Mono Benchmark Results (various optimizations)\';\n"); @@ -380,10 +390,10 @@ mini_regression (MonoImage *image, int verbose, int *total_run) { comp_time = elapsed = 0.0; /* fixme: ugly hack - delete all previously compiled methods */ - 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); - mono_internal_hash_table_destroy (&(mono_domain_get ()->jit_code_hash)); - mono_jit_code_hash_init (&(mono_domain_get ()->jit_code_hash)); + g_hash_table_destroy (domain_jit_info (domain)->jit_trampoline_hash); + domain_jit_info (domain)->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); + mono_internal_hash_table_destroy (&(domain->jit_code_hash)); + mono_jit_code_hash_init (&(domain->jit_code_hash)); g_timer_start (timer); if (mini_stats_fd) @@ -829,6 +839,8 @@ compile_all_methods_thread_main (CompileAllThreadArgs *args) continue; method = mono_get_method (image, token, NULL); + if (!method) + continue; if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || @@ -924,16 +936,29 @@ static void main_thread_handler (gpointer user_data) MainThreadArgs *main_args = user_data; MonoAssembly *assembly; - assembly = mono_domain_assembly_open (main_args->domain, main_args->file); - if (!assembly){ - fprintf (stderr, "Can not open image %s\n", main_args->file); - exit (1); - } - if (mono_compile_aot) { - int res = mono_compile_assembly (assembly, main_args->opts, main_args->aot_options); - printf ("AOT RESULT %d\n", res); + int i, res; + + /* Treat the other arguments as assemblies to compile too */ + for (i = 0; i < main_args->argc; ++i) { + assembly = mono_domain_assembly_open (main_args->domain, main_args->argv [i]); + if (!assembly) { + fprintf (stderr, "Can not open image %s\n", main_args->argv [i]); + exit (1); + } + res = mono_compile_assembly (assembly, main_args->opts, main_args->aot_options); + if (res != 0) { + fprintf (stderr, "AOT of image %s failed.\n", main_args->argv [i]); + exit (1); + } + } } else { + assembly = mono_domain_assembly_open (main_args->domain, main_args->file); + if (!assembly){ + fprintf (stderr, "Can not open image %s\n", main_args->file); + exit (1); + } + /* * This must be done in a thread managed by mono since it can invoke * managed code. @@ -945,6 +970,72 @@ static void main_thread_handler (gpointer user_data) } } +static int +load_agent (MonoDomain *domain, char *desc) +{ + char* col = strchr (desc, ':'); + char *agent, *args; + MonoAssembly *agent_assembly; + MonoImage *image; + MonoMethod *method; + guint32 entry; + MonoArray *main_args; + gpointer pa [1]; + MonoImageOpenStatus open_status; + + if (col) { + agent = g_memdup (desc, col - desc + 1); + agent [col - desc] = '\0'; + args = col + 1; + } else { + agent = g_strdup (desc); + args = NULL; + } + + agent_assembly = mono_assembly_open (agent, &open_status); + if (!agent_assembly) { + fprintf (stderr, "Cannot open agent assembly '%s': %s.\n", agent, mono_image_strerror (open_status)); + g_free (agent); + return 2; + } + + /* + * Can't use mono_jit_exec (), as it sets things which might confuse the + * real Main method. + */ + image = mono_assembly_get_image (agent_assembly); + entry = mono_image_get_entry_point (image); + if (!entry) { + g_print ("Assembly '%s' doesn't have an entry point.\n", mono_image_get_filename (image)); + g_free (agent); + return 1; + } + + method = mono_get_method (image, entry, NULL); + if (method == NULL){ + g_print ("The entry point method of assembly '%s' could not be loaded\n", agent); + g_free (agent); + return 1; + } + + mono_thread_set_main (mono_thread_current ()); + + if (args) { + main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 1); + mono_array_set (main_args, MonoString*, 0, mono_string_new (domain, args)); + } else { + main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0); + } + + g_free (agent); + + pa [0] = main_args; + /* Pass NULL as 'exc' so unhandled exceptions abort the runtime */ + mono_runtime_invoke (method, NULL, pa, NULL); + + return 0; +} + static void mini_usage_jitdeveloper (void) { @@ -966,6 +1057,8 @@ mini_usage_jitdeveloper (void) " --inject-async-exc METHOD OFFSET Inject an asynchronous exception at METHOD\n" " --verify-all Run the verifier on all 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" "\n" "Other options:\n" " --graph[=TYPE] METHOD Draws a graph of the specified method:\n"); @@ -1006,7 +1099,10 @@ mini_usage (void) " --optimize=OPT Turns on or off a specific optimization\n" " Use --list-opt to get a list of optimizations\n" " --security[=mode] Turns on the unsupported security manager (off by default)\n" - " mode is one of cas, core-clr, verifiable or validil\n"); + " 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" + ); } static void @@ -1026,6 +1122,7 @@ mini_trace_usage (void) " T:Type Specifies a type\n" " +EXPR Includes expression\n" " -EXPR Excludes expression\n" + " EXPR,EXPR Multiple expressions\n" " disabled Don't print any output until toggled via SIGUSR2\n"); } @@ -1045,14 +1142,10 @@ mini_debug_usage (void) " process with the debugger.\n"); } -#if defined(__arm__) && defined(__ARM_EABI__) +#if defined(MONO_ARCH_ARCHITECTURE) /* Redefine ARCHITECTURE to include more information */ #undef ARCHITECTURE -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -#define ARCHITECTURE "armel" -#else -#define ARCHITECTURE "armeb" -#endif +#define ARCHITECTURE MONO_ARCH_ARCHITECTURE #endif static const char info[] = @@ -1124,6 +1217,8 @@ mono_main (int argc, char* argv[]) char *profile_options = NULL; char *aot_options = NULL; char *forced_version = NULL; + GPtrArray *agents = NULL; + char *attach_options = NULL; #ifdef MONO_JIT_INFO_TABLE_TEST int test_jit_info_table = FALSE; #endif @@ -1168,7 +1263,9 @@ 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 (%s)\nCopyright (C) 2002-2008 Novell, Inc and Contributors. www.mono-project.com\n", VERSION, FULL_VERSION); + 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); + g_free (build); g_print (info); if (mini_verbose) { const char *cerror; @@ -1287,6 +1384,12 @@ mono_main (int argc, char* argv[]) } else if (strncmp (argv [i], "--profile=", 10) == 0) { enable_profile = TRUE; profile_options = argv [i] + 10; + } else if (strncmp (argv [i], "--agent=", 8) == 0) { + if (agents == NULL) + agents = g_ptr_array_new (); + g_ptr_array_add (agents, argv [i] + 8); + } else if (strncmp (argv [i], "--attach=", 9) == 0) { + attach_options = argv [i] + 9; } else if (strcmp (argv [i], "--compile") == 0) { if (i + 1 >= argc){ fprintf (stderr, "error: --compile option requires a method name argument\n"); @@ -1320,27 +1423,21 @@ mono_main (int argc, char* argv[]) if (!parse_debug_options (argv [i] + 8)) return 1; } else if (strcmp (argv [i], "--security") == 0) { - /* fixme enable verifiable code when the verifier works with 2.0 - * mini_verifier_set_mode (MINI_VERIFIER_MODE_VERIFIABLE); - */ + mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE); mono_security_set_mode (MONO_SECURITY_MODE_CAS); mono_activate_security_manager (); } else if (strncmp (argv [i], "--security=", 11) == 0) { if (strcmp (argv [i] + 11, "temporary-smcs-hack") == 0) { mono_security_set_mode (MONO_SECURITY_MODE_SMCS_HACK); } else if (strcmp (argv [i] + 11, "core-clr") == 0) { - /* fixme enable verifiable code when the verifier works with 2.0 - * mini_verifier_set_mode (MINI_VERIFIER_MODE_VERIFIABLE); - */ + mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE); mono_security_set_mode (MONO_SECURITY_MODE_CORE_CLR); } else if (strcmp (argv [i] + 11, "core-clr-test") == 0) { /* fixme should we enable verifiable code here?*/ mono_security_set_mode (MONO_SECURITY_MODE_CORE_CLR); mono_security_core_clr_test = TRUE; } else if (strcmp (argv [i] + 11, "cas") == 0){ - /* fixme enable verifiable code when the verifier works with 2.0 - * mini_verifier_set_mode (MINI_VERIFIER_MODE_VERIFIABLE); - */ + mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE); mono_security_set_mode (MONO_SECURITY_MODE_CAS); mono_activate_security_manager (); } else if (strcmp (argv [i] + 11, "validil") == 0) { @@ -1371,6 +1468,8 @@ mono_main (int argc, char* argv[]) fprintf (stderr, "Invalid --wapi suboption: '%s'\n", argv [i]); return 1; } + } else if (strcmp (argv [i], "--no-x86-stack-align") == 0) { + mono_do_x86_stack_align = FALSE; #ifdef MONO_JIT_INFO_TABLE_TEST } else if (strcmp (argv [i], "--test-jit-info-table") == 0) { test_jit_info_table = TRUE; @@ -1399,6 +1498,8 @@ mono_main (int argc, char* argv[]) mono_profiler_load (profile_options); } + mono_attach_parse_options (attach_options); + if (trace_options != NULL){ /* * Need to call this before mini_init () so we can trace methods @@ -1409,6 +1510,13 @@ mono_main (int argc, char* argv[]) exit (1); } +#ifdef DISABLE_JIT + if (!mono_aot_only) { + fprintf (stderr, "This runtime has been configured with --enable-minimal=jit, so the --full-aot command line option is required.\n"); + exit (1); + } +#endif + if (action == DO_DEBUGGER) { enable_debugging = TRUE; @@ -1425,6 +1533,21 @@ mono_main (int argc, char* argv[]) mono_set_defaults (mini_verbose, opt); mono_setup_vtable_in_class_init = FALSE; domain = mini_init (argv [i], forced_version); + + if (agents) { + int i; + + for (i = 0; i < agents->len; ++i) { + int res = load_agent (domain, (char*)g_ptr_array_index (agents, i)); + if (res) { + g_ptr_array_free (agents, TRUE); + mini_cleanup (domain); + return 1; + } + } + + g_ptr_array_free (agents, TRUE); + } switch (action) { case DO_REGRESSION: @@ -1521,6 +1644,28 @@ mono_main (int argc, char* argv[]) main_thread_handler (&main_args); mono_thread_manage (); #endif + + /* + * On unix, WaitForMultipleObjects for threads is implemented by waiting on + * a cond variable, which is set by the thread when it exits _mono code_, + * but it could still be running libc code. On amd64, the libc thread exit + * code does a stack unwind, and if it encounters a frame pointing to native + * code which is in memory which is no longer mapped (because the runtime has + * 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. + * 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 + * that it can be back-ported to 2.0 safely. + * 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 (). + */ +#ifdef __x86_64__ + mono_dont_free_global_codeman = TRUE; +#endif + mini_cleanup (domain); /* Look up return value from System.Environment.ExitCode */