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