Skip to content

Commit 87314a4

Browse files
KristofferCtimholy
authored andcommitted
step through invokes (#182)
1 parent 0ee85ae commit 87314a4

File tree

3 files changed

+71
-38
lines changed

3 files changed

+71
-38
lines changed

src/generate_builtins.jl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,22 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
138138
$head f === Core._apply
139139
argswrapped = getargs(args, frame)
140140
if !expand
141-
return Some{Any}(Core._apply(getargs(args, frame)...))
141+
return Some{Any}(Core._apply(argswrapped...))
142142
end
143143
argsflat = Base.append_any((argswrapped[1],), argswrapped[2:end]...)
144144
new_expr = Expr(:call, map(x->isa(x, Symbol) || isa(x, Expr) || isa(x, QuoteNode) ? QuoteNode(x) : x, argsflat)...)
145145
return new_expr
146+
""")
147+
continue
148+
elseif f === Core.invoke
149+
print(io,
150+
"""
151+
$head f === invoke
152+
argswrapped = getargs(args, frame)
153+
if !expand
154+
return Some{Any}(invoke(argswrapped...))
155+
end
156+
return Expr(:call, invoke, argswrapped...)
146157
""")
147158
continue
148159
end

src/interpret.jl

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,23 @@ function evaluate_call_recurse!(@nospecialize(recurse), frame::Frame, call_expr:
208208
err = length(fargs) > 1 ? fargs[2] : frame.framedata.last_exception[]
209209
throw(err)
210210
end
211-
framecode, lenv = get_call_framecode(fargs, frame.framecode, frame.pc; enter_generated=enter_generated)
212-
if lenv === nothing
213-
if isa(framecode, Compiled)
214-
popfirst!(fargs) # now it's really just `args`
215-
return f(fargs...)
211+
if fargs[1] === Core.invoke # invoke needs special handling
212+
f_invoked = which(fargs[2], fargs[3])
213+
sig = Tuple{_Typeof.(fargs)...}
214+
ret = prepare_framecode(f_invoked, sig; enter_generated=enter_generated)
215+
isa(ret, Compiled) && invoke(fargs[2:end]...)
216+
framecode, lenv = ret
217+
fargs = [fargs[2]; fargs[4:end]]
218+
lenv === nothing && return framecode # this was a Builtin
219+
else
220+
framecode, lenv = get_call_framecode(fargs, frame.framecode, frame.pc; enter_generated=enter_generated)
221+
if lenv === nothing
222+
if isa(framecode, Compiled)
223+
popfirst!(fargs) # now it's really just `args`
224+
return f(fargs...)
225+
end
226+
return framecode # this was a Builtin
216227
end
217-
return framecode # this was a Builtin
218228
end
219229
newframe = prepare_frame_caller(frame, framecode, fargs, lenv)
220230
npc = newframe.pc

test/debug.jl

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -295,39 +295,51 @@ struct B{T} end
295295
finally
296296
break_off(:error)
297297
end
298+
end
298299

299-
@testset "breakpoints" begin
300-
# In source breakpoints
301-
function f_bp(x)
302-
#=1=# i = 1
303-
#=2=# @label foo
304-
#=3=# @bp
305-
#=4=# repr("foo")
306-
#=5=# i += 1
307-
#=6=# i > 3 && return x
308-
#=7=# @goto foo
309-
end
310-
ln = @__LINE__
311-
method_start = ln - 9
312-
fr = enter_call(f_bp, 2)
313-
@test JuliaInterpreter.linenumber(fr) == method_start + 1
314-
fr, pc = JuliaInterpreter.debug_command(fr, :c)
315-
# Hit the breakpoint x1
316-
@test JuliaInterpreter.linenumber(fr) == method_start + 3
317-
@test pc isa BreakpointRef
318-
fr, pc = JuliaInterpreter.debug_command(fr, :n)
319-
@test JuliaInterpreter.linenumber(fr) == method_start + 4
320-
fr, pc = JuliaInterpreter.debug_command(fr, :c)
321-
# Hit the breakpoint again x2
322-
@test pc isa BreakpointRef
323-
@test JuliaInterpreter.linenumber(fr) == method_start + 3
324-
fr, pc = JuliaInterpreter.debug_command(fr, :c)
325-
# Hit the breakpoint for the last time x3
326-
@test pc isa BreakpointRef
327-
@test JuliaInterpreter.linenumber(fr) == method_start + 3
328-
JuliaInterpreter.debug_command(fr, :c)
329-
@test get_return(fr) == 2
300+
@testset "breakpoints" begin
301+
# In source breakpoints
302+
function f_bp(x)
303+
#=1=# i = 1
304+
#=2=# @label foo
305+
#=3=# @bp
306+
#=4=# repr("foo")
307+
#=5=# i += 1
308+
#=6=# i > 3 && return x
309+
#=7=# @goto foo
330310
end
311+
ln = @__LINE__
312+
method_start = ln - 9
313+
fr = enter_call(f_bp, 2)
314+
@test JuliaInterpreter.linenumber(fr) == method_start + 1
315+
fr, pc = JuliaInterpreter.debug_command(fr, :c)
316+
# Hit the breakpoint x1
317+
@test JuliaInterpreter.linenumber(fr) == method_start + 3
318+
@test pc isa BreakpointRef
319+
fr, pc = JuliaInterpreter.debug_command(fr, :n)
320+
@test JuliaInterpreter.linenumber(fr) == method_start + 4
321+
fr, pc = JuliaInterpreter.debug_command(fr, :c)
322+
# Hit the breakpoint again x2
323+
@test pc isa BreakpointRef
324+
@test JuliaInterpreter.linenumber(fr) == method_start + 3
325+
fr, pc = JuliaInterpreter.debug_command(fr, :c)
326+
# Hit the breakpoint for the last time x3
327+
@test pc isa BreakpointRef
328+
@test JuliaInterpreter.linenumber(fr) == method_start + 3
329+
JuliaInterpreter.debug_command(fr, :c)
330+
@test get_return(fr) == 2
331+
end
332+
333+
f_inv(x::Real) = x^2;
334+
f_inv(x::Integer) = 1 + invoke(f_inv, Tuple{Real}, x)
335+
@testset "invoke" begin
336+
fr = JuliaInterpreter.enter_call(f_inv, 2)
337+
fr, pc = JuliaInterpreter.debug_command(fr, :s) # apply_type
338+
frame, pc = JuliaInterpreter.debug_command(fr, :s) # step into invoke
339+
@test frame.framecode.scope.sig == Tuple{typeof(f_inv),Real}
340+
JuliaInterpreter.debug_command(frame, :c)
341+
frame = root(frame)
342+
@test get_return(frame) == f_inv(2)
331343
end
332344

333345
@testset "Issue #178" begin

0 commit comments

Comments
 (0)