Skip to content

Commit

Permalink
reflection: use a real world for lookups (JuliaLang#43695)
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash authored and LilithHafner committed Mar 8, 2022
1 parent 4c4376f commit 52b86d8
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 18 deletions.
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 @@ -1761,7 +1762,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

0 comments on commit 52b86d8

Please sign in to comment.