Skip to content

Commit f9ed663

Browse files
authored
Handle untracked causes of invalidation (#421)
There seem to be rare cases where edge invalidations tagged with `"verify_method"` do not list their cause. This adds a fallback target to store such invalidations. Also fixes a few minor issues that triggered internal sanity-checks (testing Symbolics): - ordering of insertion index is not relevant - ordering of methods in edge invalidation is not always the same - keytype of temporary trigger dict
1 parent 169a290 commit f9ed663

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

src/invalidations.jl

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ function Base.show(io::IO, methinvs::MultiMethodInvalidations)
448448
iscompact && print(io, ';')
449449
end
450450

451+
Base.isempty(methinvs::MultiMethodInvalidations) = isempty(methinvs.backedges) && isempty(methinvs.mt_backedges)
452+
451453
function invalidation_trees_logedges(list; exclude_corecompiler::Bool=true)
452454
# transiently we represent the graph as a flat list of nodes, a flat list of children indexes, and a Dict to look up the node index
453455
nodes = EdgeNodeType[]
@@ -493,23 +495,24 @@ function invalidation_trees_logedges(list; exclude_corecompiler::Bool=true)
493495
matchess[idx] = matches
494496
end
495497
elseif matches !== nothing
496-
@assert matchess[idx] == matches
498+
@assert Set(matches) == Set(matchess[idx])
497499
end
498500
idxt = get(nodeidx, target, nothing)
499-
@assert idxt === nothing
500-
idxt = addnode(target)
501+
if idxt === nothing
502+
idxt = addnode(target)
503+
end
501504
addcaller!(calleridxss, idxt => idx)
502505
elseif tag == "verify_methods"
503506
caller, callee = list[i+1]::CodeInstance, list[i+3]::CodeInstance
504507
i += 3
505-
idxt = get(nodeidx, caller, nothing)
506-
if idxt === nothing
507-
idxt = addnode(caller)
508-
end
509508
idx = get(nodeidx, callee, nothing)
510509
if idx === nothing
511510
idx = addnode(callee)
512511
end
512+
idxt = get(nodeidx, caller, nothing)
513+
if idxt === nothing
514+
idxt = addnode(caller)
515+
end
513516
@assert idxt >= idx
514517
idxt > idx && addcaller!(calleridxss, idxt => idx)
515518
else
@@ -552,18 +555,26 @@ function mmi_trees!(nodes::AbstractVector{EdgeNodeType}, calleridxss::Vector{Vec
552555
end
553556
end
554557

555-
mminvs = MultiMethodInvalidations[]
558+
# If anything gets added to `mminv0`, it means the cause occurred outside observation with `@snoop_invalidations`
559+
badarg = Method[]
560+
mminv0 = MultiMethodInvalidations(badarg)
561+
556562
treeindex = Dict{Union{Vector{Method},Binding},Int}()
563+
mminvs = MultiMethodInvalidations[]
557564
for i in eachindex(nodes)
558565
if i iscaller
559566
node = nodes[i]
560567
arg = get(matchess, i, node)
561568
j = get(treeindex, arg, nothing)
562569
if j === nothing
570+
if isa(arg, Binding) || (isa(arg, Vector{Method}) && !isempty(arg))
563571
mminv = MultiMethodInvalidations(arg)
564572
push!(mminvs, mminv)
565573
j = length(mminvs)
566574
treeindex[arg] = j
575+
else
576+
mminv = mminv0
577+
end
567578
else
568579
mminv = mminvs[j]
569580
end
@@ -572,6 +583,7 @@ function mmi_trees!(nodes::AbstractVector{EdgeNodeType}, calleridxss::Vector{Vec
572583
@assert !isassigned(calleridxss, i) || isempty(calleridxss[i])
573584
end
574585
end
586+
isempty(mminv0) || push!(mminvs, mminv0)
575587
return mminvs
576588
end
577589

@@ -627,7 +639,7 @@ function invalidation_trees(list::InvalidationLists; consolidate::Bool=true, kwa
627639
trees = [mtrees; etrees]
628640
else
629641
trees = mtrees
630-
mindex = Dict(tree.method => i for (i, tree) in enumerate(mtrees)) # map method to index in mtrees
642+
mindex = Dict{Union{Method,Binding},Int}(tree.method => i for (i, tree) in enumerate(mtrees)) # map method to index in mtrees
631643
for etree in etrees
632644
methods = etree.methods
633645
if isa(methods, Vector{Method})

0 commit comments

Comments
 (0)