Skip to content

Commit

Permalink
Clean direct ccalls to jl_specializations_get_linfo (#39490)
Browse files Browse the repository at this point in the history
Many of these were using an incorrect (outdated) signature for this ccall.
We now wrap this method in Core.Compiler.specialize_method, so
clean up all the places that were using it directly.
  • Loading branch information
Keno committed Feb 3, 2021
1 parent 6b91bbb commit 7b19e09
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 37 deletions.
4 changes: 2 additions & 2 deletions base/compiler/methodtable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ function findsup(@nospecialize(sig::Type{<:Tuple}), table::InternalMethodTable)
min_valid = RefValue{UInt}(typemin(UInt))
max_valid = RefValue{UInt}(typemax(UInt))
result = ccall(:jl_gf_invoke_lookup_worlds, Any, (Any, UInt, Ptr{Csize_t}, Ptr{Csize_t}),
sig, table.world, min_valid, max_valid)::Union{Method, Nothing}
sig, table.world, min_valid, max_valid)::Union{MethodMatch, Nothing}
result === nothing && return nothing
(result, WorldRange(min_valid[], max_valid[]))
(result.method, WorldRange(min_valid[], max_valid[]))
end

# This query is not cached
Expand Down
29 changes: 22 additions & 7 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,14 @@ function _methods_by_ftype(@nospecialize(t), lim::Int, world::UInt, ambig::Bool,
return ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}, Ptr{Int32}), t, lim, ambig, world, min, max, has_ambig)::Union{Array{Any,1}, Bool}
end

function _method_by_ftype(args...)
matches = _methods_by_ftype(args...)
if length(matches) != 1
error("no unique matching method found for the specified argument types")
end
return matches[1]
end

# high-level, more convenient method lookup functions

# type for reflecting and pretty-printing a subset of methods
Expand Down Expand Up @@ -1019,8 +1027,7 @@ function method_instances(@nospecialize(f), @nospecialize(t), world::UInt = type
tt = signature_type(f, t)
results = Core.MethodInstance[]
for match in _methods_by_ftype(tt, -1, world)::Vector
instance = ccall(:jl_specializations_get_linfo, Ref{MethodInstance},
(Any, Any, Any), match.method, match.spec_types, match.sparams)
instance = Core.Compiler.specialize_method(match)
push!(results, instance)
end
return results
Expand Down Expand Up @@ -1259,6 +1266,18 @@ end

print_statement_costs(args...; kwargs...) = print_statement_costs(stdout, args...; kwargs...)

function _which(@nospecialize(tt::Type), world=typemax(UInt))
min_valid = RefValue{UInt}(typemin(UInt))
max_valid = RefValue{UInt}(typemax(UInt))
match = ccall(:jl_gf_invoke_lookup_worlds, Any,
(Any, UInt, Ptr{Csize_t}, Ptr{Csize_t}),
tt, typemax(UInt), min_valid, max_valid)
if match === nothing
error("no unique matching method found for the specified argument types")
end
return match::Core.MethodMatch
end

"""
which(f, types)
Expand All @@ -1281,11 +1300,7 @@ end
Returns the method that would be called by the given type signature (as a tuple type).
"""
function which(@nospecialize(tt::Type))
m = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), tt, typemax(UInt))
if m === nothing
error("no unique matching method found for the specified argument types")
end
return m::Method
return _which(tt).method
end

"""
Expand Down
2 changes: 1 addition & 1 deletion src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2459,7 +2459,7 @@ JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup_worlds(jl_value_t *types, size_t wo
jl_method_match_t *matc = _gf_invoke_lookup(types, world, min_world, max_world);
if (matc == NULL)
return jl_nothing;
return (jl_value_t*)matc->method;
return (jl_value_t*)matc;
}

// invoke()
Expand Down
8 changes: 2 additions & 6 deletions stdlib/InteractiveUtils/src/codeview.jl
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,8 @@ function _dump_function(@nospecialize(f), @nospecialize(t), native::Bool, wrappe
end
# get the MethodInstance for the method match
world = typemax(UInt)
meth = which(f, t)
t = to_tuple_type(t)
tt = signature_type(f, t)
(ti, env) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), tt, meth.sig)::Core.SimpleVector
meth = Base.func_for_method_checked(meth, ti, env)
linfo = ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any, UInt), meth, ti, env, world)
match = Base._which(signature_type(f, t), world)
linfo = Core.Compiler.specialize_method(match)
# get the code for it
if native
str = _dump_function_linfo_native(linfo, world, wrapper, syntax, debuginfo)
Expand Down
7 changes: 2 additions & 5 deletions test/compiler/contextual.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,8 @@ module MiniCassette
end

tt = Tuple{f, args...}
mthds = _methods_by_ftype(tt, -1, typemax(UInt))
@assert length(mthds) == 1
match = mthds[1]
mi = ccall(:jl_specializations_get_linfo, Ref{MethodInstance},
(Any, Any, Any), match.method, match.spec_types, match.sparams)
match = Base._method_by_ftype(tt, -1, typemax(UInt))
mi = Core.Compiler.specialize_method(match)
# Unsupported in this mini-cassette
@assert !mi.def.isva
code_info = retrieve_code_info(mi)
Expand Down
11 changes: 3 additions & 8 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1165,14 +1165,9 @@ function get_linfo(@nospecialize(f), @nospecialize(t))
throw(ArgumentError("argument is not a generic function"))
end
# get the MethodInstance for the method match
meth = which(f, t)
t = Base.to_tuple_type(t)
ft = isa(f, Type) ? Type{f} : typeof(f)
tt = Tuple{ft, t.parameters...}
precompile(tt) # does inference (calls jl_type_infer) on this signature
(ti, env) = ccall(:jl_type_intersection_with_env, Ref{Core.SimpleVector}, (Any, Any), tt, meth.sig)
return ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance},
(Any, Any, Any), meth, tt, env)
match = Base._which(Base.signature_type(f, t), typemax(UInt))
precompile(match.spec_types)
return Core.Compiler.specialize_method(match)
end

function test_const_return(@nospecialize(f), @nospecialize(t), @nospecialize(val))
Expand Down
9 changes: 3 additions & 6 deletions test/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,8 @@ precompile_test_harness(false) do dir
let some_method = which(Base.include, (Module, String,))
# global const some_method // FIXME: support for serializing a direct reference to an external Method not implemented
global const some_linfo =
ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any, UInt),
some_method, Tuple{typeof(Base.include), Module, String}, Core.svec(), typemax(UInt))
global const some_linfo = Core.Compiler.specialize_method(some_method,
Tuple{typeof(Base.include), Module, String}, Core.svec())
end
g() = override(1.0)
Expand Down Expand Up @@ -347,9 +346,7 @@ precompile_test_harness(false) do dir
Val{nothing}},
0:25)
some_method = which(Base.include, (Module, String,))
some_linfo =
ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any, UInt),
some_method, Tuple{typeof(Base.include), Module, String}, Core.svec(), typemax(UInt))
some_linfo = Core.Compiler.specialize_method(some_method, Tuple{typeof(Base.include), Module, String}, Core.svec())
@test Foo.some_linfo::Core.MethodInstance === some_linfo

ft = Base.datatype_fieldtypes
Expand Down
3 changes: 1 addition & 2 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1321,8 +1321,7 @@ end
(::T20332{T})(x) where T = 0

let m = which(T20332{Int}(), (Int,)),
mi = ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any, UInt),
m, Tuple{T20332{T}, Int} where T, Core.svec(), typemax(UInt))
mi = Core.Compiler.specialize_method(m, Tuple{T20332{T}, Int} where T, Core.svec())
# test that this doesn't throw an error
@test occursin("MethodInstance for", repr(mi))
end
Expand Down

0 comments on commit 7b19e09

Please sign in to comment.