Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disambiguate get_world_counter and get_inference_world #53088

Merged
merged 7 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,7 @@ struct Pair{A, B}
end

function _hasmethod(@nospecialize(tt)) # this function has a special tfunc
world = ccall(:jl_get_tls_world_age, UInt, ())
world = ccall(:jl_get_tls_world_age, UInt, ()) # tls_world_age()
return Intrinsics.not_int(ccall(:jl_gf_invoke_lookup, Any, (Any, Any, UInt), tt, nothing, world) === nothing)
end

Expand Down
4 changes: 2 additions & 2 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ function edge_matches_sv(interp::AbstractInterpreter, frame::AbsIntState,
# necessary in order to retrieve this field from the generated `CodeInfo`, if it exists.
# The other `CodeInfo`s we inspect will already have this field inflated, so we just
# access it directly instead (to avoid regeneration).
world = get_world_counter(interp)
world = get_inference_world(interp)
callee_method2 = method_for_inference_heuristics(method, sig, sparams, world) # Union{Method, Nothing}

inf_method2 = method_for_inference_limit_heuristics(frame) # limit only if user token match
Expand Down Expand Up @@ -935,7 +935,7 @@ function concrete_eval_call(interp::AbstractInterpreter,
pushfirst!(args, f, invokecall.types)
f = invoke
end
world = get_world_counter(interp)
world = get_inference_world(interp)
edge = result.edge::MethodInstance
value = try
Core._call_in_world_total(world, f, args...)
Expand Down
7 changes: 5 additions & 2 deletions base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,10 @@ mutable struct InferenceState
function InferenceState(result::InferenceResult, src::CodeInfo, cache_mode::UInt8,
interp::AbstractInterpreter)
linfo = result.linfo
world = get_world_counter(interp)
world = get_inference_world(interp)
if world == typemax(UInt)
error("Entering inference from a generated function with an invalid world")
end
def = linfo.def
mod = isa(def, Method) ? def.module : def
sptypes = sptypes_from_meth_instance(linfo)
Expand Down Expand Up @@ -487,7 +490,7 @@ end

function InferenceState(result::InferenceResult, cache_mode::UInt8, interp::AbstractInterpreter)
# prepare an InferenceState object for inferring lambda
world = get_world_counter(interp)
world = get_inference_world(interp)
src = retrieve_code_info(result.linfo, world)
src === nothing && return nothing
maybe_validate_code(result.linfo, src, "lowered")
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function InliningState(sv::InferenceState, interp::AbstractInterpreter)
return InliningState(edges, sv.world, interp)
end
function InliningState(interp::AbstractInterpreter)
return InliningState(Any[], get_world_counter(interp), interp)
return InliningState(Any[], get_inference_world(interp), interp)
end

# get `code_cache(::AbstractInterpreter)` from `state::InliningState`
Expand Down Expand Up @@ -193,7 +193,7 @@ function OptimizationState(linfo::MethodInstance, src::CodeInfo, interp::Abstrac
return OptimizationState(linfo, src, nothing, stmt_info, mod, sptypes, slottypes, inlining, cfg, unreachable, bb_vartables, false)
end
function OptimizationState(linfo::MethodInstance, interp::AbstractInterpreter)
world = get_world_counter(interp)
world = get_inference_world(interp)
src = retrieve_code_info(linfo, world)
src === nothing && return nothing
return OptimizationState(linfo, src, interp)
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/ssair/irinterp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function concrete_eval_invoke(interp::AbstractInterpreter,
if (is_foldable(effects) && is_all_const_arg(argtypes, #=start=#1) &&
(is_nonoverlayed(interp) || is_nonoverlayed(effects)))
args = collect_const_args(argtypes, #=start=#1)
value = let world = get_world_counter(interp)
value = let world = get_inference_world(interp)
try
Core._call_in_world_total(world, args...)
catch
Expand Down
8 changes: 4 additions & 4 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance)
end
end
if ccall(:jl_get_module_infer, Cint, (Any,), method.module) == 0 && !generating_output(#=incremental=#false)
return retrieve_code_info(mi, get_world_counter(interp))
return retrieve_code_info(mi, get_inference_world(interp))
end
lock_mi_inference(interp, mi)
result = InferenceResult(mi, typeinf_lattice(interp))
Expand Down Expand Up @@ -1094,7 +1094,7 @@ function typeinf_ext_toplevel(interp::AbstractInterpreter, mi::MethodInstance)
end

function return_type(@nospecialize(f), t::DataType) # this method has a special tfunc
world = ccall(:jl_get_tls_world_age, UInt, ())
world = tls_world_age()
args = Any[_return_type, NativeInterpreter(world), Tuple{Core.Typeof(f), t.parameters...}]
return ccall(:jl_call_in_typeinf_world, Any, (Ptr{Ptr{Cvoid}}, Cint), args, length(args))
end
Expand All @@ -1104,7 +1104,7 @@ function return_type(@nospecialize(f), t::DataType, world::UInt)
end

function return_type(t::DataType)
world = ccall(:jl_get_tls_world_age, UInt, ())
world = tls_world_age()
return return_type(t, world)
end

Expand All @@ -1122,7 +1122,7 @@ function _return_type(interp::AbstractInterpreter, t::DataType)
rt = builtin_tfunction(interp, f, args, nothing)
rt = widenconst(rt)
else
for match in _methods_by_ftype(t, -1, get_world_counter(interp))::Vector
for match in _methods_by_ftype(t, -1, get_inference_world(interp))::Vector
ty = typeinf_type(interp, match::MethodMatch)
ty === nothing && return Any
rt = tmerge(rt, ty)
Expand Down
8 changes: 4 additions & 4 deletions base/compiler/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ If `interp::NewInterpreter` is an `AbstractInterpreter`, it is expected to provi
the following methods to satisfy the `AbstractInterpreter` API requirement:
- `InferenceParams(interp::NewInterpreter)` - return an `InferenceParams` instance
- `OptimizationParams(interp::NewInterpreter)` - return an `OptimizationParams` instance
- `get_world_counter(interp::NewInterpreter)` - return the world age for this interpreter
- `get_inference_world(interp::NewInterpreter)` - return the world age for this interpreter
- `get_inference_cache(interp::NewInterpreter)` - return the local inference cache
- `code_cache(interp::NewInterpreter)` - return the global inference cache
"""
Expand Down Expand Up @@ -402,9 +402,9 @@ end
# Quickly and easily satisfy the AbstractInterpreter API contract
InferenceParams(interp::NativeInterpreter) = interp.inf_params
OptimizationParams(interp::NativeInterpreter) = interp.opt_params
get_world_counter(interp::NativeInterpreter) = interp.world
get_inference_world(interp::NativeInterpreter) = interp.world
get_inference_cache(interp::NativeInterpreter) = interp.inf_cache
code_cache(interp::NativeInterpreter) = WorldView(GLOBAL_CI_CACHE, get_world_counter(interp))
code_cache(interp::NativeInterpreter) = WorldView(GLOBAL_CI_CACHE, get_inference_world(interp))

"""
already_inferred_quick_test(::AbstractInterpreter, ::MethodInstance)
Expand Down Expand Up @@ -458,7 +458,7 @@ Returns a method table this `interp` uses for method lookup.
External `AbstractInterpreter` can optionally return `OverlayMethodTable` here
to incorporate customized dispatches for the overridden methods.
"""
method_table(interp::AbstractInterpreter) = InternalMethodTable(get_world_counter(interp))
method_table(interp::AbstractInterpreter) = InternalMethodTable(get_inference_world(interp))
method_table(interp::NativeInterpreter) = interp.method_table

"""
Expand Down
16 changes: 16 additions & 0 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,7 @@ function code_lowered(@nospecialize(f), @nospecialize(t=Tuple); generated::Bool=
throw(ArgumentError("'debuginfo' must be either :source or :none"))
end
world = get_world_counter()
world == typemax(UInt) && error("code reflection cannot be used from generated functions")
return map(method_instances(f, t, world)) do m
if generated && hasgenerator(m)
if may_invoke_generator(m)
Expand Down Expand Up @@ -2329,6 +2330,7 @@ end

function hasmethod(f, t, kwnames::Tuple{Vararg{Symbol}}; world::UInt=get_world_counter())
@nospecialize
world == typemax(UInt) && error("code reflection cannot be used from generated functions")
isempty(kwnames) && return hasmethod(f, t; world)
t = to_tuple_type(t)
ft = Core.Typeof(f)
Expand Down Expand Up @@ -2550,8 +2552,22 @@ min_world(m::Core.CodeInstance) = m.min_world
max_world(m::Core.CodeInstance) = m.max_world
min_world(m::Core.CodeInfo) = m.min_world
max_world(m::Core.CodeInfo) = m.max_world

"""
get_world_counter()

Returns the current maximum world-age counter. This counter is global and monotonically
increasing.
"""
get_world_counter() = ccall(:jl_get_world_counter, UInt, ())

"""
tls_world_age()

Returns the world the [current_task()](@ref) is executing within.
"""
tls_world_age() = ccall(:jl_get_tls_world_age, UInt, ())

"""
propertynames(x, private=false)

Expand Down
3 changes: 3 additions & 0 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,8 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t *mi, size_t world, int force)
#ifdef _OS_WINDOWS_
DWORD last_error = GetLastError();
#endif
int last_pure = ct->ptls->in_pure_callback;
ct->ptls->in_pure_callback = 0;
size_t last_age = ct->world_age;
ct->world_age = jl_typeinf_world;
mi->inInference = 1;
Expand Down Expand Up @@ -409,6 +411,7 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t *mi, size_t world, int force)
}
ct->world_age = last_age;
ct->reentrant_timing -= 0b10;
ct->ptls->in_pure_callback = last_pure;
mi->inInference = 0;
#ifdef _OS_WINDOWS_
SetLastError(last_error);
Expand Down
2 changes: 1 addition & 1 deletion stdlib/REPL/src/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ struct REPLInterpreter <: CC.AbstractInterpreter
end
CC.InferenceParams(interp::REPLInterpreter) = interp.inf_params
CC.OptimizationParams(interp::REPLInterpreter) = interp.opt_params
CC.get_world_counter(interp::REPLInterpreter) = interp.world
CC.get_inference_world(interp::REPLInterpreter) = interp.world
CC.get_inference_cache(interp::REPLInterpreter) = interp.inf_cache
CC.code_cache(interp::REPLInterpreter) = CC.WorldView(interp.code_cache, CC.WorldRange(interp.world))
CC.get(wvc::CC.WorldView{REPLInterpreterCache}, mi::MethodInstance, default) = get(wvc.cache.dict, mi, default)
Expand Down
6 changes: 3 additions & 3 deletions test/compiler/AbstractInterpreter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ end

@newinterp MTOverlayInterp
@MethodTable OverlayedMT
CC.method_table(interp::MTOverlayInterp) = CC.OverlayMethodTable(CC.get_world_counter(interp), OverlayedMT)
CC.method_table(interp::MTOverlayInterp) = CC.OverlayMethodTable(CC.get_inference_world(interp), OverlayedMT)

function CC.add_remark!(interp::MTOverlayInterp, ::CC.InferenceState, remark)
if interp.meta !== nothing
Expand Down Expand Up @@ -120,7 +120,7 @@ end |> only === Nothing
# https://github.com/JuliaLang/julia/issues/48097
@newinterp Issue48097Interp
@MethodTable Issue48097MT
CC.method_table(interp::Issue48097Interp) = CC.OverlayMethodTable(CC.get_world_counter(interp), Issue48097MT)
CC.method_table(interp::Issue48097Interp) = CC.OverlayMethodTable(CC.get_inference_world(interp), Issue48097MT)
CC.InferenceParams(::Issue48097Interp) = CC.InferenceParams(; unoptimize_throw_blocks=false)
function CC.concrete_eval_eligible(interp::Issue48097Interp,
@nospecialize(f), result::CC.MethodCallResult, arginfo::CC.ArgInfo, sv::CC.AbsIntState)
Expand All @@ -141,7 +141,7 @@ end
# Should not concrete-eval overlayed methods in semi-concrete interpretation
@newinterp OverlaySinInterp
@MethodTable OverlaySinMT
CC.method_table(interp::OverlaySinInterp) = CC.OverlayMethodTable(CC.get_world_counter(interp), OverlaySinMT)
CC.method_table(interp::OverlaySinInterp) = CC.OverlayMethodTable(CC.get_inference_world(interp), OverlaySinMT)
overlay_sin1(x) = error("Not supposed to be called.")
@overlay OverlaySinMT overlay_sin1(x) = cos(x)
@overlay OverlaySinMT Base.sin(x::Union{Float32,Float64}) = overlay_sin1(x)
Expand Down
4 changes: 2 additions & 2 deletions test/compiler/EscapeAnalysis/EAUtils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ end

CC.InferenceParams(interp::EscapeAnalyzer) = interp.inf_params
CC.OptimizationParams(interp::EscapeAnalyzer) = interp.opt_params
CC.get_world_counter(interp::EscapeAnalyzer) = interp.world
CC.get_inference_world(interp::EscapeAnalyzer) = interp.world
CC.get_inference_cache(interp::EscapeAnalyzer) = interp.inf_cache

struct EscapeAnalyzerCacheView
Expand All @@ -127,7 +127,7 @@ struct EscapeAnalyzerCacheView
end

function CC.code_cache(interp::EscapeAnalyzer)
worlds = WorldRange(get_world_counter(interp))
worlds = WorldRange(CC.get_inference_world(interp))
return WorldView(EscapeAnalyzerCacheView(interp.code_cache, interp.escape_cache), worlds)
end
CC.haskey(wvc::WorldView{EscapeAnalyzerCacheView}, mi::MethodInstance) = haskey(wvc.cache.code_cache.cache, mi)
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/invalidation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ end

CC.InferenceParams(interp::InvalidationTester) = interp.inf_params
CC.OptimizationParams(interp::InvalidationTester) = interp.opt_params
CC.get_world_counter(interp::InvalidationTester) = interp.world
CC.get_inference_world(interp::InvalidationTester) = interp.world
CC.get_inference_cache(interp::InvalidationTester) = interp.inf_cache
CC.code_cache(interp::InvalidationTester) = WorldView(InvalidationTesterCacheView(interp.code_cache.dict), WorldRange(interp.world))
CC.get(wvc::WorldView{InvalidationTesterCacheView}, mi::MethodInstance, default) = get(wvc.cache.dict, mi, default)
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/newinterp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ macro newinterp(InterpName)
end
$CC.InferenceParams(interp::$InterpName) = interp.inf_params
$CC.OptimizationParams(interp::$InterpName) = interp.opt_params
$CC.get_world_counter(interp::$InterpName) = interp.world
$CC.get_inference_world(interp::$InterpName) = interp.world
$CC.get_inference_cache(interp::$InterpName) = interp.inf_cache
$CC.code_cache(interp::$InterpName) = $CC.WorldView(interp.code_cache, $CC.WorldRange(interp.world))
$CC.get(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance, default) = get(wvc.cache.dict, mi, default)
Expand Down
3 changes: 1 addition & 2 deletions test/worlds.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

# tests for accurate updating of method tables

using Base: get_world_counter
tls_world_age() = ccall(:jl_get_tls_world_age, UInt, ())
using Base: get_world_counter, tls_world_age
@test typemax(UInt) > get_world_counter() == tls_world_age() > 0

# test simple method replacement
Expand Down