37
37
function _insert_backedges (edges:: Vector{Any} , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} , mwis:: IdSet{Method} , external:: Bool = false )
38
38
for i = 1 : length (edges)
39
39
codeinst = edges[i]:: CodeInstance
40
- verify_method_graph (codeinst, stack, visiting, mwis)
40
+ validation_world = get_world_counter ()
41
+ verify_method_graph (codeinst, stack, visiting, mwis, validation_world)
42
+ # After validation, under the world_counter_lock, set max_world to typemax(UInt) for all dependencies
43
+ # (recursively). From that point onward the ordinary backedge mechanism is responsible for maintaining
44
+ # validity.
45
+ @ccall jl_promote_ci_to_current (codeinst:: Any , validation_world:: UInt ):: Cvoid
41
46
minvalid = codeinst. min_world
42
47
maxvalid = codeinst. max_world
48
+ # Finally, if this CI is still valid in some world age and and belongs to an external method(specialization),
49
+ # poke it that mi's cache
43
50
if maxvalid ≥ minvalid && external
44
51
caller = get_ci_mi (codeinst)
45
52
@assert isdefined (codeinst, :inferred ) # See #53586, #53109
@@ -55,9 +62,9 @@ function _insert_backedges(edges::Vector{Any}, stack::Vector{CodeInstance}, visi
55
62
end
56
63
end
57
64
58
- function verify_method_graph (codeinst:: CodeInstance , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} , mwis:: IdSet{Method} )
65
+ function verify_method_graph (codeinst:: CodeInstance , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} , mwis:: IdSet{Method} , validation_world :: UInt )
59
66
@assert isempty (stack); @assert isempty (visiting);
60
- child_cycle, minworld, maxworld = verify_method (codeinst, stack, visiting, mwis)
67
+ child_cycle, minworld, maxworld = verify_method (codeinst, stack, visiting, mwis, validation_world )
61
68
@assert child_cycle == 0
62
69
@assert isempty (stack); @assert isempty (visiting);
63
70
nothing
67
74
# - Visit the entire call graph, starting from edges[idx] to determine if that method is valid
68
75
# - Implements Tarjan's SCC (strongly connected components) algorithm, simplified to remove the count variable
69
76
# and slightly modified with an early termination option once the computation reaches its minimum
70
- function verify_method (codeinst:: CodeInstance , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} , mwis:: IdSet{Method} )
77
+ function verify_method (codeinst:: CodeInstance , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} , mwis:: IdSet{Method} , validation_world :: UInt )
71
78
world = codeinst. min_world
72
79
let max_valid2 = codeinst. max_world
73
80
if max_valid2 ≠ WORLD_AGE_REVALIDATION_SENTINEL
74
81
return 0 , world, max_valid2
75
82
end
76
83
end
77
- current_world = get_world_counter ()
78
- local minworld:: UInt , maxworld:: UInt = 1 , current_world
84
+ local minworld:: UInt , maxworld:: UInt = 1 , validation_world
79
85
def = get_ci_mi (codeinst). def
80
86
@assert def isa Method
81
87
if haskey (visiting, codeinst)
@@ -177,7 +183,7 @@ function verify_method(codeinst::CodeInstance, stack::Vector{CodeInstance}, visi
177
183
end
178
184
callee = edge
179
185
local min_valid2:: UInt , max_valid2:: UInt
180
- child_cycle, min_valid2, max_valid2 = verify_method (callee, stack, visiting, mwis)
186
+ child_cycle, min_valid2, max_valid2 = verify_method (callee, stack, visiting, mwis, validation_world )
181
187
if minworld < min_valid2
182
188
minworld = min_valid2
183
189
end
@@ -209,16 +215,14 @@ function verify_method(codeinst::CodeInstance, stack::Vector{CodeInstance}, visi
209
215
if maxworld ≠ 0
210
216
@atomic :monotonic child. min_world = minworld
211
217
end
212
- if maxworld == current_world
218
+ @atomic :monotonic child. max_world = maxworld
219
+ if maxworld == validation_world && validation_world == get_world_counter ()
213
220
Base. Compiler. store_backedges (child, child. edges)
214
- @atomic :monotonic child. max_world = typemax (UInt)
215
- else
216
- @atomic :monotonic child. max_world = maxworld
217
221
end
218
222
@assert visiting[child] == length (stack) + 1
219
223
delete! (visiting, child)
220
224
invalidations = _jl_debug_method_invalidation[]
221
- if invalidations != = nothing && maxworld < current_world
225
+ if invalidations != = nothing && maxworld < validation_world
222
226
push! (invalidations, child, " verify_methods" , cause)
223
227
end
224
228
end
0 commit comments