diff --git a/src/dump.c b/src/dump.c index 9c3b19b5f1a8d..55bb6915fee07 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1830,7 +1830,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) @@ -1884,7 +1884,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); @@ -1922,9 +1923,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); } } } diff --git a/src/gf.c b/src/gf.c index ef4694de438b2..51fa2f00ba454 100644 --- a/src/gf.c +++ b/src/gf.c @@ -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 @@ -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; } @@ -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); } @@ -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}; @@ -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]; @@ -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);