2
2
3
3
using .. Compiler. Base
4
4
using .. Compiler: _findsup, store_backedges, JLOptions, get_world_counter,
5
- _methods_by_ftype, get_methodtable, get_ci_mi, ci_has_abi, should_instrument,
5
+ _methods_by_ftype, get_methodtable, get_ci_mi, should_instrument,
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 (ext_ci_list:: Union{Nothing,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
75
scan_new_methods! (internal_methods, backedges_only)
77
76
workspace = VerifyMethodWorkspace ()
78
77
scan_new_code! (internal_methods, workspace)
79
- if ext_ci_list != = nothing
80
- insert_ext_cache (ext_ci_list)
81
- end
82
78
nothing
83
79
end
84
80
@@ -96,35 +92,19 @@ function scan_new_code!(internal_methods::Vector{Any}, workspace::VerifyMethodWo
96
92
end
97
93
end
98
94
99
- function insert_ext_cache (edges:: Vector{Any} )
100
- for i = 1 : length (edges)
101
- codeinst = edges[i]:: CodeInstance
102
- minvalid = codeinst. min_world
103
- maxvalid = codeinst. max_world
104
- # Finally, if this CI is still valid in some world age and belongs to an external method(specialization),
105
- # poke it in that mi's cache, unless there is already one there that has an invoke pointer
106
- if maxvalid ≥ minvalid
107
- caller = get_ci_mi (codeinst)
108
- @assert isdefined (codeinst, :inferred ) # See #53586, #53109
109
- inferred = @ccall jl_rettype_inferred (
110
- codeinst. owner:: Any , caller:: Any , minvalid:: UInt , maxvalid:: UInt ):: Any
111
- if inferred != = nothing && (ci_has_abi (inferred:: CodeInstance ) || ! ci_has_abi (codeinst))
112
- # We already got a code instance for this world age range from
113
- # somewhere else - we don't need this one.
114
- else
115
- @ccall jl_mi_cache_insert (caller:: Any , codeinst:: Any ):: Cvoid
116
- end
117
- end
118
- end
119
- end
120
-
121
95
function verify_method_graph (codeinst:: CodeInstance , validation_world:: UInt , workspace:: VerifyMethodWorkspace )
122
- @assert isempty (workspace. stack); @assert isempty (workspace. visiting);
123
- @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"
124
101
child_cycle, minworld, maxworld = verify_method (codeinst, validation_world, workspace)
125
102
@assert child_cycle == 0
126
- @assert isempty (workspace. stack); @assert isempty (workspace. visiting);
127
- @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"
128
108
nothing
129
109
end
130
110
@@ -206,10 +186,8 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
206
186
continue
207
187
end
208
188
209
- minworld, maxworld = get_require_world (), validation_world
210
-
211
189
if haskey (workspace. visiting, initial. codeinst)
212
- 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 )
213
191
workspace. work_states[current_depth] = VerifyMethodWorkState (work. depth, work. cause, work. recursive_index, :return_to_parent )
214
192
continue
215
193
end
@@ -218,6 +196,9 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
218
196
depth = length (workspace. stack)
219
197
workspace. visiting[initial. codeinst] = depth
220
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
+
221
202
# Check for invalidation of GlobalRef edges
222
203
if (initial. def. did_scan_source & 0x1 ) == 0x0
223
204
backedges_only = unsafe_load (cglobal (:jl_first_image_replacement_world , UInt)) == typemax (UInt)
@@ -238,7 +219,7 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
238
219
while j <= length (initial. callees)
239
220
local min_valid2:: UInt , max_valid2:: UInt
240
221
edge = initial. callees[j]
241
- @assert ! (edge isa Method)
222
+ @assert ! (edge isa Method) " unexpected Method edge indicates corrupt edges list creation "
242
223
243
224
if edge isa CodeInstance
244
225
# Convert CodeInstance to MethodInstance for validation (like original)
@@ -342,12 +323,16 @@ function verify_method(codeinst::CodeInstance, validation_world::UInt, workspace
342
323
child = pop! (workspace. stack)
343
324
if result. result_maxworld ≠ 0
344
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
345
330
end
346
331
@atomic :monotonic child. max_world = result. result_maxworld
347
- 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 )
348
333
store_backedges (child, child. edges)
349
334
end
350
- @assert workspace. visiting[child] == length (workspace. stack) + 1
335
+ @assert workspace. visiting[child] == length (workspace. stack) + 1 " internal error maintaining workspace "
351
336
delete! (workspace. visiting, child)
352
337
invalidations = _jl_debug_method_invalidation[]
353
338
if invalidations != = nothing && result. result_maxworld < validation_world
@@ -509,15 +494,15 @@ function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n
509
494
# Fast path is legal when fully_covers=true
510
495
if fully_covers && ! iszero (mi. dispatch_status & METHOD_SIG_LATEST_ONLY)
511
496
minworld = meth. primary_world
512
- @assert minworld ≤ world
497
+ @assert minworld ≤ world " expected method not present in verification world "
513
498
maxworld = typemax (UInt)
514
499
return minworld, maxworld
515
500
end
516
501
end
517
502
# Fast path is legal when fully_covers=true
518
503
if fully_covers && ! iszero (meth. dispatch_status & METHOD_SIG_LATEST_ONLY)
519
504
minworld = meth. primary_world
520
- @assert minworld ≤ world
505
+ @assert minworld ≤ world " expected method not present in verification world "
521
506
maxworld = typemax (UInt)
522
507
return minworld, maxworld
523
508
end
@@ -575,7 +560,7 @@ function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n
575
560
end
576
561
if interference_fast_path_success
577
562
# All interference sets are covered by expecteds, can return success
578
- @assert interference_minworld ≤ world
563
+ @assert interference_minworld ≤ world " expected method not present in verification world "
579
564
maxworld = typemax (UInt)
580
565
return interference_minworld, maxworld
581
566
end
@@ -636,13 +621,13 @@ const METHOD_SIG_LATEST_WHICH = 0x1
636
621
const METHOD_SIG_LATEST_ONLY = 0x2
637
622
638
623
function verify_invokesig (@nospecialize (invokesig), expected:: Method , world:: UInt , matches:: Vector{Any} )
639
- @assert invokesig isa Type
624
+ @assert invokesig isa Type " corrupt edges list "
640
625
local minworld:: UInt , maxworld:: UInt
641
626
empty! (matches)
642
627
if invokesig === expected. sig && ! iszero (expected. dispatch_status & METHOD_SIG_LATEST_WHICH)
643
628
# the invoke match is `expected` for `expected->sig`, unless `expected` is replaced
644
629
minworld = expected. primary_world
645
- @assert minworld ≤ world
630
+ @assert minworld ≤ world " expected method not present in verification world "
646
631
maxworld = typemax (UInt)
647
632
else
648
633
mt = get_methodtable (expected)
@@ -667,7 +652,7 @@ function verify_invokesig(@nospecialize(invokesig), expected::Method, world::UIn
667
652
end
668
653
669
654
# Wrapper to call insert_backedges in typeinf_world for external calls
670
- function insert_backedges_typeinf (ext_ci_list :: Union{Nothing,Vector{Any}} , internal_methods:: Vector{Any} )
671
- args = Any[insert_backedges, ext_ci_list, internal_methods]
655
+ function insert_backedges_typeinf (internal_methods:: Vector{Any} )
656
+ args = Any[insert_backedges, internal_methods]
672
657
return ccall (:jl_call_in_typeinf_world , Any, (Ptr{Any}, Cint), args, length (args))
673
658
end
0 commit comments