From 9d0591110a94b9dac0aa243c7a15cafbcf4b899e Mon Sep 17 00:00:00 2001 From: KristofferC Date: Tue, 5 May 2020 14:30:21 +0200 Subject: [PATCH] add a command line option to print out method invalidations to stderr or a file --- base/options.jl | 1 + src/dump.c | 10 +++++----- src/gf.c | 36 ++++++++++++++++++++---------------- src/init.c | 20 ++++++++++++++++++++ src/jloptions.c | 12 +++++++++++- src/julia.h | 1 + src/julia_internal.h | 4 ++++ 7 files changed, 62 insertions(+), 22 deletions(-) diff --git a/base/options.jl b/base/options.jl index 205480817a904..692e7191a044b 100644 --- a/base/options.jl +++ b/base/options.jl @@ -28,6 +28,7 @@ struct JLOptions can_inline::Int8 polly::Int8 trace_compile::Ptr{UInt8} + trace_method_invalidations::Ptr{UInt8} fast_math::Int8 worker::Int8 cookie::Ptr{UInt8} diff --git a/src/dump.c b/src/dump.c index 0e96c025ffbde..3ad59e72c1722 100644 --- a/src/dump.c +++ b/src/dump.c @@ -2294,8 +2294,6 @@ static void jl_insert_methods(jl_array_t *list) } } -extern int jl_debug_method_invalidation; - // verify that these edges intersect with the same methods as before static void jl_verify_edges(jl_array_t *targets, jl_array_t **pvalids) { @@ -2386,9 +2384,11 @@ static void jl_insert_backedges(jl_array_t *list, jl_array_t *targets) } } else { - if (jl_debug_method_invalidation) { - jl_static_show(JL_STDOUT, (jl_value_t*)caller); - jl_uv_puts(JL_STDOUT, "<<<\n", 4); + if (jl_options.trace_method_invalidations != NULL) { + jl_static_show(jl_s_method_invalidated, (jl_value_t*)caller); + jl_uv_puts(jl_s_method_invalidated, "<<<\n", 4); + if (jl_s_method_invalidated != JL_STDERR) + ios_flush(&jl_f_method_invalidated); } } } diff --git a/src/gf.c b/src/gf.c index 183a6c74d7187..30679e157b6da 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1485,17 +1485,17 @@ static void update_max_args(jl_methtable_t *mt, jl_value_t *type) mt->max_args = na; } -JL_DLLEXPORT int jl_debug_method_invalidation = 0; - // recursively invalidate cached methods that had an edge to a replaced method static void invalidate_method_instance(jl_method_instance_t *replaced, size_t max_world, int depth) { - if (jl_debug_method_invalidation) { + if (jl_options.trace_method_invalidations != NULL) { int d0 = depth; while (d0-- > 0) - jl_uv_puts(JL_STDOUT, " ", 1); - jl_static_show(JL_STDOUT, (jl_value_t*)replaced); - jl_uv_puts(JL_STDOUT, "\n", 1); + jl_uv_puts(jl_s_method_invalidated, " ", 1); + jl_static_show(jl_s_method_invalidated, (jl_value_t*)replaced); + jl_uv_puts(jl_s_method_invalidated, "\n", 1); + if (jl_s_method_invalidated != JL_STDERR) + ios_flush(&jl_f_method_invalidated); } if (!jl_is_method(replaced->def.method)) return; // shouldn't happen, but better to be safe @@ -1622,10 +1622,12 @@ static int invalidate_mt_cache(jl_typemap_entry_t *oldentry, void *closure0) } } if (intersects) { - if (jl_debug_method_invalidation) { - jl_uv_puts(JL_STDOUT, "-- ", 3); - jl_static_show(JL_STDOUT, (jl_value_t*)mi); - jl_uv_puts(JL_STDOUT, "\n", 1); + if (jl_options.trace_method_invalidations != NULL) { + jl_uv_puts(jl_s_method_invalidated, "-- ", 3); + jl_static_show(jl_s_method_invalidated, (jl_value_t*)mi); + jl_uv_puts(jl_s_method_invalidated, "\n", 1); + if (jl_s_method_invalidated != JL_STDERR) + ios_flush(&jl_f_method_invalidated); } oldentry->max_world = env->max_world; } @@ -1772,12 +1774,14 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method } } } - if (invalidated && jl_debug_method_invalidation) { - jl_uv_puts(JL_STDOUT, ">> ", 3); - jl_static_show(JL_STDOUT, (jl_value_t*)method); - jl_uv_puts(JL_STDOUT, " ", 1); - jl_static_show(JL_STDOUT, (jl_value_t*)type); - jl_uv_puts(JL_STDOUT, "\n", 1); + if (invalidated && jl_options.trace_method_invalidations != NULL) { + jl_uv_puts(jl_s_method_invalidated, ">> ", 3); + jl_static_show(jl_s_method_invalidated, (jl_value_t*)method); + jl_uv_puts(jl_s_method_invalidated, " ", 1); + jl_static_show(jl_s_method_invalidated, (jl_value_t*)type); + jl_uv_puts(jl_s_method_invalidated, "\n", 1); + if (jl_s_method_invalidated != JL_STDERR) + ios_flush(&jl_f_method_invalidated); } update_max_args(mt, type); JL_UNLOCK(&mt->writelock); diff --git a/src/init.c b/src/init.c index 019f97c81a874..3ddc54f8fade8 100644 --- a/src/init.c +++ b/src/init.c @@ -612,6 +612,24 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) } } +ios_t jl_f_method_invalidated; +JL_STREAM* jl_s_method_invalidated; +static void jl_init_method_invalidated_streams(void) { + if (jl_options.trace_method_invalidations != NULL) { + if (jl_s_method_invalidated == NULL) { + const char* t = jl_options.trace_method_invalidations; + if (!strncmp(t, "stderr", 6)) + jl_s_method_invalidated = JL_STDERR; + else { + if (ios_file(&jl_f_method_invalidated, t, 1, 1, 1, 1) == NULL) + jl_errorf("cannot open method invalidation file \"%s\" for writing", t); + jl_s_method_invalidated = (JL_STREAM*) &jl_f_method_invalidated; + } + } + } +} + + static void jl_set_io_wait(int v) { jl_ptls_t ptls = jl_get_ptls_states(); @@ -775,6 +793,8 @@ void _julia_init(JL_IMAGE_SEARCH rel) JL_GC_POP(); } + jl_init_method_invalidated_streams(); + if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON) jl_install_sigint_handler(); } diff --git a/src/jloptions.c b/src/jloptions.c index 8ab0e300cf802..9931c18fef4f2 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -58,6 +58,7 @@ jl_options_t jl_options = { 0, // quiet 1, // can_inline JL_OPTIONS_POLLY_ON, // polly NULL, // trace_compile + NULL, // trace_method_invalidations JL_OPTIONS_FAST_MATH_DEFAULT, 0, // worker NULL, // cookie @@ -161,8 +162,10 @@ static const char opts_hidden[] = " --output-bc name Generate LLVM bitcode (.bc)\n" " --output-asm name Generate an assembly file (.s)\n" " --output-incremental=no Generate an incremental output file (rather than complete)\n" - " --trace-compile={stdout,stderr}\n" + " --trace-compile={name,stderr}\n" " Print precompile statements for methods compiled during execution.\n\n" + " --trace-method-invalidations={name,stderr}\n" + " Print method invalidations.\n\n" ; JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) @@ -183,6 +186,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) opt_inline, opt_polly, opt_trace_compile, + opt_trace_method_invalidations, opt_math_mode, opt_worker, opt_bind_to, @@ -244,6 +248,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) { "inline", required_argument, 0, opt_inline }, { "polly", required_argument, 0, opt_polly }, { "trace-compile", required_argument, 0, opt_trace_compile }, + { "trace-method-invalidations", required_argument, 0, opt_trace_method_invalidations }, { "math-mode", required_argument, 0, opt_math_mode }, { "handle-signals", required_argument, 0, opt_handle_signals }, // hidden command line options @@ -617,6 +622,11 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) if (!jl_options.trace_compile) jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno)); break; + case opt_trace_method_invalidations: + jl_options.trace_method_invalidations = strdup(optarg); + if (!jl_options.trace_method_invalidations) + jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno)); + break; case opt_math_mode: if (!strcmp(optarg,"ieee")) jl_options.fast_math = JL_OPTIONS_FAST_MATH_OFF; diff --git a/src/julia.h b/src/julia.h index 75db3a651ae8b..815e84935464d 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1921,6 +1921,7 @@ typedef struct { int8_t can_inline; int8_t polly; const char *trace_compile; + const char *trace_method_invalidations; int8_t fast_math; int8_t worker; const char *cookie; diff --git a/src/julia_internal.h b/src/julia_internal.h index 46c14cd4df3be..97c7aff9bc7fa 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -905,6 +905,10 @@ JL_DLLEXPORT jl_value_t *jl_get_cfunction_trampoline( jl_unionall_t *env, jl_value_t **vals); +// Method invalidation debug output +extern ios_t jl_f_method_invalidated; +extern JL_STREAM* jl_s_method_invalidated; + // Windows only #define JL_EXE_LIBNAME ((const char*)1) #define JL_DL_LIBNAME ((const char*)2)