Skip to content

Commit 6a5027f

Browse files
committed
Fix local method tables for enter_generated
1 parent 7508239 commit 6a5027f

File tree

3 files changed

+21
-16
lines changed

3 files changed

+21
-16
lines changed

src/interpret.jl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ function bypass_builtins(frame, call_expr, pc)
173173
return nothing
174174
end
175175

176-
function evaluate_call_compiled!(::Compiled, frame::Frame, call_expr::Expr)
176+
function evaluate_call_compiled!(::Compiled, frame::Frame, call_expr::Expr; enter_generated::Bool=false)
177+
# @assert !enter_generated
177178
pc = frame.pc
178179
ret = bypass_builtins(frame, call_expr, pc)
179180
isa(ret, Some{Any}) && return ret.value
@@ -185,7 +186,7 @@ function evaluate_call_compiled!(::Compiled, frame::Frame, call_expr::Expr)
185186
return f(fargs...)
186187
end
187188

188-
function evaluate_call_recurse!(@nospecialize(recurse), frame::Frame, call_expr::Expr)
189+
function evaluate_call_recurse!(@nospecialize(recurse), frame::Frame, call_expr::Expr; enter_generated::Bool=false)
189190
pc = frame.pc
190191
ret = bypass_builtins(frame, call_expr, pc)
191192
isa(ret, Some{Any}) && return ret.value
@@ -198,7 +199,7 @@ function evaluate_call_recurse!(@nospecialize(recurse), frame::Frame, call_expr:
198199
err = length(fargs) > 1 ? fargs[2] : frame.framedata.last_exception[]
199200
throw(err)
200201
end
201-
framecode, lenv = get_call_framecode(fargs, frame.framecode, frame.pc)
202+
framecode, lenv = get_call_framecode(fargs, frame.framecode, frame.pc; enter_generated=enter_generated)
202203
if lenv === nothing
203204
if isa(framecode, Compiled)
204205
popfirst!(fargs) # now it's really just `args`
@@ -231,9 +232,9 @@ The first causes it to be executed using Julia's normal dispatch (compiled code)
231232
whereas the second recurses in via the interpreter.
232233
`recurse` has a default value of [`JuliaInterpreter.finish_and_return!`](@ref).
233234
"""
234-
evaluate_call!(::Compiled, frame::Frame, call_expr::Expr) = evaluate_call_compiled!(Compiled(), frame, call_expr)
235-
evaluate_call!(@nospecialize(recurse), frame::Frame, call_expr::Expr) = evaluate_call_recurse!(recurse, frame, call_expr)
236-
evaluate_call!(frame::Frame, call_expr::Expr) = evaluate_call!(finish_and_return!, frame, call_expr)
235+
evaluate_call!(::Compiled, frame::Frame, call_expr::Expr; kwargs...) = evaluate_call_compiled!(Compiled(), frame, call_expr; kwargs...)
236+
evaluate_call!(@nospecialize(recurse), frame::Frame, call_expr::Expr; kwargs...) = evaluate_call_recurse!(recurse, frame, call_expr; kwargs...)
237+
evaluate_call!(frame::Frame, call_expr::Expr; kwargs...) = evaluate_call!(finish_and_return!, frame, call_expr; kwargs...)
237238

238239
# The following come up only when evaluating toplevel code
239240
function evaluate_methoddef(frame, node)

src/localmethtable.jl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Return the framecode and environment for a call specified by `fargs = [f, args..
77
`parentframecode` is the caller, and `idx` is the program-counter index.
88
If possible, `framecode` will be looked up from the local method tables of `parentframe`.
99
"""
10-
function get_call_framecode(fargs, parentframe::FrameCode, idx::Int)
10+
function get_call_framecode(fargs, parentframe::FrameCode, idx::Int; enter_generated::Bool=false)
1111
nargs = length(fargs) # includes f as the first "argument"
1212
# Determine whether we can look up the appropriate framecode in the local method table
1313
if isassigned(parentframe.methodtables, idx) # if this is the first call, this may not yet be set
@@ -19,11 +19,15 @@ function get_call_framecode(fargs, parentframe::FrameCode, idx::Int)
1919
# Determine whether the argument types match the signature
2020
sig = tme.sig.parameters::SimpleVector
2121
if length(sig) == nargs
22-
matches = true
23-
for i = 1:nargs
24-
if !isa(fargs[i], sig[i])
25-
matches = false
26-
break
22+
# If this is generated, match only if `enter_generated` also matches
23+
mi = tme.func::FrameInstance
24+
matches = !is_generated(scopeof(mi.framecode)) || enter_generated == mi.enter_generated
25+
if matches
26+
for i = 1:nargs
27+
if !isa(fargs[i], sig[i])
28+
matches = false
29+
break
30+
end
2731
end
2832
end
2933
if matches
@@ -34,7 +38,6 @@ function get_call_framecode(fargs, parentframe::FrameCode, idx::Int)
3438
tmeprev.next = tme.next
3539
tme.next = tme1
3640
end
37-
mi = tme.func::FrameInstance
3841
return mi.framecode, mi.sparam_vals
3942
end
4043
end
@@ -47,12 +50,12 @@ function get_call_framecode(fargs, parentframe::FrameCode, idx::Int)
4750
end
4851
# We haven't yet encountered this argtype combination and need to look it up by dispatch
4952
fargs[1] = f = to_function(fargs[1])
50-
ret = prepare_call(f, fargs)
53+
ret = prepare_call(f, fargs; enter_generated=enter_generated)
5154
ret === nothing && return f(fargs[2:end]...), nothing
5255
isa(ret, Compiled) && return ret, nothing
5356
framecode, args, env, argtypes = ret
5457
# Store the results of the method lookup in the local method table
55-
mi = FrameInstance(framecode, env)
58+
mi = FrameInstance(framecode, env, is_generated(scopeof(framecode)) & enter_generated)
5659
# it's sort of odd to call this a TypeMapEntry, then set most of the fields incorrectly
5760
# but since we're just using it as a linked list, it's probably ok
5861
tme = ccall(:jl_new_struct_uninit, Any, (Any,), TypeMapEntry)::TypeMapEntry

src/types.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ Fields:
9090
struct FrameInstance
9191
framecode::FrameCode
9292
sparam_vals::SimpleVector
93+
enter_generated::Bool
9394
end
9495

9596
Base.show(io::IO, instance::FrameInstance) =
96-
print(io, "FrameInstance(", scopeof(instance.framecode), ", ", instance.sparam_vals, ')')
97+
print(io, "FrameInstance(", scopeof(instance.framecode), ", ", instance.sparam_vals, ", ", instance.enter_generated, ')')
9798

9899
"""
99100
`FrameData` holds the arguments, local variables, and intermediate execution state

0 commit comments

Comments
 (0)