Skip to content
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

jl_debug_method_invalidation: return a list of instances #35768

Merged
merged 1 commit into from
Jun 3, 2020
Merged
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
13 changes: 8 additions & 5 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -2294,7 +2294,7 @@ static void jl_insert_methods(jl_array_t *list)
}
}

extern int jl_debug_method_invalidation;
extern jl_array_t *_jl_debug_method_invalidation JL_GLOBALLY_ROOTED;

// 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 @@ -2348,7 +2348,8 @@ static void jl_insert_backedges(jl_array_t *list, jl_array_t *targets)
// map(enable, ((list[i] => targets[list[i + 1] .* 2]) for i in 1:2:length(list) if all(valids[list[i + 1]])))
size_t i, l = jl_array_len(list);
jl_array_t *valids = NULL;
JL_GC_PUSH1(&valids);
jl_value_t *loctag = NULL;
JL_GC_PUSH2(&valids, &loctag);
jl_verify_edges(targets, &valids);
for (i = 0; i < l; i += 2) {
jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
Expand Down Expand Up @@ -2386,9 +2387,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_debug_method_invalidation) {
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)caller);
loctag = jl_cstr_to_string("insert_backedges");
jl_gc_wb(_jl_debug_method_invalidation, loctag);
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
}
}
}
Expand Down
96 changes: 75 additions & 21 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1485,17 +1485,33 @@ 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;
jl_array_t *_jl_debug_method_invalidation JL_GLOBALLY_ROOTED = NULL;
JL_DLLEXPORT jl_value_t *jl_debug_method_invalidation(int state)
{
/* After calling with `state = 1`, caller is responsible for
holding a reference to the returned array until this is called
again with `state = 0`. */
if (state) {
if (_jl_debug_method_invalidation)
return (jl_value_t*) _jl_debug_method_invalidation;
_jl_debug_method_invalidation = jl_alloc_array_1d(jl_array_any_type, 0);
return (jl_value_t*) _jl_debug_method_invalidation;
}
_jl_debug_method_invalidation = NULL;
return jl_nothing;
}

// 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) {
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);
if (_jl_debug_method_invalidation) {
jl_value_t *boxeddepth = NULL;
JL_GC_PUSH1(&boxeddepth);
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)replaced);
boxeddepth = jl_box_int32(depth);
jl_array_ptr_1d_push(_jl_debug_method_invalidation, boxeddepth);
jl_gc_wb(_jl_debug_method_invalidation, boxeddepth);
JL_GC_POP();
}
if (!jl_is_method(replaced->def.method))
return; // shouldn't happen, but better to be safe
Expand Down Expand Up @@ -1622,10 +1638,14 @@ 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_debug_method_invalidation) {
jl_value_t *loctag = NULL;
JL_GC_PUSH1(&loctag);
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi);
loctag = jl_cstr_to_string("invalidate_mt_cache");
jl_gc_wb(_jl_debug_method_invalidation, loctag);
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
JL_GC_POP();
}
oldentry->max_world = env->max_world;
}
Expand Down Expand Up @@ -1673,12 +1693,33 @@ JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *metho
jl_typemap_visitor(mt->cache, invalidate_mt_cache, (void*)&mt_cache_env);
// Invalidate the backedges
jl_svec_t *specializations = methodentry->func.method->specializations;
int invalidated = 0;
jl_value_t *loctag = NULL;
JL_GC_PUSH1(&loctag);
size_t i, l = jl_svec_len(specializations);
for (i = 0; i < l; i++) {
jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i);
if (mi)
invalidate_backedges(mi, methodentry->max_world);
if (mi) {
invalidated = 1;
if (invalidate_backedges(mi, methodentry->max_world))
if (_jl_debug_method_invalidation) {
if (!loctag) {
loctag = jl_cstr_to_string("jl_method_table_disable");
jl_gc_wb(_jl_debug_method_invalidation, loctag);
}
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
}
}
}
if (invalidated && _jl_debug_method_invalidation) {
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)method);
if (!loctag) {
loctag = jl_cstr_to_string("jl_method_table_disable");
jl_gc_wb(_jl_debug_method_invalidation, loctag);
}
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
}
JL_GC_POP();
JL_UNLOCK(&mt->writelock);
}

Expand All @@ -1693,7 +1734,8 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
method->primary_world = ++jl_world_counter;
size_t max_world = method->primary_world - 1;
int invalidated = 0;
JL_GC_PUSH1(&oldvalue);
jl_value_t *loctag = NULL; // debug info for invalidation
JL_GC_PUSH2(&oldvalue, &loctag);
JL_LOCK(&mt->writelock);
// first delete the existing entry (we'll disable it later)
struct jl_typemap_assoc search = {(jl_value_t*)type, method->primary_world, NULL, 0, ~(size_t)0};
Expand Down Expand Up @@ -1722,6 +1764,8 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
jl_method_instance_t *backedge = (jl_method_instance_t*)backedges[i];
invalidate_method_instance(backedge, max_world, 0);
invalidated = 1;
if (_jl_debug_method_invalidation)
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)backedgetyp);
}
else {
backedges[ins++] = backedges[i - 1];
Expand Down Expand Up @@ -1767,17 +1811,27 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
for (i = 0; i < l; i++) {
jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i);
if (mi != NULL && !jl_has_empty_intersection(type, (jl_value_t*)mi->specTypes))
if (invalidate_backedges(mi, max_world))
if (invalidate_backedges(mi, max_world)) {
invalidated = 1;
if (_jl_debug_method_invalidation) {
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi);
if (!loctag) {
loctag = jl_cstr_to_string("jl_method_table_insert");
jl_gc_wb(_jl_debug_method_invalidation, loctag);
}
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
}
}
}
}
}
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_debug_method_invalidation) {
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)method);
if (!loctag) {
loctag = jl_cstr_to_string("jl_method_table_insert");
jl_gc_wb(_jl_debug_method_invalidation, loctag);
}
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
}
update_max_args(mt, type);
JL_UNLOCK(&mt->writelock);
Expand Down