Skip to content
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
46 changes: 21 additions & 25 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2574,9 +2574,9 @@ function abstract_eval_replaceglobal!(interp::AbstractInterpreter, sv::AbsIntSta
M isa Module || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
s isa Symbol || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
gr = GlobalRef(M, s)
(valid_worlds, (rte, T)) = scan_leaf_partitions(interp, gr, sv.world) do interp, _, partition
(valid_worlds, (rte, T)) = scan_leaf_partitions(interp, gr, sv.world) do interp, binding, partition
partition_T = nothing
partition_rte = abstract_eval_partition_load(interp, partition)
partition_rte = abstract_eval_partition_load(interp, binding, partition)
if binding_kind(partition) == PARTITION_KIND_GLOBAL
partition_T = partition_restriction(partition)
end
Expand Down Expand Up @@ -3558,13 +3558,11 @@ function abstract_eval_binding_partition!(interp::AbstractInterpreter, g::Global
return partition
end

abstract_eval_partition_load(interp::Union{AbstractInterpreter, Nothing}, ::Core.Binding, partition::Core.BindingPartition) =
abstract_eval_partition_load(interp, partition)
function abstract_eval_partition_load(interp::Union{AbstractInterpreter, Nothing}, partition::Core.BindingPartition)
function abstract_eval_partition_load(interp::Union{AbstractInterpreter, Nothing}, binding::Core.Binding, partition::Core.BindingPartition)
kind = binding_kind(partition)
isdepwarn = (partition.kind & PARTITION_FLAG_DEPWARN) != 0
local_getglobal_effects = Effects(generic_getglobal_effects, effect_free=isdepwarn ? ALWAYS_FALSE : ALWAYS_TRUE)
if is_some_guard(kind) || kind == PARTITION_KIND_UNDEF_CONST
if is_some_guard(kind)
if interp !== nothing && InferenceParams(interp).assume_bindings_static
return RTEffects(Union{}, UndefVarError, EFFECTS_THROWS)
else
Expand All @@ -3590,12 +3588,23 @@ function abstract_eval_partition_load(interp::Union{AbstractInterpreter, Nothing
# Could be replaced by a backdated const which has an effect, so we can't assume it won't.
# Besides, we would prefer not to merge the world range for this into the world range for
# _GLOBAL, because that would pessimize codegen.
local_getglobal_effects = Effects(local_getglobal_effects, effect_free=ALWAYS_FALSE)
effects = Effects(local_getglobal_effects, effect_free=ALWAYS_FALSE)
rt = Any
else
rt = partition_restriction(partition)
effects = local_getglobal_effects
end
if (interp !== nothing && InferenceParams(interp).assume_bindings_static &&
kind in (PARTITION_KIND_GLOBAL, PARTITION_KIND_DECLARED) &&
isdefined(binding, :value))
exct = Union{}
effects = Effects(generic_getglobal_effects; nothrow=true)
else
# We do not assume in general that assigned global bindings remain assigned.
# The existence of pkgimages allows them to revert in practice.
exct = UndefVarError
end
return RTEffects(rt, UndefVarError, local_getglobal_effects)
return RTEffects(rt, exct, effects)
end

function scan_specified_partitions(query::Function, walk_binding_partition::Function, interp, g::GlobalRef, wwr::WorldWithRange)
Expand Down Expand Up @@ -3643,28 +3652,15 @@ scan_partitions(query::Function, interp, g::GlobalRef, wwr::WorldWithRange) =
abstract_load_all_consistent_leaf_partitions(interp, g::GlobalRef, wwr::WorldWithRange) =
scan_leaf_partitions(abstract_eval_partition_load, interp, g, wwr)

function abstract_eval_globalref_partition(interp, binding::Core.Binding, partition::Core.BindingPartition)
# For inference purposes, we don't particularly care which global binding we end up loading, we only
# care about its type. However, we would still like to terminate the world range for the particular
# binding we end up reaching such that codegen can emit a simpler pointer load.
Pair{RTEffects, Union{Nothing, Core.Binding}}(
abstract_eval_partition_load(interp, partition),
binding_kind(partition) in (PARTITION_KIND_GLOBAL, PARTITION_KIND_DECLARED) ? binding : nothing)
end

function abstract_eval_globalref(interp, g::GlobalRef, saw_latestworld::Bool, sv::AbsIntState)
if saw_latestworld
return RTEffects(Any, Any, generic_getglobal_effects)
end
(valid_worlds, (ret, binding_if_global)) = scan_leaf_partitions(abstract_eval_globalref_partition, interp, g, sv.world)
# For inference purposes, we don't particularly care which global binding we end up loading, we only
# care about its type. However, we would still like to terminate the world range for the particular
# binding we end up reaching such that codegen can emit a simpler pointer load.
(valid_worlds, ret) = scan_leaf_partitions(abstract_eval_partition_load, interp, g, sv.world)
update_valid_age!(sv, valid_worlds)
if ret.rt !== Union{} && ret.exct === UndefVarError && binding_if_global !== nothing && InferenceParams(interp).assume_bindings_static
if isdefined(binding_if_global, :value)
ret = RTEffects(ret.rt, Union{}, Effects(generic_getglobal_effects, nothrow=true))
end
# We do not assume in general that assigned global bindings remain assigned.
# The existence of pkgimages allows them to revert in practice.
end
return ret
end

Expand Down
22 changes: 18 additions & 4 deletions Compiler/test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6348,14 +6348,28 @@ end === Int
swapglobal!(@__MODULE__, :swapglobal!_xxx, x)
end === Union{}

@newinterp AssumeBindingsStaticInterp
Compiler.InferenceParams(::AssumeBindingsStaticInterp) = Compiler.InferenceParams(; assume_bindings_static=true)

eval(Expr(:const, :swapglobal!_must_throw))
@newinterp SwapGlobalInterp
Compiler.InferenceParams(::SwapGlobalInterp) = Compiler.InferenceParams(; assume_bindings_static=true)
function func_swapglobal!_must_throw(x)
swapglobal!(@__MODULE__, :swapglobal!_must_throw, x)
end
@test Base.infer_return_type(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) === Union{}
@test !Compiler.is_effect_free(Base.infer_effects(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) )
@test Base.infer_return_type(func_swapglobal!_must_throw, (Int,); interp=AssumeBindingsStaticInterp()) === Union{}
@test !Compiler.is_effect_free(Base.infer_effects(func_swapglobal!_must_throw, (Int,); interp=AssumeBindingsStaticInterp()) )

global global_decl_defined
global_decl_defined = 42
@test Base.infer_effects(; interp=AssumeBindingsStaticInterp()) do
global global_decl_defined
return global_decl_defined
end |> Compiler.is_nothrow
global global_decl_defined2::Int
global_decl_defined2 = 42
@test Base.infer_effects(; interp=AssumeBindingsStaticInterp()) do
global global_decl_defined2
return global_decl_defined2
end |> Compiler.is_nothrow

@eval get_exception() = $(Expr(:the_exception))
@test Base.infer_return_type() do
Expand Down
6 changes: 3 additions & 3 deletions base/invalidation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,12 @@ function invalidate_code_for_globalref!(b::Core.Binding, invalidated_bpart::Core
(_, (ib, ibpart)) = Compiler.walk_binding_partition(b, invalidated_bpart, new_max_world)
(_, (nb, nbpart)) = Compiler.walk_binding_partition(b, new_bpart, new_max_world+1)

# abstract_eval_globalref_partition is the maximum amount of information that inference
# `abstract_eval_partition_load` is the maximum amount of information that inference
# reads from a binding partition. If this information does not change - we do not need to
# invalidate any code that inference created, because we know that the result will not change.
need_to_invalidate_code =
Compiler.abstract_eval_globalref_partition(nothing, ib, ibpart) !==
Compiler.abstract_eval_globalref_partition(nothing, nb, nbpart)
Compiler.abstract_eval_partition_load(nothing, ib, ibpart) !==
Compiler.abstract_eval_partition_load(nothing, nb, nbpart)

need_to_invalidate_export = export_affecting_partition_flags(invalidated_bpart) !==
export_affecting_partition_flags(new_bpart)
Expand Down