Skip to content

Commit f33697a

Browse files
committed
jl_debug_method_invalidation: return a list of instances, signatures, and tags
Rather than print debug info, this stores the relevant entities to an array. This facilitates easier analysis of the causes, for example making it possible to automatically walk the hierarchy of related code objects (methods, functions, signature types), perform type-intersection, etc. Analysis code will live outside Julia proper (SnoopCompile and MethodAnalysis are two early "consumers").
1 parent ddf7ce9 commit f33697a

File tree

2 files changed

+83
-26
lines changed

2 files changed

+83
-26
lines changed

src/dump.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,7 +2294,7 @@ static void jl_insert_methods(jl_array_t *list)
22942294
}
22952295
}
22962296

2297-
extern int jl_debug_method_invalidation;
2297+
extern jl_array_t *_jl_debug_method_invalidation JL_GLOBALLY_ROOTED;
22982298

22992299
// verify that these edges intersect with the same methods as before
23002300
static void jl_verify_edges(jl_array_t *targets, jl_array_t **pvalids)
@@ -2348,7 +2348,8 @@ static void jl_insert_backedges(jl_array_t *list, jl_array_t *targets)
23482348
// map(enable, ((list[i] => targets[list[i + 1] .* 2]) for i in 1:2:length(list) if all(valids[list[i + 1]])))
23492349
size_t i, l = jl_array_len(list);
23502350
jl_array_t *valids = NULL;
2351-
JL_GC_PUSH1(&valids);
2351+
jl_value_t *loctag = NULL;
2352+
JL_GC_PUSH2(&valids, &loctag);
23522353
jl_verify_edges(targets, &valids);
23532354
for (i = 0; i < l; i += 2) {
23542355
jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
@@ -2386,9 +2387,11 @@ static void jl_insert_backedges(jl_array_t *list, jl_array_t *targets)
23862387
}
23872388
}
23882389
else {
2389-
if (jl_debug_method_invalidation) {
2390-
jl_static_show(JL_STDOUT, (jl_value_t*)caller);
2391-
jl_uv_puts(JL_STDOUT, "<<<\n", 4);
2390+
if (_jl_debug_method_invalidation) {
2391+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)caller);
2392+
loctag = jl_cstr_to_string("insert_backedges");
2393+
jl_gc_wb(_jl_debug_method_invalidation, loctag);
2394+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
23922395
}
23932396
}
23942397
}

src/gf.c

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,17 +1485,33 @@ static void update_max_args(jl_methtable_t *mt, jl_value_t *type)
14851485
mt->max_args = na;
14861486
}
14871487

1488-
JL_DLLEXPORT int jl_debug_method_invalidation = 0;
1488+
jl_array_t *_jl_debug_method_invalidation JL_GLOBALLY_ROOTED = NULL;
1489+
JL_DLLEXPORT jl_value_t *jl_debug_method_invalidation(int state)
1490+
{
1491+
/* After calling with `state = 1`, caller is responsible for
1492+
holding a reference to the returned array until this is called
1493+
again with `state = 0`. */
1494+
if (state) {
1495+
if (_jl_debug_method_invalidation)
1496+
return (jl_value_t*) _jl_debug_method_invalidation;
1497+
_jl_debug_method_invalidation = jl_alloc_array_1d(jl_array_any_type, 0);
1498+
return (jl_value_t*) _jl_debug_method_invalidation;
1499+
}
1500+
_jl_debug_method_invalidation = NULL;
1501+
return jl_nothing;
1502+
}
14891503

14901504
// recursively invalidate cached methods that had an edge to a replaced method
14911505
static void invalidate_method_instance(jl_method_instance_t *replaced, size_t max_world, int depth)
14921506
{
1493-
if (jl_debug_method_invalidation) {
1494-
int d0 = depth;
1495-
while (d0-- > 0)
1496-
jl_uv_puts(JL_STDOUT, " ", 1);
1497-
jl_static_show(JL_STDOUT, (jl_value_t*)replaced);
1498-
jl_uv_puts(JL_STDOUT, "\n", 1);
1507+
if (_jl_debug_method_invalidation) {
1508+
jl_value_t *boxeddepth = NULL;
1509+
JL_GC_PUSH1(&boxeddepth);
1510+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)replaced);
1511+
boxeddepth = jl_box_int32(depth);
1512+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, boxeddepth);
1513+
jl_gc_wb(_jl_debug_method_invalidation, boxeddepth);
1514+
JL_GC_POP();
14991515
}
15001516
if (!jl_is_method(replaced->def.method))
15011517
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)
16221638
}
16231639
}
16241640
if (intersects) {
1625-
if (jl_debug_method_invalidation) {
1626-
jl_uv_puts(JL_STDOUT, "-- ", 3);
1627-
jl_static_show(JL_STDOUT, (jl_value_t*)mi);
1628-
jl_uv_puts(JL_STDOUT, "\n", 1);
1641+
if (_jl_debug_method_invalidation) {
1642+
jl_value_t *loctag = NULL;
1643+
JL_GC_PUSH1(&loctag);
1644+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi);
1645+
loctag = jl_cstr_to_string("invalidate_mt_cache");
1646+
jl_gc_wb(_jl_debug_method_invalidation, loctag);
1647+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
1648+
JL_GC_POP();
16291649
}
16301650
oldentry->max_world = env->max_world;
16311651
}
@@ -1673,12 +1693,33 @@ JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *metho
16731693
jl_typemap_visitor(mt->cache, invalidate_mt_cache, (void*)&mt_cache_env);
16741694
// Invalidate the backedges
16751695
jl_svec_t *specializations = methodentry->func.method->specializations;
1696+
int invalidated = 0;
1697+
jl_value_t *loctag = NULL;
1698+
JL_GC_PUSH1(&loctag);
16761699
size_t i, l = jl_svec_len(specializations);
16771700
for (i = 0; i < l; i++) {
16781701
jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i);
1679-
if (mi)
1680-
invalidate_backedges(mi, methodentry->max_world);
1702+
if (mi) {
1703+
invalidated = 1;
1704+
if (invalidate_backedges(mi, methodentry->max_world))
1705+
if (_jl_debug_method_invalidation) {
1706+
if (!loctag) {
1707+
loctag = jl_cstr_to_string("jl_method_table_disable");
1708+
jl_gc_wb(_jl_debug_method_invalidation, loctag);
1709+
}
1710+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
1711+
}
1712+
}
1713+
}
1714+
if (invalidated && _jl_debug_method_invalidation) {
1715+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)method);
1716+
if (!loctag) {
1717+
loctag = jl_cstr_to_string("jl_method_table_disable");
1718+
jl_gc_wb(_jl_debug_method_invalidation, loctag);
1719+
}
1720+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
16811721
}
1722+
JL_GC_POP();
16821723
JL_UNLOCK(&mt->writelock);
16831724
}
16841725

@@ -1693,7 +1734,8 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
16931734
method->primary_world = ++jl_world_counter;
16941735
size_t max_world = method->primary_world - 1;
16951736
int invalidated = 0;
1696-
JL_GC_PUSH1(&oldvalue);
1737+
jl_value_t *loctag = NULL; // debug info for invalidation
1738+
JL_GC_PUSH2(&oldvalue, &loctag);
16971739
JL_LOCK(&mt->writelock);
16981740
// first delete the existing entry (we'll disable it later)
16991741
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
17221764
jl_method_instance_t *backedge = (jl_method_instance_t*)backedges[i];
17231765
invalidate_method_instance(backedge, max_world, 0);
17241766
invalidated = 1;
1767+
if (_jl_debug_method_invalidation)
1768+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)backedgetyp);
17251769
}
17261770
else {
17271771
backedges[ins++] = backedges[i - 1];
@@ -1767,17 +1811,27 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
17671811
for (i = 0; i < l; i++) {
17681812
jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i);
17691813
if (mi != NULL && !jl_has_empty_intersection(type, (jl_value_t*)mi->specTypes))
1770-
if (invalidate_backedges(mi, max_world))
1814+
if (invalidate_backedges(mi, max_world)) {
17711815
invalidated = 1;
1816+
if (_jl_debug_method_invalidation) {
1817+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi);
1818+
if (!loctag) {
1819+
loctag = jl_cstr_to_string("jl_method_table_insert");
1820+
jl_gc_wb(_jl_debug_method_invalidation, loctag);
1821+
}
1822+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
1823+
}
1824+
}
17721825
}
17731826
}
17741827
}
1775-
if (invalidated && jl_debug_method_invalidation) {
1776-
jl_uv_puts(JL_STDOUT, ">> ", 3);
1777-
jl_static_show(JL_STDOUT, (jl_value_t*)method);
1778-
jl_uv_puts(JL_STDOUT, " ", 1);
1779-
jl_static_show(JL_STDOUT, (jl_value_t*)type);
1780-
jl_uv_puts(JL_STDOUT, "\n", 1);
1828+
if (invalidated && _jl_debug_method_invalidation) {
1829+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)method);
1830+
if (!loctag) {
1831+
loctag = jl_cstr_to_string("jl_method_table_insert");
1832+
jl_gc_wb(_jl_debug_method_invalidation, loctag);
1833+
}
1834+
jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
17811835
}
17821836
update_max_args(mt, type);
17831837
JL_UNLOCK(&mt->writelock);

0 commit comments

Comments
 (0)