@@ -6,6 +6,7 @@ using ..Compiler: _findsup, store_backedges, JLOptions, get_world_counter,
6
6
morespecific, RefValue, get_require_world, Vector, IdDict
7
7
using . Core: CodeInstance, MethodInstance
8
8
9
+ const CI_FLAGS_NATIVE_CACHE_VALID = 0b1000
9
10
const WORLD_AGE_REVALIDATION_SENTINEL:: UInt = 1
10
11
const _jl_debug_method_invalidation = RefValue {Union{Nothing,Vector{Any}}} (nothing )
11
12
debug_method_invalidation (onoff:: Bool ) =
53
54
function VerifyMethodInitialState (codeinst:: CodeInstance )
54
55
mi = get_ci_mi (codeinst)
55
56
def = mi. def:: Method
56
- callees = codeinst. edges
57
- VerifyMethodInitialState (codeinst, mi, def, callees)
57
+ VerifyMethodInitialState (codeinst, mi, def, codeinst. edges)
58
58
end
59
59
60
60
function VerifyMethodWorkState (dummy_cause:: CodeInstance )
68
68
69
69
# Restore backedges to external targets
70
70
# `edges` = [caller1, ...], the list of worklist-owned code instances internally
71
- # `ext_ci_list` = [caller1, ...], the list of worklist-owned code instances externally
72
- function insert_backedges (edges:: Vector{Any} , ext_ci_list:: Union{Nothing,Vector{Any}} , extext_methods:: Vector{Any} , internal_methods:: Vector{Any} )
71
+ function insert_backedges (internal_methods:: Vector{Any} )
73
72
# determine which CodeInstance objects are still valid in our image
74
73
# to enable any applicable new codes
75
74
backedges_only = unsafe_load (cglobal (:jl_first_image_replacement_world , UInt)) == typemax (UInt)
76
- scan_new_methods! (extext_methods, internal_methods, backedges_only)
75
+ scan_new_methods! (internal_methods, backedges_only)
77
76
workspace = VerifyMethodWorkspace ()
78
- _insert_backedges (edges, workspace)
79
- if ext_ci_list != = nothing
80
- _insert_backedges (ext_ci_list, workspace, #= external=# true )
81
- end
77
+ scan_new_code! (internal_methods, workspace)
78
+ nothing
82
79
end
83
80
84
- function _insert_backedges (edges:: Vector{Any} , workspace:: VerifyMethodWorkspace , external:: Bool = false )
85
- for i = 1 : length (edges)
86
- codeinst = edges[i]:: CodeInstance
81
+ function scan_new_code! (internal_methods:: Vector{Any} , workspace:: VerifyMethodWorkspace )
82
+ for i = 1 : length (internal_methods)
83
+ codeinst = internal_methods[i]
84
+ codeinst isa CodeInstance || continue
85
+ # codeinst.owner === nothing || continue
87
86
validation_world = get_world_counter ()
88
87
verify_method_graph (codeinst, validation_world, workspace)
89
88
# After validation, under the world_counter_lock, set max_world to typemax(UInt) for all dependencies
90
89
# (recursively). From that point onward the ordinary backedge mechanism is responsible for maintaining
91
90
# validity.
92
91
@ccall jl_promote_ci_to_current (codeinst:: Any , validation_world:: UInt ):: Cvoid
93
- minvalid = codeinst. min_world
94
- maxvalid = codeinst. max_world
95
- # Finally, if this CI is still valid in some world age and belongs to an external method(specialization),
96
- # poke it that mi's cache
97
- if maxvalid ≥ minvalid && external
98
- caller = get_ci_mi (codeinst)
99
- @assert isdefined (codeinst, :inferred ) # See #53586, #53109
100
- inferred = @ccall jl_rettype_inferred (
101
- codeinst. owner:: Any , caller:: Any , minvalid:: UInt , maxvalid:: UInt ):: Any
102
- if inferred != = nothing
103
- # We already got a code instance for this world age range from
104
- # somewhere else - we don't need this one.
105
- else
106
- @ccall jl_mi_cache_insert (caller:: Any , codeinst:: Any ):: Cvoid
107
- end
108
- end
109
92
end
110
93
end
111
94
112
95
function verify_method_graph (codeinst:: CodeInstance , validation_world:: UInt , workspace:: VerifyMethodWorkspace )
113
- @assert isempty (workspace. stack); @assert isempty (workspace. visiting);
114
- @assert isempty (workspace. initial_states); @assert isempty (workspace. work_states); @assert isempty (workspace. result_states)
96
+ @assert isempty (workspace. stack) " workspace corrupted"
97
+ @assert isempty (workspace. visiting) " workspace corrupted"
98
+ @assert isempty (workspace. initial_states) " workspace corrupted"
99
+ @assert isempty (workspace. work_states) " workspace corrupted"
100
+ @assert isempty (workspace. result_states) " workspace corrupted"
115
101
child_cycle, minworld, maxworld = verify_method (codeinst, validation_world, workspace)
116
102
@assert child_cycle == 0
117
- @assert isempty (workspace. stack); @assert isempty (workspace. visiting);
118
- @assert isempty (workspace. initial_states); @assert isempty (workspace. work_states); @assert isempty (workspace. result_states)
103
+ @assert isempty (workspace. stack) " workspace corrupted"
104
+ @assert isempty (workspace. visiting) " workspace corrupted"
105
+ @assert isempty (workspace. initial_states) " workspace corrupted"
106
+ @assert isempty (workspace. work_states) " workspace corrupted"
107
+ @assert isempty (workspace. result_states) " workspace corrupted"
119
108
nothing
120
109
end
121
110
@@ -197,10 +186,8 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
197
186
continue
198
187
end
199
188
200
- minworld, maxworld = get_require_world (), validation_world
201
-
202
189
if haskey (workspace. visiting, initial. codeinst)
203
- workspace. result_states[current_depth] = VerifyMethodResultState (workspace. visiting[initial. codeinst], minworld, maxworld )
190
+ workspace. result_states[current_depth] = VerifyMethodResultState (workspace. visiting[initial. codeinst], UInt ( 1 ), validation_world )
204
191
workspace. work_states[current_depth] = VerifyMethodWorkState (work. depth, work. cause, work. recursive_index, :return_to_parent )
205
192
continue
206
193
end
@@ -209,6 +196,9 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
209
196
depth = length (workspace. stack)
210
197
workspace. visiting[initial. codeinst] = depth
211
198
199
+ # unable to backdate before require_world, since Bindings are not able to track that information
200
+ minworld, maxworld = get_require_world (), validation_world
201
+
212
202
# Check for invalidation of GlobalRef edges
213
203
if (initial. def. did_scan_source & 0x1 ) == 0x0
214
204
backedges_only = unsafe_load (cglobal (:jl_first_image_replacement_world , UInt)) == typemax (UInt)
@@ -229,7 +219,7 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
229
219
while j <= length (initial. callees)
230
220
local min_valid2:: UInt , max_valid2:: UInt
231
221
edge = initial. callees[j]
232
- @assert ! (edge isa Method)
222
+ @assert ! (edge isa Method) " unexpected Method edge indicates corrupt edges list creation "
233
223
234
224
if edge isa CodeInstance
235
225
# Convert CodeInstance to MethodInstance for validation (like original)
@@ -333,12 +323,16 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
333
323
child = pop! (workspace. stack)
334
324
if result. result_maxworld ≠ 0
335
325
@atomic :monotonic child. min_world = result. result_minworld
326
+ # Finally, if this CI is still valid in some world age and marked as valid in the native cache, poke it in that mi's cache now
327
+ if child. flags & CI_FLAGS_NATIVE_CACHE_VALID == CI_FLAGS_NATIVE_CACHE_VALID
328
+ @ccall jl_mi_cache_insert (get_ci_mi (child):: Any , child:: Any ):: Cvoid
329
+ end
336
330
end
337
331
@atomic :monotonic child. max_world = result. result_maxworld
338
- if result. result_maxworld == validation_world && validation_world == get_world_counter ()
332
+ if result. result_maxworld == validation_world && validation_world == get_world_counter () && isdefined (child, :edges )
339
333
store_backedges (child, child. edges)
340
334
end
341
- @assert workspace. visiting[child] == length (workspace. stack) + 1
335
+ @assert workspace. visiting[child] == length (workspace. stack) + 1 " internal error maintaining workspace "
342
336
delete! (workspace. visiting, child)
343
337
invalidations = _jl_debug_method_invalidation[]
344
338
if invalidations != = nothing && result. result_maxworld < validation_world
@@ -500,15 +494,15 @@ function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n
500
494
# Fast path is legal when fully_covers=true
501
495
if fully_covers && ! iszero (mi. dispatch_status & METHOD_SIG_LATEST_ONLY)
502
496
minworld = meth. primary_world
503
- @assert minworld ≤ world
497
+ @assert minworld ≤ world " expected method not present in verification world "
504
498
maxworld = typemax (UInt)
505
499
return minworld, maxworld
506
500
end
507
501
end
508
502
# Fast path is legal when fully_covers=true
509
503
if fully_covers && ! iszero (meth. dispatch_status & METHOD_SIG_LATEST_ONLY)
510
504
minworld = meth. primary_world
511
- @assert minworld ≤ world
505
+ @assert minworld ≤ world " expected method not present in verification world "
512
506
maxworld = typemax (UInt)
513
507
return minworld, maxworld
514
508
end
@@ -566,7 +560,7 @@ function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n
566
560
end
567
561
if interference_fast_path_success
568
562
# All interference sets are covered by expecteds, can return success
569
- @assert interference_minworld ≤ world
563
+ @assert interference_minworld ≤ world " expected method not present in verification world "
570
564
maxworld = typemax (UInt)
571
565
return interference_minworld, maxworld
572
566
end
@@ -627,13 +621,13 @@ const METHOD_SIG_LATEST_WHICH = 0x1
627
621
const METHOD_SIG_LATEST_ONLY = 0x2
628
622
629
623
function verify_invokesig (@nospecialize (invokesig), expected:: Method , world:: UInt , matches:: Vector{Any} )
630
- @assert invokesig isa Type
624
+ @assert invokesig isa Type " corrupt edges list "
631
625
local minworld:: UInt , maxworld:: UInt
632
626
empty! (matches)
633
627
if invokesig === expected. sig && ! iszero (expected. dispatch_status & METHOD_SIG_LATEST_WHICH)
634
628
# the invoke match is `expected` for `expected->sig`, unless `expected` is replaced
635
629
minworld = expected. primary_world
636
- @assert minworld ≤ world
630
+ @assert minworld ≤ world " expected method not present in verification world "
637
631
maxworld = typemax (UInt)
638
632
else
639
633
mt = get_methodtable (expected)
@@ -658,7 +652,7 @@ function verify_invokesig(@nospecialize(invokesig), expected::Method, world::UIn
658
652
end
659
653
660
654
# Wrapper to call insert_backedges in typeinf_world for external calls
661
- function insert_backedges_typeinf (edges :: Vector{Any} , ext_ci_list :: Union{Nothing,Vector{Any}} , extext_methods :: Vector{Any} , internal_methods:: Vector{Any} )
662
- args = Any[insert_backedges, edges, ext_ci_list, extext_methods, internal_methods]
655
+ function insert_backedges_typeinf (internal_methods:: Vector{Any} )
656
+ args = Any[insert_backedges, internal_methods]
663
657
return ccall (:jl_call_in_typeinf_world , Any, (Ptr{Any}, Cint), args, length (args))
664
658
end
0 commit comments