From: alanwucanada@... Date: 2018-12-08T06:33:22+00:00 Subject: [ruby-core:90377] [Ruby trunk Bug#15303] Return tracepoint doesn't fire when tailcall optimization is applied Issue #15303 has been updated by alanwu (Alan Wu). File no-tco-no-problem.patch added ko1 (Koichi Sasada) wrote: > Cancel tailcall opt when `return` event is specified. I think anyone who goes through all the trouble to enable tailcall elimination right now relies on it to avoid stack overflow. Why else would someone use it? It doesn't make your program faster, it's cumbersome to enable, and it erases part of your stack trace which makes debugging harder. Making this change seems to me replacing a problem with a different one. It is a problem that affects way less people admittedly, but I feel that it would be punishing functional programmers for the benefit of everyone else. If we just want to fix the problem most people have today, i.e., byebug's `next` command's breakage, making Forwardable not use TCO is good enough. It will still be broken for tailcall optimized code, but at least most people won't run into this problem. That might be the most pragmatic "fix", and it's a simple one. With it, we can keep ignoring this problem and wait till someone complains. ---------------------------------------- Bug #15303: Return tracepoint doesn't fire when tailcall optimization is applied https://bugs.ruby-lang.org/issues/15303#change-75487 * Author: alanwu (Alan Wu) * Status: Open * Priority: Normal * Assignee: * Target version: * ruby -v: ruby 2.6.0dev (2018-11-14 trunk 65727) [x86_64-darwin17] * Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN ---------------------------------------- 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 ~~~ ~~~ ruby 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-------------------------------- no-tco-no-problem.patch (520 Bytes) -- https://bugs.ruby-lang.org/ Unsubscribe: