8888# and hence our re-use of the `callargs` field of Frame would introduce
8989# bugs. Since these nodes use a very limited repertoire of calls, we can special-case
9090# this quite easily.
91- function lookup_or_eval(@nospecialize(recurse) , frame:: Frame , @nospecialize(node))
91+ function lookup_or_eval(interp :: Interpreter , frame:: Frame , @nospecialize(node))
9292 if isa(node, SSAValue)
9393 return lookup_var(frame, node)
9494 elseif isa(node, SlotNumber)
@@ -102,7 +102,7 @@ function lookup_or_eval(@nospecialize(recurse), frame::Frame, @nospecialize(node
102102 elseif isa(node, Expr)
103103 ex = Expr(node. head)
104104 for arg in node. args
105- push!(ex. args, lookup_or_eval(recurse , frame, arg))
105+ push!(ex. args, lookup_or_eval(interp , frame, arg))
106106 end
107107 if ex. head === :call
108108 f = ex. args[1 ]
@@ -136,7 +136,7 @@ function lookup_or_eval(@nospecialize(recurse), frame::Frame, @nospecialize(node
136136 elseif isa(node, Type)
137137 return node
138138 end
139- return eval_rhs(recurse , frame, node)
139+ return eval_rhs(interp , frame, node)
140140end
141141
142142function resolvefc(frame:: Frame , @nospecialize(expr))
@@ -159,13 +159,13 @@ function resolvefc(frame::Frame, @nospecialize(expr))
159159 @invokelatest error(" unexpected ccall to " , expr)
160160end
161161
162- function collect_args(@nospecialize(recurse) , frame:: Frame , call_expr:: Expr ; isfc:: Bool = false )
162+ function collect_args(interp :: Interpreter , frame:: Frame , call_expr:: Expr ; isfc:: Bool = false )
163163 args = frame. framedata. callargs
164164 resize!(args, length(call_expr. args))
165165 args[1 ] = isfc ? resolvefc(frame, call_expr. args[1 ]) : lookup(frame, call_expr. args[1 ])
166166 for i = 2 : length(args)
167167 if isexpr(call_expr. args[i], :call)
168- args[i] = lookup_or_eval(recurse , frame, call_expr. args[i])
168+ args[i] = lookup_or_eval(interp , frame, call_expr. args[i])
169169 else
170170 args[i] = lookup(frame, call_expr. args[i])
171171 end
@@ -174,13 +174,13 @@ function collect_args(@nospecialize(recurse), frame::Frame, call_expr::Expr; isf
174174end
175175
176176"""
177- ret = evaluate_foreigncall(recurse , frame::Frame, call_expr)
177+ ret = evaluate_foreigncall(interp , frame::Frame, call_expr)
178178
179179Evaluate a `:foreigncall` (from a `ccall`) statement `callexpr` in the context of `frame`.
180180"""
181- function evaluate_foreigncall(@nospecialize(recurse) , frame:: Frame , call_expr:: Expr )
181+ function evaluate_foreigncall(interp :: Interpreter , frame:: Frame , call_expr:: Expr )
182182 head = call_expr. head
183- args = collect_args(recurse , frame, call_expr; isfc = head === :foreigncall)
183+ args = collect_args(interp , frame, call_expr; isfc = head === :foreigncall)
184184 for i = 2 : length(args)
185185 arg = args[i]
186186 args[i] = isa(arg, Symbol) ? QuoteNode(arg) : arg
@@ -210,11 +210,11 @@ function evaluate_foreigncall(@nospecialize(recurse), frame::Frame, call_expr::E
210210end
211211
212212# We have to intercept ccalls / llvmcalls before we try it as a builtin
213- function bypass_builtins(@nospecialize(recurse) , frame:: Frame , call_expr:: Expr , pc:: Int )
213+ function bypass_builtins(interp :: Interpreter , frame:: Frame , call_expr:: Expr , pc:: Int )
214214 if isassigned(frame. framecode. methodtables, pc)
215215 tme = frame. framecode. methodtables[pc]
216216 if isa(tme, Compiled)
217- fargs = collect_args(recurse , frame, call_expr)
217+ fargs = collect_args(interp , frame, call_expr)
218218 f = to_function(fargs[1 ])
219219 fmod = parentmodule(f):: Module
220220 if fmod === JuliaInterpreter. CompiledCalls || fmod === Core. Compiler
@@ -243,25 +243,25 @@ function native_call(fargs::Vector{Any}, frame::Frame)
243243 return @invokelatest f(fargs... )
244244end
245245
246- function evaluate_call_compiled!( :: Compiled , frame:: Frame , call_expr:: Expr ; enter_generated:: Bool = false )
246+ function evaluate_call!(interp :: Compiled , frame:: Frame , call_expr:: Expr , enter_generated:: Bool = false )
247247 # @assert !enter_generated
248248 pc = frame. pc
249- ret = bypass_builtins(Compiled() , frame, call_expr, pc)
249+ ret = bypass_builtins(interp , frame, call_expr, pc)
250250 isa(ret, Some{Any}) && return ret. value
251251 ret = maybe_evaluate_builtin(frame, call_expr, false )
252252 isa(ret, Some{Any}) && return ret. value
253- fargs = collect_args(Compiled() , frame, call_expr)
253+ fargs = collect_args(interp , frame, call_expr)
254254 return native_call(fargs, frame)
255255end
256256
257- function evaluate_call_recurse!(@nospecialize(recurse) , frame:: Frame , call_expr:: Expr ; enter_generated:: Bool = false )
257+ function evaluate_call!(interp :: Interpreter , frame:: Frame , call_expr:: Expr , enter_generated:: Bool = false )
258258 pc = frame. pc
259- ret = bypass_builtins(recurse , frame, call_expr, pc)
259+ ret = bypass_builtins(interp , frame, call_expr, pc)
260260 isa(ret, Some{Any}) && return ret. value
261261 ret = maybe_evaluate_builtin(frame, call_expr, true )
262262 isa(ret, Some{Any}) && return ret. value
263263 call_expr = ret
264- fargs = collect_args(recurse , frame, call_expr)
264+ fargs = collect_args(interp , frame, call_expr)
265265 if fargs[1 ] === Core. eval
266266 return Core. eval(fargs[2 ], fargs[3 ]) # not a builtin, but worth treating specially
267267 elseif fargs[1 ] === Base. rethrow
@@ -291,30 +291,24 @@ function evaluate_call_recurse!(@nospecialize(recurse), frame::Frame, call_expr:
291291 npc = newframe. pc
292292 shouldbreak(newframe, npc) && return BreakpointRef(newframe. framecode, npc)
293293 # if the following errors, handle_err will pop the stack and recycle newframe
294- if recurse === finish_and_return!
295- # Optimize this case to avoid dynamic dispatch
296- ret = finish_and_return!(finish_and_return!, newframe, false )
297- else
298- ret = recurse(recurse, newframe, false )
299- end
294+ ret = finish_and_return!(interp, newframe, false )
300295 isa(ret, BreakpointRef) && return ret
301296 frame. callee = nothing
302297 return_from(newframe)
303298 return ret
304299end
305300
306301"""
307- ret = evaluate_call!(Compiled() , frame::Frame, call_expr)
308- ret = evaluate_call!(recurse, frame::Frame, call_expr)
302+ ret = evaluate_call!(interp::Interpreter , frame::Frame, call_expr::Expr, enter_generated::Bool=false )
303+ ret = evaluate_call!(frame::Frame, call_expr::Expr, enter_generated::Bool=false )
309304
310305Evaluate a `:call` expression `call_expr` in the context of `frame`.
311306The first causes it to be executed using Julia's normal dispatch (compiled code),
312307whereas the second recurses in via the interpreter.
313- `recurse ` has a default value of [`JuliaInterpreter.finish_and_return! `](@ref).
308+ `interp ` has a default value of [`RecursiveInterpreter `](@ref).
314309"""
315- evaluate_call!(:: Compiled , frame:: Frame , call_expr:: Expr ; kwargs... ) = evaluate_call_compiled!(Compiled(), frame, call_expr; kwargs... )
316- evaluate_call!(@nospecialize(recurse), frame:: Frame , call_expr:: Expr ; kwargs... ) = evaluate_call_recurse!(recurse, frame, call_expr; kwargs... )
317- evaluate_call!(frame:: Frame , call_expr:: Expr ; kwargs... ) = evaluate_call!(finish_and_return!, frame, call_expr; kwargs... )
310+ evaluate_call!(frame:: Frame , call_expr:: Expr , enter_generated:: Bool = false ) =
311+ evaluate_call!(RecursiveInterpreter(), frame, call_expr, enter_generated)
318312
319313# The following come up only when evaluating toplevel code
320314function evaluate_methoddef(frame:: Frame , node:: Expr )
@@ -398,7 +392,7 @@ function maybe_assign!(frame::Frame, @nospecialize(stmt), @nospecialize(val))
398392end
399393maybe_assign!(frame:: Frame , @nospecialize(val)) = maybe_assign!(frame, pc_expr(frame), val)
400394
401- function eval_rhs(@nospecialize(recurse) , frame:: Frame , node:: Expr )
395+ function eval_rhs(interp :: Interpreter , frame:: Frame , node:: Expr )
402396 head = node. head
403397 if head === :new
404398 args = Any[lookup(frame, arg) for arg in node. args]
@@ -413,11 +407,9 @@ function eval_rhs(@nospecialize(recurse), frame::Frame, node::Expr)
413407 elseif head === :isdefined
414408 return check_isdefined(frame, node. args[1 ])
415409 elseif head === :call
416- # here it's crucial to avoid dynamic dispatch
417- isa(recurse, Compiled) && return evaluate_call_compiled!(recurse, frame, node)
418- return evaluate_call_recurse!(recurse, frame, node)
410+ return evaluate_call!(interp, frame, node)
419411 elseif head === :foreigncall || head === :cfunction
420- return evaluate_foreigncall(recurse , frame, node)
412+ return evaluate_foreigncall(interp , frame, node)
421413 elseif head === :copyast
422414 val = (node. args[1 ]:: QuoteNode ). value
423415 return isa(val, Expr) ? copy(val) : val
481473# in `step_expr!`
482474const _location = Dict{Tuple{Method,Int},Int}()
483475
484- function step_expr!(@nospecialize(recurse) , frame:: Frame , @nospecialize(node), istoplevel:: Bool )
476+ function step_expr!(interp :: Interpreter , frame:: Frame , @nospecialize(node), istoplevel:: Bool )
485477 pc, code, data = frame. pc, frame. framecode, frame. framedata
486478 # if !is_leaf(frame)
487479 # show_stackloc(frame)
@@ -501,7 +493,7 @@ function step_expr!(@nospecialize(recurse), frame::Frame, @nospecialize(node), i
501493 if node. head === :(= )
502494 lhs, rhs = node. args
503495 if isa(rhs, Expr)
504- rhs = eval_rhs(recurse , frame, rhs)
496+ rhs = eval_rhs(interp , frame, rhs)
505497 else
506498 rhs = lookup(frame, rhs)
507499 end
@@ -547,12 +539,12 @@ function step_expr!(@nospecialize(recurse), frame::Frame, @nospecialize(node), i
547539 end
548540 elseif node. head === :thunk
549541 newframe = Frame(moduleof(frame), node. args[1 ]:: CodeInfo )
550- if isa(recurse , Compiled)
551- finish!(recurse , newframe, true )
542+ if isa(interp , Compiled)
543+ finish!(interp , newframe, true )
552544 else
553545 newframe. caller = frame
554546 frame. callee = newframe
555- finish!(recurse , newframe, true )
547+ finish!(interp , newframe, true )
556548 frame. callee = nothing
557549 end
558550 return_from(newframe)
@@ -569,7 +561,7 @@ function step_expr!(@nospecialize(recurse), frame::Frame, @nospecialize(node), i
569561 end
570562 newframe = ($ Frame)(mod, ex)
571563 while true
572- ($ through_methoddef_or_done!)($ recurse , newframe) === nothing && break
564+ ($ through_methoddef_or_done!)($ interp , newframe) === nothing && break
573565 end
574566 $ return_from(newframe)
575567 end )))
@@ -580,12 +572,12 @@ function step_expr!(@nospecialize(recurse), frame::Frame, @nospecialize(node), i
580572 elseif node. head === :latestworld
581573 frame. world = Base. get_world_counter()
582574 else
583- rhs = eval_rhs(recurse , frame, node)
575+ rhs = eval_rhs(interp , frame, node)
584576 end
585577 elseif node. head === :thunk || node. head === :toplevel
586578 error(" this frame needs to be run at top level" )
587579 else
588- rhs = eval_rhs(recurse , frame, node)
580+ rhs = eval_rhs(interp , frame, node)
589581 end
590582 elseif isa(node, GotoNode)
591583 @assert is_leaf(frame)
@@ -616,7 +608,7 @@ function step_expr!(@nospecialize(recurse), frame::Frame, @nospecialize(node), i
616608 rhs = lookup(frame, node)
617609 end
618610 catch err
619- return handle_err(recurse , frame, err)
611+ return handle_err(interp , frame, err)
620612 end
621613 @isdefined(rhs) && isa(rhs, BreakpointRef) && return rhs
622614 if isassign(frame, pc)
@@ -631,25 +623,24 @@ function step_expr!(@nospecialize(recurse), frame::Frame, @nospecialize(node), i
631623end
632624
633625"""
634- pc = step_expr!(recurse , frame, istoplevel=false)
626+ pc = step_expr!(interp::Interpreter , frame, istoplevel=false)
635627 pc = step_expr!(frame, istoplevel=false)
636628
637629Execute the next statement in `frame`. `pc` is the new program counter, or `nothing`
638630if execution terminates, or a [`BreakpointRef`](@ref) if execution hits a breakpoint.
639631
640- `recurse ` controls call evaluation; `recurse = Compiled()` evaluates :call expressions
641- by normal dispatch. The default value `recurse = finish_and_return! ` will use recursive
632+ `interp ` controls call evaluation; `interp = Compiled()` evaluates :call expressions
633+ by normal dispatch. The default value `interp = RecursiveInterpreter() ` will use recursive
642634interpretation.
643635
644636If you are evaluating `frame` at module scope you should pass `istoplevel=true`.
645637"""
646- step_expr!(@nospecialize(recurse), frame:: Frame , istoplevel:: Bool = false ) =
647- step_expr!(recurse, frame, pc_expr(frame), istoplevel)
648- step_expr!(frame:: Frame , istoplevel:: Bool = false ) =
649- step_expr!(finish_and_return!, frame, istoplevel)
638+ step_expr!(interp:: Interpreter , frame:: Frame , istoplevel:: Bool = false ) =
639+ step_expr!(interp, frame, pc_expr(frame), istoplevel)
640+ step_expr!(frame:: Frame , istoplevel:: Bool = false ) = step_expr!(RecursiveInterpreter(), frame, istoplevel)
650641
651642"""
652- loc = handle_err(recurse , frame, err)
643+ loc = handle_err(interp , frame, err)
653644
654645Deal with an error `err` that arose while evaluating `frame`. There are one of three
655646behaviors:
@@ -660,7 +651,7 @@ behaviors:
660651 `loc` is a `BreakpointRef`;
661652- otherwise, `err` gets rethrown.
662653"""
663- function handle_err(@nospecialize(recurse) , frame:: Frame , @nospecialize(err))
654+ function handle_err(:: Interpreter , frame:: Frame , @nospecialize(err))
664655 data = frame. framedata
665656 err_will_be_thrown_to_top_level = isempty(data. exception_frames) && ! data. caller_will_catch_err
666657 if break_on_throw[] || (break_on_error[] && err_will_be_thrown_to_top_level)
@@ -692,15 +683,16 @@ end
692683lookup_return(frame:: Frame , node:: ReturnNode ) = lookup(frame, node. val)
693684
694685"""
695- ret = get_return(frame)
686+ ret = get_return(interp, frame)
696687
697688Get the return value of `frame`. Throws an error if `frame.pc` does not point to a `return` expression.
698689`frame` must have already been executed so that the return value has been computed (see,
699690e.g., [`JuliaInterpreter.finish!`](@ref)).
700691"""
701- function get_return(frame)
692+ function get_return(interp :: Interpreter , frame:: Frame )
702693 node = pc_expr(frame)
703694 is_return(node) || @invokelatest error(" expected return statement, got " , node)
704695 return lookup_return(frame, node)
705696end
697+ get_return(frame:: Frame ) = get_return(RecursiveInterpreter(), frame)
706698get_return(t:: Tuple{Module,Expr,Frame} ) = get_return(t[end ])
0 commit comments