From 72f02dfb6f2ff78664aed7da899419404b4b5520 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 7 Jan 2022 23:38:09 -0500 Subject: [PATCH] reflection: use a real world for lookups (#43695) --- base/reflection.jl | 17 +++++++++-------- stdlib/InteractiveUtils/src/codeview.jl | 2 +- stdlib/Test/src/Test.jl | 10 ++++++---- test/compiler/contextual.jl | 6 +++--- test/compiler/inference.jl | 2 +- test/compiler/validation.jl | 2 +- 6 files changed, 21 insertions(+), 18 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index e245623a75704e..c9582865f0a403 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -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 @@ -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)) @@ -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 @@ -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`. @@ -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 @@ -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] @@ -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 diff --git a/stdlib/InteractiveUtils/src/codeview.jl b/stdlib/InteractiveUtils/src/codeview.jl index 7c749f0af27c8a..4e2164cb161a88 100644 --- a/stdlib/InteractiveUtils/src/codeview.jl +++ b/stdlib/InteractiveUtils/src/codeview.jl @@ -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 diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index a6dc6b0ef2d73e..dc0a3cf25ce0df 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -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 @@ -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 diff --git a/test/compiler/contextual.jl b/test/compiler/contextual.jl index 10fff8d90ff243..f20e02d3710703 100644 --- a/test/compiler/contextual.jl +++ b/test/compiler/contextual.jl @@ -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 diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index f101ef70dc5fe3..2fc06e67b639b8 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -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 diff --git a/test/compiler/validation.jl b/test/compiler/validation.jl index 6326cb709e30d3..ffa79ed1c823d4 100644 --- a/test/compiler/validation.jl +++ b/test/compiler/validation.jl @@ -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)