Skip to content

Commit 8548679

Browse files
committed
Add missing handling for methods defined for external method tables
1 parent b8520fc commit 8548679

File tree

4 files changed

+31
-19
lines changed

4 files changed

+31
-19
lines changed

src/codeedges.jl

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -242,27 +242,25 @@ function direct_links!(cl::CodeLinks, src::CodeInfo)
242242
add_inner!(cl, icl, i)
243243
continue
244244
elseif isexpr(stmt, :method)
245-
if length(stmt.args) === 3 && (arg3 = stmt.args[3]; arg3 isa CodeInfo)
246-
icl = CodeLinks(cl.thismod, arg3)
247-
add_inner!(cl, icl, i)
248-
end
249-
name = stmt.args[1]
250-
if isa(name, GlobalRef) || isa(name, Symbol)
245+
if length(stmt.args) === 1
246+
# A function with no methods was defined. Associate its new binding to it.
247+
name = stmt.args[1]
251248
if isa(name, Symbol)
252249
name = GlobalRef(cl.thismod, name)
253250
end
254-
assign = get(cl.nameassigns, name, nothing)
255-
if assign === nothing
256-
cl.nameassigns[name] = assign = Int[]
251+
if !isa(name, GlobalRef)
252+
@show stmt
253+
error("name ", typeof(name), " not recognized")
257254
end
255+
assign = get!(Vector{Int}, cl.nameassigns, name)
258256
push!(assign, i)
259257
targetstore = get!(Links, cl.namepreds, name)
260258
target = P(name, targetstore)
261259
add_links!(target, stmt, cl)
262-
elseif name in (nothing, false)
263-
else
264-
@show stmt
265-
error("name ", typeof(name), " not recognized")
260+
elseif length(stmt.args) === 3 && (arg3 = stmt.args[3]; arg3 isa CodeInfo) # method definition
261+
# A method was defined for an existing function.
262+
icl = CodeLinks(cl.thismod, arg3)
263+
add_inner!(cl, icl, i)
266264
end
267265
rhs = stmt
268266
target = P(SSAValue(i), cl.ssapreds[i])

src/packagedef.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Base.Experimental.@optlevel 1
22

3-
using Core: SimpleVector
3+
using Core: SimpleVector, MethodTable
44
using Core.IR: CodeInfo, GotoIfNot, GotoNode, IR, MethodInstance, ReturnNode
55
@static if isdefined(Core.IR, :EnterNode)
66
using Core.IR: EnterNode

src/signatures.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function signature(@nospecialize(recurse), frame::Frame, @nospecialize(stmt), pc
5353
stmt = pc_expr(frame, pc)
5454
end
5555
isa(stmt, Expr) || return nothing, pc
56-
mt = extract_method_table(frame, stmt; eval = false)
56+
mt = extract_method_table(frame, stmt)
5757
sigsv = @lookup(frame, stmt.args[2])::SimpleVector
5858
sigt = signature(sigsv)
5959
return MethodInfoKey(mt, sigt), lastpc
@@ -189,7 +189,9 @@ function identify_framemethod_calls(frame)
189189
end
190190
msrc = stmt.args[3]
191191
if msrc isa CodeInfo
192-
key = key::Union{GlobalRef,Bool,Nothing}
192+
# XXX: Properly support interpolated `Core.MethodTable`. This will require using
193+
# `stmt.args[2]` instead of `stmt.args[1]` to identify the parent function.
194+
isa(key, Union{GlobalRef,Bool,Nothing}) || continue
193195
for (j, mstmt) in enumerate(msrc.code)
194196
isa(mstmt, Expr) || continue
195197
jj = j
@@ -548,7 +550,7 @@ function methoddef!(@nospecialize(recurse), signatures::Vector{MethodInfoKey}, f
548550
if isa(meth, Method) && (meth.sig <: sigt && sigt <: meth.sig)
549551
push!(signatures, mt => meth.sig)
550552
else
551-
if arg1 === false || arg1 === nothing
553+
if arg1 === false || arg1 === nothing || isa(mt, MethodTable)
552554
# If it's anonymous and not defined, define it
553555
pc = step_expr!(recurse, frame, stmt, true)
554556
meth = whichtt(sigt, mt)

test/signatures.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,12 @@ end
505505

506506
end
507507

508+
module ExternalMT
509+
Base.Experimental.@MethodTable method_table
510+
macro overlay(ex) esc(:(Base.Experimental.@overlay $method_table $ex)) end
511+
end
512+
508513
@testset "Support for external method tables" begin
509-
ExternalMT = Module()
510-
Core.eval(ExternalMT, :(Base.Experimental.@MethodTable method_table))
511514
signatures = MethodInfoKey[]
512515

513516
ex = :(foo(x) = "foo")
@@ -525,6 +528,15 @@ end
525528
@test length(signatures) == 1
526529
(mt, sig) = pop!(signatures)
527530
@test (mt, sig) === (ExternalMT.method_table, Tuple{typeof(ExternalMT.foo), Any})
531+
532+
ex = :(@overlay foo(x::Int64) = "overlayed foo, second edition")
533+
Core.eval(ExternalMT, ex)
534+
frame = Frame(ExternalMT, ex)
535+
pc = methoddefs!(signatures, frame; define = false)
536+
@test length(signatures) == 1
537+
(mt, sig) = pop!(signatures)
538+
@test (mt, sig) === (ExternalMT.method_table, Tuple{typeof(ExternalMT.foo), Int64})
539+
LoweredCodeUtils.identify_framemethod_calls(frame) # make sure this does not throw
528540
end
529541

530542
end # module signatures

0 commit comments

Comments
 (0)