Skip to content

Commit

Permalink
effects: change the overlayed::Bool property to nooverlayed::Bool
Browse files Browse the repository at this point in the history
The current naming of `overlayed` is a bit confusing since 
`overlayed === true`, which is the conservative default value, actually
means "it _may_ be overlayed" while `overlayed === false` means 
"this is not absolutely overlayed".
I think it should be named as `nooverlayed`, and then a query name like
`is_nooverlayed` would be more sensible than the alternative 
`is_overlayed`,
which actually should be something like `may_be_overlayed`.
  • Loading branch information
aviatesk committed Mar 29, 2022
1 parent e2ea152 commit 10b4114
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 88 deletions.
73 changes: 38 additions & 35 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,25 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
# function has not seen any side effects, we would like to make sure there
# aren't any in the throw block either to enable other optimizations.
add_remark!(interp, sv, "Skipped call in throw block")
overlayed = true
if isoverlayed(method_table(interp))
if !sv.ipo_effects.overlayed
nooverlayed = false
if isnooverlayed(method_table(interp))
nooverlayed = true
else
if sv.ipo_effects.nooverlayed
# as we may want to concrete-evaluate this frame in cases when there are
# no overlayed calls, try an additional effort now to check if this call
# isn't overlayed rather than just handling it conservatively
matches = find_matching_methods(arginfo.argtypes, atype, method_table(interp),
InferenceParams(interp).MAX_UNION_SPLITTING, max_methods)
if !isa(matches, FailedMethodMatch)
overlayed = matches.overlayed
nooverlayed = matches.nooverlayed
end
end
else
overlayed = false
end
# At this point we are guaranteed to end up throwing on this path,
# which is all that's required for :consistent-cy. Of course, we don't
# know anything else about this statement.
tristate_merge!(sv, Effects(; consistent=ALWAYS_TRUE, overlayed))
tristate_merge!(sv, Effects(; consistent=ALWAYS_TRUE, nooverlayed))
return CallMeta(Any, false)
end

Expand All @@ -88,11 +88,11 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
any_const_result = false
const_results = Union{InferenceResult,Nothing,ConstResult}[]
multiple_matches = napplicable > 1
if matches.overlayed
if !matches.nooverlayed
# currently we don't have a good way to execute the overlayed method definition,
# so we should give up pure/concrete eval when any of the matched methods is overlayed
f = nothing
tristate_merge!(sv, Effects(EFFECTS_TOTAL; overlayed=true))
tristate_merge!(sv, Effects(EFFECTS_TOTAL; nooverlayed=false))
end

val = pure_eval_call(interp, f, applicable, arginfo, sv)
Expand Down Expand Up @@ -212,7 +212,9 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
end

if seen != napplicable
tristate_merge!(sv, Effects(; overlayed=false)) # already accounted for method overlay above
# there may be unanalyzed effects within unseen dispatch candidate,
# but we can still ignore nooverlayed effect here since we already accounted for it
tristate_merge!(sv, EFFECTS_UNKNOWN)
elseif isa(matches, MethodMatches) ? (!matches.fullmatch || any_ambig(matches)) :
(!_all(b->b, matches.fullmatches) || any_ambig(matches))
# Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
Expand Down Expand Up @@ -251,7 +253,7 @@ struct MethodMatches
valid_worlds::WorldRange
mt::Core.MethodTable
fullmatch::Bool
overlayed::Bool
nooverlayed::Bool
end
any_ambig(info::MethodMatchInfo) = info.results.ambig
any_ambig(m::MethodMatches) = any_ambig(m.info)
Expand All @@ -263,7 +265,7 @@ struct UnionSplitMethodMatches
valid_worlds::WorldRange
mts::Vector{Core.MethodTable}
fullmatches::Vector{Bool}
overlayed::Bool
nooverlayed::Bool
end
any_ambig(m::UnionSplitMethodMatches) = _any(any_ambig, m.info.matches)

Expand All @@ -278,7 +280,7 @@ function find_matching_methods(argtypes::Vector{Any}, @nospecialize(atype), meth
valid_worlds = WorldRange()
mts = Core.MethodTable[]
fullmatches = Bool[]
overlayed = false
nooverlayed = true
for i in 1:length(split_argtypes)
arg_n = split_argtypes[i]::Vector{Any}
sig_n = argtypes_to_type(arg_n)
Expand All @@ -289,8 +291,8 @@ function find_matching_methods(argtypes::Vector{Any}, @nospecialize(atype), meth
if result === missing
return FailedMethodMatch("For one of the union split cases, too many methods matched")
end
matches, overlayedᵢ = result
overlayed |= overlayedᵢ
matches, nooverlayedᵢ = result
nooverlayed &= nooverlayedᵢ
push!(infos, MethodMatchInfo(matches))
for m in matches
push!(applicable, m)
Expand All @@ -317,7 +319,7 @@ function find_matching_methods(argtypes::Vector{Any}, @nospecialize(atype), meth
valid_worlds,
mts,
fullmatches,
overlayed)
nooverlayed)
else
mt = ccall(:jl_method_table_for, Any, (Any,), atype)
if mt === nothing
Expand All @@ -330,14 +332,14 @@ function find_matching_methods(argtypes::Vector{Any}, @nospecialize(atype), meth
# (assume this will always be true, so we don't compute / update valid age in this case)
return FailedMethodMatch("Too many methods matched")
end
matches, overlayed = result
matches, nooverlayed = result
fullmatch = _any(match->(match::MethodMatch).fully_covers, matches)
return MethodMatches(matches.matches,
MethodMatchInfo(matches),
matches.valid_worlds,
mt,
fullmatch,
overlayed)
nooverlayed)
end
end

Expand Down Expand Up @@ -712,7 +714,7 @@ function concrete_eval_eligible(interp::AbstractInterpreter,
@nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState)
# disable concrete-evaluation since this function call is tainted by some overlayed
# method and currently there is no direct way to execute overlayed methods
isoverlayed(method_table(interp)) && result.edge_effects.overlayed && return false
!isnooverlayed(method_table(interp)) && !result.edge_effects.nooverlayed && return false
return f !== nothing &&
result.edge !== nothing &&
is_total_or_error(result.edge_effects) &&
Expand Down Expand Up @@ -1500,20 +1502,20 @@ end
function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgInfo, sv::InferenceState)
ft′ = argtype_by_index(argtypes, 2)
ft = widenconst(ft′)
ft === Bottom && return CallMeta(Bottom, false), EFFECTS_THROWN
ft === Bottom && return CallMeta(Bottom, false), EFFECTS_THROWS
(types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, 3))
types === Bottom && return CallMeta(Bottom, false), EFFECTS_THROWN
types === Bottom && return CallMeta(Bottom, false), EFFECTS_THROWS
isexact || return CallMeta(Any, false), Effects()
argtype = argtypes_to_type(argtype_tail(argtypes, 4))
nargtype = typeintersect(types, argtype)
nargtype === Bottom && return CallMeta(Bottom, false), EFFECTS_THROWN
nargtype === Bottom && return CallMeta(Bottom, false), EFFECTS_THROWS
nargtype isa DataType || return CallMeta(Any, false), Effects() # other cases are not implemented below
isdispatchelem(ft) || return CallMeta(Any, false), Effects() # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below
ft = ft::DataType
types = rewrap_unionall(Tuple{ft, unwrap_unionall(types).parameters...}, types)::Type
nargtype = Tuple{ft, nargtype.parameters...}
argtype = Tuple{ft, argtype.parameters...}
match, valid_worlds, overlayed = findsup(types, method_table(interp))
match, valid_worlds, nooverlayed = findsup(types, method_table(interp))
match === nothing && return CallMeta(Any, false), Effects()
update_valid_age!(sv, valid_worlds)
method = match.method
Expand All @@ -1533,13 +1535,14 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn
# argtypes′[i] = t ⊑ a ? t : a
# end
const_call_result = abstract_call_method_with_const_args(interp, result,
overlayed ? nothing : singleton_type(ft′), arginfo, match, sv)
nooverlayed ? singleton_type(ft′) : nothing, arginfo, match, sv)
const_result = nothing
if const_call_result !== nothing
if const_call_result.rt rt
(; rt, effects, const_result) = const_call_result
end
end
effects = Effects(effects; nooverlayed)
return CallMeta(from_interprocedural!(rt, sv, arginfo, sig), InvokeCallInfo(match, const_result)), effects
end

Expand Down Expand Up @@ -1585,12 +1588,12 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
end
end
end
tristate_merge!(sv, Effects(; overlayed=false)) # TODO
tristate_merge!(sv, EFFECTS_UNKNOWN) # TODO
return CallMeta(Any, false)
elseif f === TypeVar
# Manually look through the definition of TypeVar to
# make sure to be able to get `PartialTypeVar`s out.
tristate_merge!(sv, Effects(; overlayed=false)) # TODO
tristate_merge!(sv, EFFECTS_UNKNOWN) # TODO
(la < 2 || la > 4) && return CallMeta(Union{}, false)
n = argtypes[2]
ub_var = Const(Any)
Expand All @@ -1603,17 +1606,17 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
end
return CallMeta(typevar_tfunc(n, lb_var, ub_var), false)
elseif f === UnionAll
tristate_merge!(sv, Effects(; overlayed=false)) # TODO
tristate_merge!(sv, EFFECTS_UNKNOWN) # TODO
return CallMeta(abstract_call_unionall(argtypes), false)
elseif f === Tuple && la == 2
tristate_merge!(sv, Effects(; overlayed=false)) # TODO
tristate_merge!(sv, EFFECTS_UNKNOWN) # TODO
aty = argtypes[2]
ty = isvarargtype(aty) ? unwrapva(aty) : widenconst(aty)
if !isconcretetype(ty)
return CallMeta(Tuple, false)
end
elseif is_return_type(f)
tristate_merge!(sv, Effects(; overlayed=false)) # TODO
tristate_merge!(sv, EFFECTS_UNKNOWN) # TODO
return return_type_tfunc(interp, argtypes, sv)
elseif la == 2 && istopfunction(f, :!)
# handle Conditional propagation through !Bool
Expand Down Expand Up @@ -1956,21 +1959,21 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e),
effects.effect_free ? ALWAYS_TRUE : TRISTATE_UNKNOWN,
effects.nothrow ? ALWAYS_TRUE : TRISTATE_UNKNOWN,
effects.terminates_globally ? ALWAYS_TRUE : TRISTATE_UNKNOWN,
#=overlayed=#false
#=nooverlayed=#true
))
else
tristate_merge!(sv, Effects(; overlayed=false))
tristate_merge!(sv, EFFECTS_UNKNOWN)
end
elseif ehead === :cfunction
tristate_merge!(sv, Effects(; overlayed=false))
tristate_merge!(sv, EFFECTS_UNKNOWN)
t = e.args[1]
isa(t, Type) || (t = Any)
abstract_eval_cfunction(interp, e, vtypes, sv)
elseif ehead === :method
tristate_merge!(sv, Effects(; overlayed=false))
tristate_merge!(sv, EFFECTS_UNKNOWN)
t = (length(e.args) == 1) ? Any : Nothing
elseif ehead === :copyast
tristate_merge!(sv, Effects(; overlayed=false))
tristate_merge!(sv, EFFECTS_UNKNOWN)
t = abstract_eval_value(interp, e.args[1], vtypes, sv)
if t isa Const && t.val isa Expr
# `copyast` makes copies of Exprs
Expand Down Expand Up @@ -2283,7 +2286,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
effect_free=ALWAYS_FALSE,
nothrow=TRISTATE_UNKNOWN))
elseif !isa(lhs, SSAValue)
tristate_merge!(frame, Effects(; overlayed=false))
tristate_merge!(frame, EFFECTS_UNKNOWN)
end
elseif hd === :method
stmt = stmt::Expr
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ mutable struct InferenceState
#=parent=#nothing,
#=cached=#cache === :global,
#=inferred=#false, #=dont_work_on_me=#false, #=restrict_abstract_call_sites=# isa(linfo.def, Module),
#=ipo_effects=#Effects(consistent, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, false, inbounds_taints_consistency),
#=ipo_effects=#Effects(EFFECTS_TOTAL; consistent, inbounds_taints_consistency),
interp)
result.result = frame
cache !== :no && push!(get_inference_cache(interp), result)
Expand Down
26 changes: 13 additions & 13 deletions base/compiler/methodtable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ getindex(result::MethodLookupResult, idx::Int) = getindex(result.matches, idx)::

"""
findall(sig::Type, view::MethodTableView; limit::Int=typemax(Int)) ->
(matches::MethodLookupResult, overlayed::Bool) or missing
(matches::MethodLookupResult, nooverlayed::Bool) or missing
Find all methods in the given method table `view` that are applicable to the given signature `sig`.
If no applicable methods are found, an empty result is returned.
If the number of applicable methods exceeded the specified limit, `missing` is returned.
`overlayed` indicates if any matching method is defined in an overlayed method table.
`nooverlayed` indicates if any matching method isn't defined in an overlayed method table.
"""
function findall(@nospecialize(sig::Type), table::InternalMethodTable; limit::Int=Int(typemax(Int32)))
result = _findall(sig, nothing, table.world, limit)
result === missing && return missing
return result, false
return result, true
end

function findall(@nospecialize(sig::Type), table::OverlayMethodTable; limit::Int=Int(typemax(Int32)))
Expand All @@ -60,7 +60,7 @@ function findall(@nospecialize(sig::Type), table::OverlayMethodTable; limit::Int
nr = length(result)
if nr 1 && result[nr].fully_covers
# no need to fall back to the internal method table
return result, true
return result, false
end
# fall back to the internal method table
fallback_result = _findall(sig, nothing, table.world, limit)
Expand All @@ -71,7 +71,7 @@ function findall(@nospecialize(sig::Type), table::OverlayMethodTable; limit::Int
WorldRange(
max(result.valid_worlds.min_world, fallback_result.valid_worlds.min_world),
min(result.valid_worlds.max_world, fallback_result.valid_worlds.max_world)),
result.ambig | fallback_result.ambig), !isempty(result)
result.ambig | fallback_result.ambig), isempty(result)
end

function _findall(@nospecialize(sig::Type), mt::Union{Nothing,Core.MethodTable}, world::UInt, limit::Int)
Expand All @@ -87,7 +87,7 @@ end

"""
findsup(sig::Type, view::MethodTableView) ->
(match::MethodMatch, valid_worlds::WorldRange, overlayed::Bool) or nothing
(match::MethodMatch, valid_worlds::WorldRange, nooverlayed::Bool) or nothing
Find the (unique) method such that `sig <: match.method.sig`, while being more
specific than any other method with the same property. In other words, find the method
Expand All @@ -101,23 +101,23 @@ It is possible that no method is an upper bound of `sig`, or
it is possible that among the upper bounds, there is no least element.
In both cases `nothing` is returned.
`overlayed` indicates if the matching method is defined in an overlayed method table.
`overlayed` indicates if the matching method isn't defined in an overlayed method table.
"""
function findsup(@nospecialize(sig::Type), table::InternalMethodTable)
return (_findsup(sig, nothing, table.world)..., false)
return (_findsup(sig, nothing, table.world)..., true)
end

function findsup(@nospecialize(sig::Type), table::OverlayMethodTable)
match, valid_worlds = _findsup(sig, table.mt, table.world)
match !== nothing && return match, valid_worlds, true
match !== nothing && return match, valid_worlds, false
# fall back to the internal method table
fallback_match, fallback_valid_worlds = _findsup(sig, nothing, table.world)
return (
fallback_match,
WorldRange(
max(valid_worlds.min_world, fallback_valid_worlds.min_world),
min(valid_worlds.max_world, fallback_valid_worlds.max_world)),
false)
true)
end

function _findsup(@nospecialize(sig::Type), mt::Union{Nothing,Core.MethodTable}, world::UInt)
Expand All @@ -129,6 +129,6 @@ function _findsup(@nospecialize(sig::Type), mt::Union{Nothing,Core.MethodTable},
return match, valid_worlds
end

isoverlayed(::MethodTableView) = error("unsatisfied MethodTableView interface")
isoverlayed(::InternalMethodTable) = false
isoverlayed(::OverlayMethodTable) = true
isnooverlayed(::MethodTableView) = error("unsatisfied MethodTableView interface")
isnooverlayed(::InternalMethodTable) = true
isnooverlayed(::OverlayMethodTable) = false
2 changes: 1 addition & 1 deletion base/compiler/ssair/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ function Base.show(io::IO, e::Core.Compiler.Effects)
print(io, ',')
printstyled(io, string(tristate_letter(e.terminates), 't'); color=tristate_color(e.terminates))
print(io, ')')
e.overlayed && printstyled(io, ''; color=:red)
e.nooverlayed || printstyled(io, ''; color=:red)
end

@specialize
Loading

0 comments on commit 10b4114

Please sign in to comment.