@@ -24,17 +24,17 @@ function signature(sigsv::SimpleVector)
24
24
end
25
25
26
26
"""
27
- sigt, lastpc = signature([interp::Interpreter=RecursiveInterpreter()], frame::Frame, pc::Int)
27
+ (mt, sigt) , lastpc = signature([interp::Interpreter=RecursiveInterpreter()], frame::Frame, pc::Int)
28
28
29
- Compute the signature-type `sigt` of a method whose definition in `frame` starts at `pc`.
29
+ Compute the method table `mt` and signature-type `sigt` of a method whose definition in `frame` starts at `pc`.
30
30
Generally, `pc` should point to the `Expr(:method, methname)` statement, in which case
31
31
`lastpc` is the final statement number in `frame` that is part of the signature
32
32
(i.e, the line above the 3-argument `:method` expression).
33
33
Alternatively, `pc` can point to the 3-argument `:method` expression,
34
34
as long as all the relevant SSAValues have been assigned.
35
35
In this case, `lastpc == pc`.
36
36
37
- If no 3-argument `:method` expression is found, `sigt ` will be `nothing `.
37
+ If no 3-argument `:method` expression is found, `nothing ` will be returned in place of `(mt, sigt) `.
38
38
"""
39
39
function signature (interp:: Interpreter , frame:: Frame , @nospecialize (stmt), pc:: Int )
40
40
mod = moduleof (frame)
@@ -52,9 +52,10 @@ function signature(interp::Interpreter, frame::Frame, @nospecialize(stmt), pc::I
52
52
stmt = pc_expr (frame, pc)
53
53
end
54
54
isa (stmt, Expr) || return nothing , pc
55
+ mt = extract_method_table (frame, stmt)
55
56
sigsv = lookup (interp, frame, stmt. args[2 ]):: SimpleVector
56
57
sigt = signature (sigsv)
57
- return sigt, lastpc
58
+ return MethodInfoKey (mt, sigt) , lastpc
58
59
end
59
60
signature (interp:: Interpreter , frame:: Frame , pc:: Int ) = signature (interp, frame, pc_expr (frame, pc), pc)
60
61
signature (frame:: Frame , pc:: Int ) = signature (RecursiveInterpreter (), frame, pc)
@@ -187,7 +188,9 @@ function identify_framemethod_calls(frame::Frame)
187
188
end
188
189
msrc = stmt. args[3 ]
189
190
if msrc isa CodeInfo
190
- key = key:: Union{GlobalRef,Bool,Nothing}
191
+ # XXX : Properly support interpolated `Core.MethodTable`. This will require using
192
+ # `stmt.args[2]` instead of `stmt.args[1]` to identify the parent function.
193
+ isa (key, Union{GlobalRef,Bool,Nothing}) || continue
191
194
for (j, mstmt) in enumerate (msrc. code)
192
195
isa (mstmt, Expr) || continue
193
196
jj = j
@@ -444,9 +447,9 @@ function get_running_name(interp::Interpreter, frame::Frame, pc::Int, name::Glob
444
447
pctop -= 1
445
448
stmt = pc_expr (frame, pctop)
446
449
end # end fix
447
- sigtparent, lastpcparent = signature (interp, frame, pctop)
450
+ (mt, sigtparent) , lastpcparent = signature (interp, frame, pctop)
448
451
sigtparent === nothing && return name, pc, lastpcparent
449
- methparent = whichtt (sigtparent)
452
+ methparent = whichtt (sigtparent, mt )
450
453
methparent === nothing && return name, pc, lastpcparent # caller isn't defined, no correction is needed
451
454
if isgen
452
455
cname = GlobalRef (moduleof (frame), nameof (methparent. generator. gen))
515
518
"""
516
519
ret = methoddef!([interp::Interpreter=RecursiveInterpreter()], signatures, frame; define=true)
517
520
518
- Compute the signature of a method definition. `frame.pc` should point to a
519
- `:method` expression. Upon exit, the new signature will be added to `signatures`.
521
+ Compute the method table/ signature pair of a method definition. `frame.pc` should point to a
522
+ `:method` expression. Upon exit, the new method table/ signature pair will be added to `signatures`.
520
523
521
524
There are several possible return values:
522
525
@@ -535,27 +538,27 @@ occurs for "empty method" expressions, e.g., `:(function foo end)`. `pc` will be
535
538
By default the method will be defined (evaluated). You can prevent this by setting `define=false`.
536
539
This is recommended if you are simply extracting signatures from code that has already been evaluated.
537
540
"""
538
- function methoddef! (interp:: Interpreter , signatures, frame:: Frame , @nospecialize (stmt), pc:: Int ; define:: Bool = true )
541
+ function methoddef! (interp:: Interpreter , signatures:: Vector{MethodInfoKey} , frame:: Frame , @nospecialize (stmt), pc:: Int ; define:: Bool = true )
539
542
framecode, pcin = frame. framecode, pc
540
543
if ismethod3 (stmt)
541
544
pc3 = pc
542
545
arg1 = stmt. args[1 ]
543
- sigt, pc = signature (interp, frame, stmt, pc)
544
- meth = whichtt (sigt)
546
+ (mt, sigt) , pc = signature (interp, frame, stmt, pc)
547
+ meth = whichtt (sigt, mt )
545
548
if isa (meth, Method) && (meth. sig <: sigt && sigt <: meth.sig )
546
549
pc = define ? step_expr! (interp, frame, stmt, true ) : next_or_nothing! (interp, frame)
547
550
elseif define
548
551
pc = step_expr! (interp, frame, stmt, true )
549
- meth = whichtt (sigt)
552
+ meth = whichtt (sigt, mt )
550
553
end
551
554
if isa (meth, Method) && (meth. sig <: sigt && sigt <: meth.sig )
552
- push! (signatures, meth. sig)
555
+ push! (signatures, mt => meth. sig)
553
556
else
554
- if arg1 === false || arg1 === nothing
557
+ if arg1 === false || arg1 === nothing || isa (mt, MethodTable)
555
558
# If it's anonymous and not defined, define it
556
559
pc = step_expr! (interp, frame, stmt, true )
557
- meth = whichtt (sigt)
558
- isa (meth, Method) && push! (signatures, meth. sig)
560
+ meth = whichtt (sigt, mt )
561
+ isa (meth, Method) && push! (signatures, mt => meth. sig)
559
562
return pc, pc3
560
563
else
561
564
# guard against busted lookup, e.g., https://github.com/JuliaLang/julia/issues/31112
@@ -596,7 +599,7 @@ function methoddef!(interp::Interpreter, signatures, frame::Frame, @nospecialize
596
599
end
597
600
found || return nothing
598
601
while true # methods containing inner methods may need multiple trips through this loop
599
- sigt, pc = signature (interp, frame, stmt, pc)
602
+ (mt, sigt) , pc = signature (interp, frame, stmt, pc)
600
603
stmt = pc_expr (frame, pc)
601
604
while ! isexpr (stmt, :method , 3 )
602
605
pc = next_or_nothing (interp, frame, pc) # this should not check define, we've probably already done this once
@@ -611,15 +614,15 @@ function methoddef!(interp::Interpreter, signatures, frame::Frame, @nospecialize
611
614
# signature of the active method. So let's get the active signature.
612
615
frame. pc = pc
613
616
pc = define ? step_expr! (interp, frame, stmt, true ) : next_or_nothing! (interp, frame)
614
- meth = whichtt (sigt)
615
- isa (meth, Method) && push! (signatures, meth. sig) # inner methods are not visible
617
+ meth = whichtt (sigt, mt )
618
+ isa (meth, Method) && push! (signatures, mt => meth. sig) # inner methods are not visible
616
619
name === name3 && return pc, pc3 # if this was an inner method we should keep going
617
620
stmt = pc_expr (frame, pc) # there *should* be more statements in this frame
618
621
end
619
622
end
620
- methoddef! (interp:: Interpreter , signatures, frame:: Frame , pc:: Int ; define:: Bool = true ) =
623
+ methoddef! (interp:: Interpreter , signatures:: Vector{MethodInfoKey} , frame:: Frame , pc:: Int ; define:: Bool = true ) =
621
624
methoddef! (interp, signatures, frame, pc_expr (frame, pc), pc; define)
622
- function methoddef! (interp:: Interpreter , signatures, frame:: Frame ; define:: Bool = true )
625
+ function methoddef! (interp:: Interpreter , signatures:: Vector{MethodInfoKey} , frame:: Frame ; define:: Bool = true )
623
626
pc = frame. pc
624
627
stmt = pc_expr (frame, pc)
625
628
if ! ismethod (stmt)
@@ -628,27 +631,27 @@ function methoddef!(interp::Interpreter, signatures, frame::Frame; define::Bool=
628
631
pc === nothing && error (" pc at end of frame without finding a method" )
629
632
methoddef! (interp, signatures, frame, pc; define)
630
633
end
631
- methoddef! (signatures, frame:: Frame , pc:: Int ; define:: Bool = true ) =
634
+ methoddef! (signatures:: Vector{MethodInfoKey} , frame:: Frame , pc:: Int ; define:: Bool = true ) =
632
635
methoddef! (RecursiveInterpreter (), signatures, frame, pc_expr (frame, pc), pc; define)
633
- methoddef! (signatures, frame:: Frame ; define:: Bool = true ) =
636
+ methoddef! (signatures:: Vector{MethodInfoKey} , frame:: Frame ; define:: Bool = true ) =
634
637
methoddef! (RecursiveInterpreter (), signatures, frame; define)
635
638
636
- function methoddefs! (interp:: Interpreter , signatures, frame:: Frame , pc:: Int ; define:: Bool = true )
639
+ function methoddefs! (interp:: Interpreter , signatures:: Vector{MethodInfoKey} , frame:: Frame , pc:: Int ; define:: Bool = true )
637
640
ret = methoddef! (interp, signatures, frame, pc; define)
638
641
pc = ret === nothing ? ret : ret[1 ]
639
642
return _methoddefs! (interp, signatures, frame, pc; define)
640
643
end
641
- function methoddefs! (interp:: Interpreter , signatures, frame:: Frame ; define:: Bool = true )
644
+ function methoddefs! (interp:: Interpreter , signatures:: Vector{MethodInfoKey} , frame:: Frame ; define:: Bool = true )
642
645
ret = methoddef! (interp, signatures, frame; define)
643
646
pc = ret === nothing ? ret : ret[1 ]
644
647
return _methoddefs! (interp, signatures, frame, pc; define)
645
648
end
646
- methoddefs! (signatures, frame:: Frame , pc:: Int ; define:: Bool = true ) =
649
+ methoddefs! (signatures:: Vector{MethodInfoKey} , frame:: Frame , pc:: Int ; define:: Bool = true ) =
647
650
methoddefs! (RecursiveInterpreter (), signatures, frame, pc; define)
648
- methoddefs! (signatures, frame:: Frame ; define:: Bool = true ) =
651
+ methoddefs! (signatures:: Vector{MethodInfoKey} , frame:: Frame ; define:: Bool = true ) =
649
652
methoddefs! (RecursiveInterpreter (), signatures, frame; define)
650
653
651
- function _methoddefs! (interp:: Interpreter , signatures, frame:: Frame , pc:: Int ; define:: Bool = define)
654
+ function _methoddefs! (interp:: Interpreter , signatures:: Vector{MethodInfoKey} , frame:: Frame , pc:: Int ; define:: Bool = define)
652
655
while pc != = nothing
653
656
stmt = pc_expr (frame, pc)
654
657
if ! ismethod (stmt)
0 commit comments