Bug #15303
closedReturn tracepoint doesn't fire when tailcall optimization is applied
Description
After a tailcall, the "return" tracepoint event is only fired once. Normally, after a call at the end of a method, the return event is fired twice, once for the callee returning and once for the caller returning.
The following script outputs
:call
:call
:call
:return
method_source = <<-RB
def toy(n)
return if n == 2
toy(n+1)
end
RB
iseq = RubyVM::InstructionSequence.compile(method_source, tailcall_optimization: true)
#puts iseq.disasm
iseq.eval
trace = TracePoint.new(:call, :return) do |tp|
p tp.event
end
trace.enable
toy(0)
The "return" event behaves more like a "stack frame pop" event currently. I don't think it's feasible/desirable to have the same behavior when TCO is applied, but it would be nice if there was some way for the tracepoint to know a tail call is going to happen.
I'm raising this issue because the popular debugger "byebug" relies on these events to track execution in various stack frames. https://github.com/deivid-rodriguez/byebug/issues/481
Forwardable explicitly uses TCO which triggers this issue.
Files