@@ -24,17 +24,17 @@ function signature(sigsv::SimpleVector)
2424end
2525
2626"""
27- sigt, lastpc = signature([interp::Interpreter=RecursiveInterpreter()], frame::Frame, pc::Int)
27+ (mt, sigt) , lastpc = signature([interp::Interpreter=RecursiveInterpreter()], frame::Frame, pc::Int)
2828
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`.
3030Generally, `pc` should point to the `Expr(:method, methname)` statement, in which case
3131`lastpc` is the final statement number in `frame` that is part of the signature
3232(i.e, the line above the 3-argument `:method` expression).
3333Alternatively, `pc` can point to the 3-argument `:method` expression,
3434as long as all the relevant SSAValues have been assigned.
3535In this case, `lastpc == pc`.
3636
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) `.
3838"""
3939function signature (interp:: Interpreter , frame:: Frame , @nospecialize (stmt), pc:: Int )
4040 mod = moduleof (frame)
@@ -52,9 +52,10 @@ function signature(interp::Interpreter, frame::Frame, @nospecialize(stmt), pc::I
5252 stmt = pc_expr (frame, pc)
5353 end
5454 isa (stmt, Expr) || return nothing , pc
55+ mt = extract_method_table (frame, stmt)
5556 sigsv = lookup (interp, frame, stmt. args[2 ]):: SimpleVector
5657 sigt = signature (sigsv)
57- return sigt, lastpc
58+ return MethodInfoKey (mt, sigt) , lastpc
5859end
5960signature (interp:: Interpreter , frame:: Frame , pc:: Int ) = signature (interp, frame, pc_expr (frame, pc), pc)
6061signature (frame:: Frame , pc:: Int ) = signature (RecursiveInterpreter (), frame, pc)
@@ -187,7 +188,9 @@ function identify_framemethod_calls(frame::Frame)
187188 end
188189 msrc = stmt. args[3 ]
189190 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
191194 for (j, mstmt) in enumerate (msrc. code)
192195 isa (mstmt, Expr) || continue
193196 jj = j
@@ -444,9 +447,9 @@ function get_running_name(interp::Interpreter, frame::Frame, pc::Int, name::Glob
444447 pctop -= 1
445448 stmt = pc_expr (frame, pctop)
446449 end # end fix
447- sigtparent, lastpcparent = signature (interp, frame, pctop)
450+ (mt, sigtparent) , lastpcparent = signature (interp, frame, pctop)
448451 sigtparent === nothing && return name, pc, lastpcparent
449- methparent = whichtt (sigtparent)
452+ methparent = whichtt (sigtparent, mt )
450453 methparent === nothing && return name, pc, lastpcparent # caller isn't defined, no correction is needed
451454 if isgen
452455 cname = GlobalRef (moduleof (frame), nameof (methparent. generator. gen))
515518"""
516519 ret = methoddef!([interp::Interpreter=RecursiveInterpreter()], signatures, frame; define=true)
517520
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`.
520523
521524There are several possible return values:
522525
@@ -535,27 +538,27 @@ occurs for "empty method" expressions, e.g., `:(function foo end)`. `pc` will be
535538By default the method will be defined (evaluated). You can prevent this by setting `define=false`.
536539This is recommended if you are simply extracting signatures from code that has already been evaluated.
537540"""
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 )
539542 framecode, pcin = frame. framecode, pc
540543 if ismethod3 (stmt)
541544 pc3 = pc
542545 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 )
545548 if isa (meth, Method) && (meth. sig <: sigt && sigt <: meth.sig )
546549 pc = define ? step_expr! (interp, frame, stmt, true ) : next_or_nothing! (interp, frame)
547550 elseif define
548551 pc = step_expr! (interp, frame, stmt, true )
549- meth = whichtt (sigt)
552+ meth = whichtt (sigt, mt )
550553 end
551554 if isa (meth, Method) && (meth. sig <: sigt && sigt <: meth.sig )
552- push! (signatures, meth. sig)
555+ push! (signatures, mt => meth. sig)
553556 else
554- if arg1 === false || arg1 === nothing
557+ if arg1 === false || arg1 === nothing || isa (mt, MethodTable)
555558 # If it's anonymous and not defined, define it
556559 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)
559562 return pc, pc3
560563 else
561564 # 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
596599 end
597600 found || return nothing
598601 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)
600603 stmt = pc_expr (frame, pc)
601604 while ! isexpr (stmt, :method , 3 )
602605 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
611614 # signature of the active method. So let's get the active signature.
612615 frame. pc = pc
613616 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
616619 name === name3 && return pc, pc3 # if this was an inner method we should keep going
617620 stmt = pc_expr (frame, pc) # there *should* be more statements in this frame
618621 end
619622end
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 ) =
621624 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 )
623626 pc = frame. pc
624627 stmt = pc_expr (frame, pc)
625628 if ! ismethod (stmt)
@@ -628,27 +631,27 @@ function methoddef!(interp::Interpreter, signatures, frame::Frame; define::Bool=
628631 pc === nothing && error (" pc at end of frame without finding a method" )
629632 methoddef! (interp, signatures, frame, pc; define)
630633end
631- methoddef! (signatures, frame:: Frame , pc:: Int ; define:: Bool = true ) =
634+ methoddef! (signatures:: Vector{MethodInfoKey} , frame:: Frame , pc:: Int ; define:: Bool = true ) =
632635 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 ) =
634637 methoddef! (RecursiveInterpreter (), signatures, frame; define)
635638
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 )
637640 ret = methoddef! (interp, signatures, frame, pc; define)
638641 pc = ret === nothing ? ret : ret[1 ]
639642 return _methoddefs! (interp, signatures, frame, pc; define)
640643end
641- function methoddefs! (interp:: Interpreter , signatures, frame:: Frame ; define:: Bool = true )
644+ function methoddefs! (interp:: Interpreter , signatures:: Vector{MethodInfoKey} , frame:: Frame ; define:: Bool = true )
642645 ret = methoddef! (interp, signatures, frame; define)
643646 pc = ret === nothing ? ret : ret[1 ]
644647 return _methoddefs! (interp, signatures, frame, pc; define)
645648end
646- methoddefs! (signatures, frame:: Frame , pc:: Int ; define:: Bool = true ) =
649+ methoddefs! (signatures:: Vector{MethodInfoKey} , frame:: Frame , pc:: Int ; define:: Bool = true ) =
647650 methoddefs! (RecursiveInterpreter (), signatures, frame, pc; define)
648- methoddefs! (signatures, frame:: Frame ; define:: Bool = true ) =
651+ methoddefs! (signatures:: Vector{MethodInfoKey} , frame:: Frame ; define:: Bool = true ) =
649652 methoddefs! (RecursiveInterpreter (), signatures, frame; define)
650653
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)
652655 while pc != = nothing
653656 stmt = pc_expr (frame, pc)
654657 if ! ismethod (stmt)
0 commit comments