3737function _insert_backedges (edges:: Vector{Any} , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} , mwis:: IdSet{Method} , external:: Bool = false )
3838 for i = 1 : length (edges)
3939 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
4146 minvalid = codeinst. min_world
4247 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
4350 if maxvalid ≥ minvalid && external
4451 caller = get_ci_mi (codeinst)
4552 @assert isdefined (codeinst, :inferred ) # See #53586, #53109
@@ -55,9 +62,9 @@ function _insert_backedges(edges::Vector{Any}, stack::Vector{CodeInstance}, visi
5562 end
5663end
5764
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 )
5966 @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 )
6168 @assert child_cycle == 0
6269 @assert isempty (stack); @assert isempty (visiting);
6370 nothing
6774# - Visit the entire call graph, starting from edges[idx] to determine if that method is valid
6875# - Implements Tarjan's SCC (strongly connected components) algorithm, simplified to remove the count variable
6976# 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 )
7178 world = codeinst. min_world
7279 let max_valid2 = codeinst. max_world
7380 if max_valid2 ≠ WORLD_AGE_REVALIDATION_SENTINEL
7481 return 0 , world, max_valid2
7582 end
7683 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
7985 def = get_ci_mi (codeinst). def
8086 @assert def isa Method
8187 if haskey (visiting, codeinst)
@@ -177,7 +183,7 @@ function verify_method(codeinst::CodeInstance, stack::Vector{CodeInstance}, visi
177183 end
178184 callee = edge
179185 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 )
181187 if minworld < min_valid2
182188 minworld = min_valid2
183189 end
@@ -209,16 +215,14 @@ function verify_method(codeinst::CodeInstance, stack::Vector{CodeInstance}, visi
209215 if maxworld ≠ 0
210216 @atomic :monotonic child. min_world = minworld
211217 end
212- if maxworld == current_world
218+ @atomic :monotonic child. max_world = maxworld
219+ if maxworld == validation_world && validation_world == get_world_counter ()
213220 Base. Compiler. store_backedges (child, child. edges)
214- @atomic :monotonic child. max_world = typemax (UInt)
215- else
216- @atomic :monotonic child. max_world = maxworld
217221 end
218222 @assert visiting[child] == length (stack) + 1
219223 delete! (visiting, child)
220224 invalidations = _jl_debug_method_invalidation[]
221- if invalidations != = nothing && maxworld < current_world
225+ if invalidations != = nothing && maxworld < validation_world
222226 push! (invalidations, child, " verify_methods" , cause)
223227 end
224228 end
0 commit comments