@@ -6,6 +6,7 @@ using ..Compiler: _findsup, store_backedges, JLOptions, get_world_counter,
66 morespecific, RefValue, get_require_world, Vector, IdDict
77using . Core: CodeInstance, MethodInstance
88
9+ const CI_FLAGS_NATIVE_CACHE_VALID = 0b1000
910const WORLD_AGE_REVALIDATION_SENTINEL:: UInt = 1
1011const _jl_debug_method_invalidation = RefValue {Union{Nothing,Vector{Any}}} (nothing )
1112debug_method_invalidation (onoff:: Bool ) =
5354function VerifyMethodInitialState (codeinst:: CodeInstance )
5455 mi = get_ci_mi (codeinst)
5556 def = mi. def:: Method
56- callees = codeinst. edges
57- VerifyMethodInitialState (codeinst, mi, def, callees)
57+ VerifyMethodInitialState (codeinst, mi, def, codeinst. edges)
5858end
5959
6060function VerifyMethodWorkState (dummy_cause:: CodeInstance )
6868
6969# Restore backedges to external targets
7070# `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} )
7372 # determine which CodeInstance objects are still valid in our image
7473 # to enable any applicable new codes
7574 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)
7776 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
8279end
8380
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
8786 validation_world = get_world_counter ()
8887 verify_method_graph (codeinst, validation_world, workspace)
8988 # After validation, under the world_counter_lock, set max_world to typemax(UInt) for all dependencies
9089 # (recursively). From that point onward the ordinary backedge mechanism is responsible for maintaining
9190 # validity.
9291 @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
10992 end
11093end
11194
11295function 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"
115101 child_cycle, minworld, maxworld = verify_method (codeinst, validation_world, workspace)
116102 @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"
119108 nothing
120109end
121110
@@ -197,10 +186,8 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
197186 continue
198187 end
199188
200- minworld, maxworld = get_require_world (), validation_world
201-
202189 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 )
204191 workspace. work_states[current_depth] = VerifyMethodWorkState (work. depth, work. cause, work. recursive_index, :return_to_parent )
205192 continue
206193 end
@@ -209,6 +196,9 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
209196 depth = length (workspace. stack)
210197 workspace. visiting[initial. codeinst] = depth
211198
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+
212202 # Check for invalidation of GlobalRef edges
213203 if (initial. def. did_scan_source & 0x1 ) == 0x0
214204 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
229219 while j <= length (initial. callees)
230220 local min_valid2:: UInt , max_valid2:: UInt
231221 edge = initial. callees[j]
232- @assert ! (edge isa Method)
222+ @assert ! (edge isa Method) " unexpected Method edge indicates corrupt edges list creation "
233223
234224 if edge isa CodeInstance
235225 # Convert CodeInstance to MethodInstance for validation (like original)
@@ -333,12 +323,16 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
333323 child = pop! (workspace. stack)
334324 if result. result_maxworld ≠ 0
335325 @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
336330 end
337331 @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 )
339333 store_backedges (child, child. edges)
340334 end
341- @assert workspace. visiting[child] == length (workspace. stack) + 1
335+ @assert workspace. visiting[child] == length (workspace. stack) + 1 " internal error maintaining workspace "
342336 delete! (workspace. visiting, child)
343337 invalidations = _jl_debug_method_invalidation[]
344338 if invalidations != = nothing && result. result_maxworld < validation_world
@@ -500,15 +494,15 @@ function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n
500494 # Fast path is legal when fully_covers=true
501495 if fully_covers && ! iszero (mi. dispatch_status & METHOD_SIG_LATEST_ONLY)
502496 minworld = meth. primary_world
503- @assert minworld ≤ world
497+ @assert minworld ≤ world " expected method not present in verification world "
504498 maxworld = typemax (UInt)
505499 return minworld, maxworld
506500 end
507501 end
508502 # Fast path is legal when fully_covers=true
509503 if fully_covers && ! iszero (meth. dispatch_status & METHOD_SIG_LATEST_ONLY)
510504 minworld = meth. primary_world
511- @assert minworld ≤ world
505+ @assert minworld ≤ world " expected method not present in verification world "
512506 maxworld = typemax (UInt)
513507 return minworld, maxworld
514508 end
@@ -566,7 +560,7 @@ function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n
566560 end
567561 if interference_fast_path_success
568562 # 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 "
570564 maxworld = typemax (UInt)
571565 return interference_minworld, maxworld
572566 end
@@ -627,13 +621,13 @@ const METHOD_SIG_LATEST_WHICH = 0x1
627621const METHOD_SIG_LATEST_ONLY = 0x2
628622
629623function verify_invokesig (@nospecialize (invokesig), expected:: Method , world:: UInt , matches:: Vector{Any} )
630- @assert invokesig isa Type
624+ @assert invokesig isa Type " corrupt edges list "
631625 local minworld:: UInt , maxworld:: UInt
632626 empty! (matches)
633627 if invokesig === expected. sig && ! iszero (expected. dispatch_status & METHOD_SIG_LATEST_WHICH)
634628 # the invoke match is `expected` for `expected->sig`, unless `expected` is replaced
635629 minworld = expected. primary_world
636- @assert minworld ≤ world
630+ @assert minworld ≤ world " expected method not present in verification world "
637631 maxworld = typemax (UInt)
638632 else
639633 mt = get_methodtable (expected)
@@ -658,7 +652,7 @@ function verify_invokesig(@nospecialize(invokesig), expected::Method, world::UIn
658652end
659653
660654# 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]
663657 return ccall (:jl_call_in_typeinf_world , Any, (Ptr{Any}, Cint), args, length (args))
664658end
0 commit comments