Skip to content

RFC: add a command line option to print out method invalidations to stderr or a file #35745

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions base/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
10 changes: 5 additions & 5 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
36 changes: 20 additions & 16 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 20 additions & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
}
Expand Down
12 changes: 11 additions & 1 deletion src/jloptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down