Skip to content

Commit

Permalink
follow up #44448, correct findall/findsup for OverlayMethodTable (
Browse files Browse the repository at this point in the history
#44511)

- respect world range of failed lookup into `OverlayMethodTable`:
  <#44448 (comment)>
- fix calculation of merged valid world range:
  <#44448 (comment)>
- make `findsup` return valid `WorldRange` unconditionally, and enable
  more strict world validation within `abstract_invoke`:
  <#44448 (comment)>
- fix the default `limit::Int` value of `findall`
  • Loading branch information
aviatesk committed Mar 9, 2022
1 parent d15704a commit 0a4a850
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 28 deletions.
7 changes: 3 additions & 4 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1474,11 +1474,10 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn
types = rewrap_unionall(Tuple{ft, unwrap_unionall(types).parameters...}, types)::Type
nargtype = Tuple{ft, nargtype.parameters...}
argtype = Tuple{ft, argtype.parameters...}
result = findsup(types, method_table(interp))
result === nothing && return CallMeta(Any, false)
match, valid_worlds = result
method = match.method
match, valid_worlds = findsup(types, method_table(interp))
match === nothing && return CallMeta(Any, false)
update_valid_age!(sv, valid_worlds)
method = match.method
(ti, env::SimpleVector) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), nargtype, method.sig)::SimpleVector
(; rt, edge) = result = abstract_call_method(interp, method, ti, env, false, sv)
edge !== nothing && add_backedge!(edge::MethodInstance, sv)
Expand Down
46 changes: 25 additions & 21 deletions base/compiler/methodtable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,29 +47,28 @@ 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.
"""
function findall(@nospecialize(sig::Type), table::InternalMethodTable; limit::Int=typemax(Int))
function findall(@nospecialize(sig::Type), table::InternalMethodTable; limit::Int=Int(typemax(Int32)))
return _findall(sig, nothing, table.world, limit)
end

function findall(@nospecialize(sig::Type), table::OverlayMethodTable; limit::Int=typemax(Int))
function findall(@nospecialize(sig::Type), table::OverlayMethodTable; limit::Int=Int(typemax(Int32)))
result = _findall(sig, table.mt, table.world, limit)
result === missing && return missing
if !isempty(result)
if all(match->match.fully_covers, result)
# no need to fall back to the internal method table
return result
else
# merge the match results with the internal method table
fallback_result = _findall(sig, nothing, table.world, limit)
return MethodLookupResult(
vcat(result.matches, fallback_result.matches),
WorldRange(min(result.valid_worlds.min_world, fallback_result.valid_worlds.min_world),
max(result.valid_worlds.max_world, fallback_result.valid_worlds.max_world)),
result.ambig | fallback_result.ambig)
end
nr = length(result)
if nr 1 && result[nr].fully_covers
# no need to fall back to the internal method table
return result
end
# fall back to the internal method table
return _findall(sig, nothing, table.world, limit)
fallback_result = _findall(sig, nothing, table.world, limit)
fallback_result === missing && return missing
# merge the fallback match results with the internal method table
return MethodLookupResult(
vcat(result.matches, fallback_result.matches),
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)
end

function _findall(@nospecialize(sig::Type), mt::Union{Nothing,Core.MethodTable}, world::UInt, limit::Int)
Expand Down Expand Up @@ -102,17 +101,22 @@ function findsup(@nospecialize(sig::Type), table::InternalMethodTable)
end

function findsup(@nospecialize(sig::Type), table::OverlayMethodTable)
result = _findsup(sig, table.mt, table.world)
result === nothing || return result
return _findsup(sig, nothing, table.world) # fall back to the internal method table
match, valid_worlds = _findsup(sig, table.mt, table.world)
match !== nothing && return match, valid_worlds
# 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))
end

function _findsup(@nospecialize(sig::Type), mt::Union{Nothing,Core.MethodTable}, world::UInt)
min_valid = RefValue{UInt}(typemin(UInt))
max_valid = RefValue{UInt}(typemax(UInt))
result = ccall(:jl_gf_invoke_lookup_worlds, Any, (Any, Any, UInt, Ptr{Csize_t}, Ptr{Csize_t}),
match = ccall(:jl_gf_invoke_lookup_worlds, Any, (Any, Any, UInt, Ptr{Csize_t}, Ptr{Csize_t}),
sig, mt, world, min_valid, max_valid)::Union{MethodMatch, Nothing}
return result === nothing ? result : (result, WorldRange(min_valid[], max_valid[]))
valid_worlds = WorldRange(min_valid[], max_valid[])
return match, valid_worlds
end

isoverlayed(::MethodTableView) = error("unsatisfied MethodTableView interface")
Expand Down
6 changes: 3 additions & 3 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1347,11 +1347,11 @@ end
print_statement_costs(args...; kwargs...) = print_statement_costs(stdout, args...; kwargs...)

function _which(@nospecialize(tt::Type), world=get_world_counter())
result = Core.Compiler._findsup(tt, nothing, world)
if result === nothing
match, _ = Core.Compiler._findsup(tt, nothing, world)
if match === nothing
error("no unique matching method found for the specified argument types")
end
return first(result)::Core.MethodMatch
return match
end

"""
Expand Down

0 comments on commit 0a4a850

Please sign in to comment.