36
36
function _insert_backedges (edges:: Vector{Any} , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} , external:: Bool = false )
37
37
for i = 1 : length (edges)
38
38
codeinst = edges[i]:: CodeInstance
39
- verify_method_graph (codeinst, stack, visiting)
39
+ validation_world = get_world_counter ()
40
+ verify_method_graph (codeinst, stack, visiting, validation_world)
41
+ # After validation, under the world_counter_lock, set max_world to typemax(UInt) for all dependencies
42
+ # (recursively). From that point onward the ordinary backedge mechanism is responsible for maintaining
43
+ # validity.
44
+ @ccall jl_promote_ci_to_current (codeinst:: Any , validation_world:: UInt ):: Cvoid
40
45
minvalid = codeinst. min_world
41
46
maxvalid = codeinst. max_world
47
+ # Finally, if this CI is still valid in some world age and and belongs to an external method(specialization),
48
+ # poke it that mi's cache
42
49
if maxvalid ≥ minvalid && external
43
50
caller = get_ci_mi (codeinst)
44
51
@assert isdefined (codeinst, :inferred ) # See #53586, #53109
@@ -54,9 +61,9 @@ function _insert_backedges(edges::Vector{Any}, stack::Vector{CodeInstance}, visi
54
61
end
55
62
end
56
63
57
- function verify_method_graph (codeinst:: CodeInstance , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} )
64
+ function verify_method_graph (codeinst:: CodeInstance , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} , validation_world :: UInt )
58
65
@assert isempty (stack); @assert isempty (visiting);
59
- child_cycle, minworld, maxworld = verify_method (codeinst, stack, visiting)
66
+ child_cycle, minworld, maxworld = verify_method (codeinst, stack, visiting, validation_world )
60
67
@assert child_cycle == 0
61
68
@assert isempty (stack); @assert isempty (visiting);
62
69
nothing
66
73
# - Visit the entire call graph, starting from edges[idx] to determine if that method is valid
67
74
# - Implements Tarjan's SCC (strongly connected components) algorithm, simplified to remove the count variable
68
75
# and slightly modified with an early termination option once the computation reaches its minimum
69
- function verify_method (codeinst:: CodeInstance , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} )
76
+ function verify_method (codeinst:: CodeInstance , stack:: Vector{CodeInstance} , visiting:: IdDict{CodeInstance,Int} , validation_world :: UInt )
70
77
world = codeinst. min_world
71
78
let max_valid2 = codeinst. max_world
72
79
if max_valid2 ≠ WORLD_AGE_REVALIDATION_SENTINEL
73
80
return 0 , world, max_valid2
74
81
end
75
82
end
76
- current_world = get_world_counter ()
77
- local minworld:: UInt , maxworld:: UInt = 1 , current_world
83
+ local minworld:: UInt , maxworld:: UInt = 1 , validation_world
78
84
@assert get_ci_mi (codeinst). def isa Method
79
85
if haskey (visiting, codeinst)
80
86
return visiting[codeinst], minworld, maxworld
@@ -156,7 +162,7 @@ function verify_method(codeinst::CodeInstance, stack::Vector{CodeInstance}, visi
156
162
end
157
163
callee = edge
158
164
local min_valid2:: UInt , max_valid2:: UInt
159
- child_cycle, min_valid2, max_valid2 = verify_method (callee, stack, visiting)
165
+ child_cycle, min_valid2, max_valid2 = verify_method (callee, stack, visiting, validation_world )
160
166
if minworld < min_valid2
161
167
minworld = min_valid2
162
168
end
@@ -188,16 +194,14 @@ function verify_method(codeinst::CodeInstance, stack::Vector{CodeInstance}, visi
188
194
if maxworld ≠ 0
189
195
@atomic :monotonic child. min_world = minworld
190
196
end
191
- if maxworld == current_world
197
+ @atomic :monotonic child. max_world = maxworld
198
+ if maxworld == validation_world && validation_world == get_world_counter ()
192
199
Base. Compiler. store_backedges (child, child. edges)
193
- @atomic :monotonic child. max_world = typemax (UInt)
194
- else
195
- @atomic :monotonic child. max_world = maxworld
196
200
end
197
201
@assert visiting[child] == length (stack) + 1
198
202
delete! (visiting, child)
199
203
invalidations = _jl_debug_method_invalidation[]
200
- if invalidations != = nothing && maxworld < current_world
204
+ if invalidations != = nothing && maxworld < validation_world
201
205
push! (invalidations, child, " verify_methods" , cause)
202
206
end
203
207
end
0 commit comments