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

reflection: use a real world for lookups #43695

Merged
merged 3 commits into from
Jan 8, 2022
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
17 changes: 9 additions & 8 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@ function methods(@nospecialize(f), @nospecialize(t),
throw(ArgumentError("argument is not a generic function"))
end
t = to_tuple_type(t)
world = typemax(UInt)
world = get_world_counter()
# Lack of specialization => a comprehension triggers too many invalidations via _collect, so collect the methods manually
ms = Method[]
for m in _methods(f, t, -1, world)::Vector
Expand All @@ -995,7 +995,7 @@ methods(f::Core.Builtin) = MethodList(Method[], typeof(f).name.mt)

function methods_including_ambiguous(@nospecialize(f), @nospecialize(t))
tt = signature_type(f, t)
world = typemax(UInt)
world = get_world_counter()
min = RefValue{UInt}(typemin(UInt))
max = RefValue{UInt}(typemax(UInt))
ms = _methods_by_ftype(tt, nothing, -1, world, true, min, max, Ptr{Int32}(C_NULL))
Expand Down Expand Up @@ -1069,7 +1069,7 @@ _uncompressed_ir(ci::Core.CodeInstance, s::Array{UInt8,1}) = ccall(:jl_uncompres
const uncompressed_ast = uncompressed_ir
const _uncompressed_ast = _uncompressed_ir

function method_instances(@nospecialize(f), @nospecialize(t), world::UInt = typemax(UInt))
function method_instances(@nospecialize(f), @nospecialize(t), world::UInt=get_world_counter())
tt = signature_type(f, t)
results = Core.MethodInstance[]
for match in _methods_by_ftype(tt, -1, world)::Vector
Expand Down Expand Up @@ -1429,7 +1429,7 @@ function parentmodule(@nospecialize(f), @nospecialize(types))
end

"""
hasmethod(f, t::Type{<:Tuple}[, kwnames]; world=typemax(UInt)) -> Bool
hasmethod(f, t::Type{<:Tuple}[, kwnames]; world=get_world_counter()) -> Bool

Determine whether the given generic function has a method matching the given
`Tuple` of argument types with the upper bound of world age given by `world`.
Expand Down Expand Up @@ -1464,13 +1464,13 @@ julia> hasmethod(g, Tuple{}, (:a, :b, :c, :d)) # g accepts arbitrary kwargs
true
```
"""
function hasmethod(@nospecialize(f), @nospecialize(t); world=typemax(UInt))
function hasmethod(@nospecialize(f), @nospecialize(t); world::UInt=get_world_counter())
t = to_tuple_type(t)
t = signature_type(f, t)
return ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), t, world) !== nothing
end

function hasmethod(@nospecialize(f), @nospecialize(t), kwnames::Tuple{Vararg{Symbol}}; world=typemax(UInt))
function hasmethod(@nospecialize(f), @nospecialize(t), kwnames::Tuple{Vararg{Symbol}}; world::UInt=get_world_counter())
# TODO: this appears to be doing the wrong queries
hasmethod(f, t, world=world) || return false
isempty(kwnames) && return true
Expand Down Expand Up @@ -1501,7 +1501,7 @@ function bodyfunction(basemethod::Method)
# %1 = mkw(kwvalues..., #self#, args...)
# return %1
# where `mkw` is the name of the "active" keyword body-function.
ast = Base.uncompressed_ast(basemethod)
ast = uncompressed_ast(basemethod)
f = nothing
if isa(ast, Core.CodeInfo) && length(ast.code) >= 2
callexpr = ast.code[end-1]
Expand Down Expand Up @@ -1570,10 +1570,11 @@ function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=false)
if !ambiguous_bottom
has_bottom_parameter(ti) && return false
end
world = get_world_counter()
min = UInt[typemin(UInt)]
max = UInt[typemax(UInt)]
has_ambig = Int32[0]
ms = _methods_by_ftype(ti, nothing, -1, typemax(UInt), true, min, max, has_ambig)::Vector
ms = _methods_by_ftype(ti, nothing, -1, world, true, min, max, has_ambig)::Vector
has_ambig[] == 0 && return false
if !ambiguous_bottom
filter!(ms) do m::Core.MethodMatch
Expand Down
2 changes: 1 addition & 1 deletion stdlib/InteractiveUtils/src/codeview.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ function _dump_function(@nospecialize(f), @nospecialize(t), native::Bool, wrappe
throw(ArgumentError("argument is not a generic function"))
end
# get the MethodInstance for the method match
world = typemax(UInt)
world = Base.get_world_counter()
match = Base._which(signature_type(f, t), world)
linfo = Core.Compiler.specialize_method(match)
# get the code for it
Expand Down
10 changes: 6 additions & 4 deletions stdlib/Test/src/Test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1704,9 +1704,10 @@ function detect_ambiguities(mods::Module...;
function examine(mt::Core.MethodTable)
for m in Base.MethodList(mt)
is_in_mods(m.module, recursive, mods) || continue
ambig = Int32[0]
ms = Base._methods_by_ftype(m.sig, nothing, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig)
ambig[1] == 0 && continue
world = Base.get_world_counter()
ambig = Ref{Int32}(0)
ms = Base._methods_by_ftype(m.sig, nothing, -1, world, true, Ref(typemin(UInt)), Ref(typemax(UInt)), ambig)
ambig[] == 0 && continue
isa(ms, Bool) && continue
for match2 in ms
match2 = match2::Core.MethodMatch
Expand Down Expand Up @@ -1760,7 +1761,8 @@ function detect_unbound_args(mods...;
if Base.isvatuple(tuple_sig)
params = tuple_sig.parameters[1:(end - 1)]
tuple_sig = Base.rewrap_unionall(Tuple{params...}, m.sig)
mf = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), tuple_sig, typemax(UInt))
world = Base.get_world_counter()
mf = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), tuple_sig, world)
if mf !== nothing && mf !== m && mf.sig <: tuple_sig
continue
end
Expand Down
6 changes: 3 additions & 3 deletions test/compiler/contextual.jl
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,13 @@ end

end

methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, nothing, 1, typemax(UInt))
methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, nothing, 1, Base.get_world_counter())
@test only(methods).method.module === Base.Math

methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, OverlayModule.mt, 1, typemax(UInt))
methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, OverlayModule.mt, 1, Base.get_world_counter())
@test only(methods).method.module === OverlayModule

methods = Base._methods_by_ftype(Tuple{typeof(sin), Int}, OverlayModule.mt, 1, typemax(UInt))
methods = Base._methods_by_ftype(Tuple{typeof(sin), Int}, OverlayModule.mt, 1, Base.get_world_counter())
@test isempty(methods)

# precompilation
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1232,7 +1232,7 @@ function get_linfo(@nospecialize(f), @nospecialize(t))
throw(ArgumentError("argument is not a generic function"))
end
# get the MethodInstance for the method match
match = Base._which(Base.signature_type(f, t), typemax(UInt))
match = Base._which(Base.signature_type(f, t), Base.get_world_counter())
precompile(match.spec_types)
return Core.Compiler.specialize_method(match)
end
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/validation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function f22938(a, b, x...)
end

msig = Tuple{typeof(f22938),Int,Int,Int,Int}
world = typemax(UInt)
world = Base.get_world_counter()
match = Base._methods_by_ftype(msig, -1, world)[]
mi = Core.Compiler.specialize_method(match)
c0 = Core.Compiler.retrieve_code_info(mi)
Expand Down