[mono/mono] a57f9ce8: [runtime] JIT debugging option to optimize only single methods.
"Mark Probst (
[email protected] )" <
[email protected] >
Fri, 18 Oct 2013 23:24:00 +0000
Newsgroups
gmane.comp.gnome.mono.patches
Message-ID
<00000141cde1f8ed-a8bd2935-5249-4269-b6ae-ad8e62ac0f11-000000@email.amazonses.com>
Branch: refs/heads/master
Home: https://github.com/mono/mono
Compare: https://github.com/mono/mono/compare/b17461cb8a48...a57f9ce8a0c0
Commit: a57f9ce8a0c0d3acb0606f63594398632fe3887e
Author: Mark Probst <[email protected] > (schani)
Date: 2013-10-18 23:19:00 GMT
URL: https://github.com/mono/mono/commit/a57f9ce8a0c0d3acb0606f63594398632fe3887e
[runtime] JIT debugging option to optimize only single methods.
The --single-method option run regression tests from an assembly, like
--regression. Instead of going through a list of optimizations,
however, it takes one optimization combination, runs all tests with
all optimizations turned off, while gathering a list of which methods
were jitted. Then, for each jitted method, it runs all tests again,
with the optimizations applied to only that one method, stopping as
soon as a test fails. Example:
mono --single-method=branch,peephole basic-float.exe
Changed paths:
M mono/mini/driver.c
M mono/mini/mini.c
M mono/mini/mini.h
Modified: mono/mini/driver.c
===================================================================
@@ -342,18 +342,128 @@
}
#endif
+static gboolean do_single_method_regression = FALSE;
+static guint32 single_method_regression_opt;
+static MonoMethod *current_single_method = NULL;
+static GSList *single_method_list = NULL;
+static GHashTable *single_method_hash = NULL;
+
+guint32
+mono_get_optimizations_for_method (MonoMethod *method, guint32 default_opt)
+{
+ g_assert (method);
+
+ if (!do_single_method_regression)
+ return default_opt;
+ if (!current_single_method) {
+ if (!single_method_hash)
+ single_method_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ if (!g_hash_table_lookup (single_method_hash, method)) {
+ g_hash_table_insert (single_method_hash, method, method);
+ single_method_list = g_slist_prepend (single_method_list, method);
+ }
+ return default_opt;
+ }
+ if (method == current_single_method)
+ return single_method_regression_opt;
+ return default_opt;
+}
+
+static void
+mini_regression_step (MonoImage *image, int verbose, int *total_run, int *total,
+ guint32 opt_flags,
+ GTimer *timer, MonoDomain *domain)
+{
+ int result, expected, failed, cfailed, run, code_size;
+ TestMethod func;
+ double elapsed, comp_time, start_time;
+ char *n;
+ int i;
+
+ mono_set_defaults (verbose, opt_flags);
+ n = opt_descr (opt_flags);
+ 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 */
+ 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)
+ fprintf (mini_stats_fd, "[");
+ for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
+ MonoMethod *method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
+ if (!method)
+ continue;
+ if (strncmp (method->name, "test_", 5) == 0) {
+ MonoCompile *cfg;
+
+ expected = atoi (method->name + 5);
+ run++;
+ start_time = g_timer_elapsed (timer, NULL);
+ comp_time -= start_time;
+ cfg = mini_method_compile (method, mono_get_optimizations_for_method (method, opt_flags), mono_get_root_domain (), TRUE, FALSE, 0);
+ comp_time += g_timer_elapsed (timer, NULL);
+ if (cfg->exception_type == MONO_EXCEPTION_NONE) {
+ if (verbose >= 2)
+ g_print ("Running '%s' ...\n", method->name);
+#ifdef MONO_USE_AOT_COMPILER
+ if ((func = mono_aot_get_method (mono_get_root_domain (), method)))
+ ;
+ else
+#endif
+ func = (TestMethod)(gpointer)cfg->native_code;
+ func = (TestMethod)mono_create_ftnptr (mono_get_root_domain (), func);
+ result = func ();
+ if (result != expected) {
+ failed++;
+ g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
+ }
+ code_size += cfg->code_len;
+ mono_destroy_compile (cfg);
+
+ } else {
+ cfailed++;
+ if (verbose)
+ g_print ("Test '%s' failed compilation.\n", method->name);
+ }
+ if (mini_stats_fd)
+ fprintf (mini_stats_fd, "%f, ",
+ g_timer_elapsed (timer, NULL) - start_time);
+ }
+ }
+ if (mini_stats_fd)
+ fprintf (mini_stats_fd, "],\n");
+ g_timer_stop (timer);
+ elapsed = g_timer_elapsed (timer, NULL);
+ if (failed > 0 || cfailed > 0){
+ g_print ("Results: total tests: %d, failed: %d, cfailed: %d (pass: %.2f%%)\n",
+ run, failed, cfailed, 100.0*(run-failed-cfailed)/run);
+ } else {
+ g_print ("Results: total tests: %d, all pass \n", run);
+ }
+
+ g_print ("Elapsed time: %f secs (%f, %f), Code size: %d\n\n", elapsed,
+ elapsed - comp_time, comp_time, code_size);
+ *total += failed + cfailed;
+ *total_run += run;
+}
+
static int
mini_regression (MonoImage *image, int verbose, int *total_run)
{
- guint32 i, opt, opt_flags;
+ guint32 i, opt;
MonoMethod *method;
- MonoCompile *cfg;
char *n;
- int result, expected, failed, cfailed, run, code_size, total;
- TestMethod func;
GTimer *timer = g_timer_new ();
MonoDomain *domain = mono_domain_get ();
guint32 exclude = 0;
+ int total;
/* Note: mono_hwcap_init () called in mono_init () before we get here. */
mono_arch_cpu_optimizations (&exclude);
@@ -363,7 +473,7 @@
fprintf (mini_stats_fd, "$graph->set_legend(qw(");
for (opt = 0; opt < G_N_ELEMENTS (opt_sets); opt++) {
- opt_flags = opt_sets [opt];
+ guint32 opt_flags = opt_sets [opt];
n = opt_descr (opt_flags);
if (!n [0])
n = (char *)"none";
@@ -396,80 +506,37 @@
total = 0;
*total_run = 0;
- for (opt = 0; opt < G_N_ELEMENTS (opt_sets); ++opt) {
- double elapsed, comp_time, start_time;
-
- opt_flags = opt_sets [opt] & ~exclude;
- mono_set_defaults (verbose, opt_flags);
- n = opt_descr (opt_flags);
- 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 */
- 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)
- fprintf (mini_stats_fd, "[");
- 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 (!method)
- continue;
- 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_get_root_domain (), TRUE, FALSE, 0);
- comp_time += g_timer_elapsed (timer, NULL);
- if (cfg->exception_type == MONO_EXCEPTION_NONE) {
- if (verbose >= 2)
- g_print ("Running '%s' ...\n", method->name);
-#ifdef MONO_USE_AOT_COMPILER
- if ((func = mono_aot_get_method (mono_get_root_domain (), method)))
- ;
- else
-#endif
- func = (TestMethod)(gpointer)cfg->native_code;
- func = (TestMethod)mono_create_ftnptr (mono_get_root_domain (), func);
- result = func ();
- if (result != expected) {
- failed++;
- g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
- }
- code_size += cfg->code_len;
- mono_destroy_compile (cfg);
-
- } else {
- cfailed++;
- if (verbose)
- g_print ("Test '%s' failed compilation.\n", method->name);
- }
- if (mini_stats_fd)
- fprintf (mini_stats_fd, "%f, ",
- g_timer_elapsed (timer, NULL) - start_time);
- }
+ if (do_single_method_regression) {
+ GSList *iter;
+
+ mini_regression_step (image, verbose, total_run, &total,
+ 0,
+ timer, domain);
+ if (total)
+ return total;
+ g_print ("Single method regression: %d methods\n", g_slist_length (single_method_list));
+
+ for (iter = single_method_list; iter; iter = g_slist_next (iter)) {
+ char *method_name;
+
+ current_single_method = iter->data;
+
+ method_name = mono_method_full_name (current_single_method, TRUE);
+ g_print ("Current single method: %s\n", method_name);
+ g_free (method_name);
+
+ mini_regression_step (image, verbose, total_run, &total,
+ 0,
+ timer, domain);
+ if (total)
+ return total;
}
- if (mini_stats_fd)
- fprintf (mini_stats_fd, "],\n");
- g_timer_stop (timer);
- elapsed = g_timer_elapsed (timer, NULL);
- if (failed > 0 || cfailed > 0){
- g_print ("Results: total tests: %d, failed: %d, cfailed: %d (pass: %.2f%%)\n",
- run, failed, cfailed, 100.0*(run-failed-cfailed)/run);
- } else {
- g_print ("Results: total tests: %d, all pass \n", run);
+ } else {
+ for (opt = 0; opt < G_N_ELEMENTS (opt_sets); ++opt) {
+ mini_regression_step (image, verbose, total_run, &total,
+ opt_sets [opt] & ~exclude,
+ timer, domain);
}
-
- g_print ("Elapsed time: %f secs (%f, %f), Code size: %d\n\n", elapsed,
- elapsed - comp_time, comp_time, code_size);
- total += failed + cfailed;
- *total_run += run;
}
if (mini_stats_fd) {
@@ -829,6 +896,7 @@
enum {
DO_BENCH,
DO_REGRESSION,
+ DO_SINGLE_METHOD_REGRESSION,
DO_COMPILE,
DO_EXEC,
DO_DRAW,
@@ -888,7 +956,7 @@ enum {
g_print ("Compiling %d %s\n", count, desc);
g_free (desc);
}
- cfg = mini_method_compile (method, args->opts, mono_get_root_domain (), FALSE, FALSE, 0);
+ cfg = mini_method_compile (method, mono_get_optimizations_for_method (method, args->opts), mono_get_root_domain (), FALSE, FALSE, 0);
if (cfg->exception_type != MONO_EXCEPTION_NONE) {
printf ("Compilation of %s failed with exception '%s':\n", mono_method_full_name (cfg->method, TRUE), cfg->exception_message);
fail_count ++;
@@ -1100,6 +1168,7 @@ static void main_thread_handler (gpointer user_data)
" --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"
+ " --single-method=OPTS Runs regressions with only one method optimized with OPTS at any time\n"
" --statfile FILE Sets the stat file to FILE\n"
" --stats Print statistics about the JIT operations\n"
" --wapi=hps|semdel|seminfo IO-layer maintenance\n"
@@ -1486,6 +1555,11 @@ BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved)
break;
if (strcmp (argv [i], "--regression") == 0) {
action = DO_REGRESSION;
+ } else if (strncmp (argv [i], "--single-method=", 16) == 0) {
+ char *full_opts = g_strdup_printf ("-all,%s", argv [i] + 16);
+ action = DO_SINGLE_METHOD_REGRESSION;
+ single_method_regression_opt = parse_optimizations (full_opts);
+ g_free (full_opts);
} 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) {
@@ -1878,6 +1952,8 @@ BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved)
}
switch (action) {
+ case DO_SINGLE_METHOD_REGRESSION:
+ do_single_method_regression = TRUE;
case DO_REGRESSION:
if (mini_regression_list (mini_verbose, argc -i, argv + i)) {
g_print ("Regression ERRORS!\n");
Modified: mono/mini/mini.c
===================================================================
@@ -6138,7 +6138,7 @@ void *mono_global_codeman_reserve (int size)
MonoException *ex = NULL;
gpointer code;
- code = mono_jit_compile_method_with_opt (method, default_opt, &ex);
+ code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), &ex);
if (!code) {
g_assert (ex);
mono_raise_exception (ex);
@@ -6349,7 +6349,7 @@ void *mono_global_codeman_reserve (int size)
if (callee) {
MonoException *jit_ex = NULL;
- info->compiled_method = mono_jit_compile_method_with_opt (callee, default_opt, &jit_ex);
+ info->compiled_method = mono_jit_compile_method_with_opt (callee, mono_get_optimizations_for_method (callee, default_opt), &jit_ex);
if (!info->compiled_method) {
g_free (info);
g_assert (jit_ex);
Modified: mono/mini/mini.h
===================================================================
@@ -1875,6 +1875,7 @@ enum {
/* helper methods */
void mono_disable_optimizations (guint32 opts) MONO_INTERNAL;
void mono_set_optimizations (guint32 opts) MONO_INTERNAL;
+guint32 mono_get_optimizations_for_method (MonoMethod *method, guint32 default_opt) MONO_INTERNAL;
void mono_set_verbose_level (guint32 level) MONO_INTERNAL;
MonoJumpInfoToken* mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token) MONO_INTERNAL;
MonoJumpInfoToken* mono_jump_info_token_new2 (MonoMemPool *mp, MonoImage *image, guint32 token, MonoGenericContext *context) MONO_INTERNAL;
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches