Skip to content

Commit 4dcf357

Browse files
authored
inference: Don't confuse frames in different interpreters (#53627)
Diffractor's abstract interpreter sometimes needs to do side queries using the native interpreter. These are pushed onto the regular inference callstack in anticipation of a future where compiler plugins may want to recurse from the native interpreter back into the Diffractor abstract interpreter. However, this introduced a subtle challenge: When the native interpreter is looking at a frame that is currently on the inference stack, it would treat them as the same, incorrectly merging inference across the two abstract interpreters (which have different semantics and may not be confused). The caches for the two abstract interpreters were already different, so once things are inferred, there's no problem (likely because things were already inferred on the native interpreter), but if not, this could cause subtle and hard to debug problems.
1 parent 321fb2c commit 4dcf357

File tree

4 files changed

+22
-1
lines changed

4 files changed

+22
-1
lines changed

base/compiler/abstractinterpretation.jl

+4
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,10 @@ function edge_matches_sv(interp::AbstractInterpreter, frame::AbsIntState,
689689
if callee_method2 !== inf_method2
690690
return false
691691
end
692+
if isa(frame, InferenceState) && cache_owner(frame.interp) !== cache_owner(interp)
693+
# Don't assume that frames in different interpreters are the same
694+
return false
695+
end
692696
if !hardlimit || InferenceParams(interp).ignore_recursion_hardlimit
693697
# if this is a soft limit,
694698
# also inspect the parent of this edge,

base/compiler/inferencestate.jl

+11
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,16 @@ function empty_backedges!(frame::InferenceState, currpc::Int=frame.currpc)
731731
end
732732

733733
function print_callstack(sv::InferenceState)
734+
print("=================== Callstack: ==================\n")
735+
idx = 0
734736
while sv !== nothing
737+
print("[")
738+
print(idx)
739+
if !isa(sv.interp, NativeInterpreter)
740+
print(", ")
741+
print(typeof(sv.interp))
742+
end
743+
print("] ")
735744
print(sv.linfo)
736745
is_cached(sv) || print(" [uncached]")
737746
println()
@@ -740,7 +749,9 @@ function print_callstack(sv::InferenceState)
740749
println()
741750
end
742751
sv = sv.parent
752+
idx += 1
743753
end
754+
print("================= End callstack ==================\n")
744755
end
745756

746757
function narguments(sv::InferenceState, include_va::Bool=true)

base/compiler/typeinfer.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ function merge_call_chain!(interp::AbstractInterpreter, parent::InferenceState,
746746
end
747747

748748
function is_same_frame(interp::AbstractInterpreter, mi::MethodInstance, frame::InferenceState)
749-
return mi === frame_instance(frame)
749+
return mi === frame_instance(frame) && cache_owner(interp) === cache_owner(frame.interp)
750750
end
751751

752752
function poison_callstack!(infstate::InferenceState, topmost::InferenceState)

base/show.jl

+6
Original file line numberDiff line numberDiff line change
@@ -2888,6 +2888,12 @@ show(io::IO, ::Core.Compiler.NativeInterpreter) =
28882888
show(io::IO, cache::Core.Compiler.CachedMethodTable) =
28892889
print(io, typeof(cache), "(", Core.Compiler.length(cache.cache), " entries)")
28902890

2891+
function show(io::IO, limited::Core.Compiler.LimitedAccuracy)
2892+
print(io, "Core.Compiler.LimitedAccuracy(")
2893+
show(io, limited.typ)
2894+
print(io, ", #= ", Core.Compiler.length(limited.causes), " cause(s) =#)")
2895+
end
2896+
28912897
function dump(io::IOContext, x::SimpleVector, n::Int, indent)
28922898
if isempty(x)
28932899
print(io, "empty SimpleVector")

0 commit comments

Comments
 (0)