Open timholy opened 3 years ago
I've inserted the following debugging code (everywhere in compiler/
that I can see a reference to max_world
):
diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl
index 988f2eefa2..0542ecfa80 100644
--- a/base/compiler/inferencestate.jl
+++ b/base/compiler/inferencestate.jl
@@ -100,6 +100,9 @@ mutable struct InferenceState
inmodule = linfo.def::Module
end
+ if src.max_world < typemax(UInt)
+ println("here 1 with ", src)
+ end
valid_worlds = WorldRange(src.min_world,
src.max_world == typemax(UInt) ? get_world_counter() : src.max_world)
frame = new(
diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl
index 5082b01ea5..6e63d0d393 100644
--- a/base/compiler/typeinfer.jl
+++ b/base/compiler/typeinfer.jl
@@ -353,6 +353,10 @@ function transform_result_for_cache(interp::AbstractInterpreter, linfo::MethodIn
end
if inferred_result isa CodeInfo
inferred_result.min_world = first(valid_worlds)
+ if last(valid_worlds) < typemax(UInt)
+ println("here 2: inferred_result.max_world = ", inferred_result.max_world)
+ println("setting it to ", last(valid_worlds))
+ end
inferred_result.max_world = last(valid_worlds)
inferred_result = maybe_compress_codeinfo(interp, linfo, inferred_result)
end
@@ -723,6 +727,10 @@ function typeinf_edge(interp::AbstractInterpreter, method::Method, @nospecialize
mi = specialize_method(method, atypes, sparams)::MethodInstance
code = get(code_cache(interp), mi, nothing)
if code isa CodeInstance # return existing rettype if the code is already inferred
+ if max_world(code) < typemax(UInt)
+ println("here 3: max_world(code) = ", max_world(code))
+ println("caller state: ", caller.valid_worlds, " and ", caller.world)
+ end
update_valid_age!(caller, WorldRange(min_world(code), max_world(code)))
if isdefined(code, :rettype_const)
if isa(code.rettype_const, Vector{Any}) && !(Vector{Any} <: code.rettype)
@@ -816,6 +824,10 @@ function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance)
tree.parent = mi
tree.rettype = Core.Typeof(code.rettype_const)
tree.min_world = code.min_world
+ if code.max_world < typemax(UInt)
+ println("here 4, tree.max_world = ", tree.max_world)
+ println("code.max_world = ", code.max_world)
+ end
tree.max_world = code.max_world
return tree
elseif isa(inf, CodeInfo)
@@ -824,6 +836,10 @@ function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance)
inf.max_world == code.max_world &&
inf.rettype === code.rettype)
inf = copy(inf)
+ if code.max_world < typemax(UInt)
+ println("here 5, inf.max_world = ", inf.max_world)
+ println("code.max_world = ", code.max_world)
+ end
inf.min_world = code.min_world
inf.max_world = code.max_world
inf.rettype = code.rettype
It doesn't fire on the profile_test
example above. Of course there are quite a few places in the C code where that gets set too.
OK, I've narrowed this a lot. Two sources that were essentially spurious:
Core
methods run in an old world age, so it's not surprising that anything new that gets compiled there has an old agemax_world
of 0.There are still a few cases that seem to fall outside these categories, so I'll leave this open for now. I also don't know why it's useful to cache CodeInstances, if we're not going to be able to use them.
I'm not sure I understand this properly, but using the
master
branch of SnoopCompile:Those were all MethodInstances that were inferred (more likely,
Const
-inferred) during running of that workload, and yet they haveCodeInstance
s that are no longer valid. A wild guess is that somehow the@generated
constructor forNamedTuple
s triggers invalidation?For some packages, the list of apparent runtime invalidations is pretty huge. Example (CC @tlienart):
Does anyone know what's going on? Again, I'll emphasize that
@snoopr
does not record any invalidations with the same protocol.