diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 8d669e502ccc61..70b6bde6ed611b 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -451,6 +451,17 @@ def one_plus_two assert_equal(3, one_plus_two) end + def test_tailcall_and_post_arg + tailcall(<<~RUBY) + def ret_const = :ok + + def post_arg(_a = 1, _b) = ret_const + RUBY + + # YJIT probably uses a fallback on the call to post_arg + assert_equal(:ok, post_arg(0)) + end + def test_tailcall_interrupted_by_sigint bug12576 = 'ruby-core:76327' script = "#{<<-"begin;"}\n#{<<~'end;'}" diff --git a/vm_exec.h b/vm_exec.h index 152410a6a738bf..b1eeb506607454 100644 --- a/vm_exec.h +++ b/vm_exec.h @@ -176,7 +176,8 @@ default: \ // Run the JIT from the interpreter #define JIT_EXEC(ec, val) do { \ rb_jit_func_t func; \ - if (val == Qundef && (func = jit_compile(ec))) { \ + /* don't run tailcalls since that breaks FINISH */ \ + if (val == Qundef && GET_CFP() != ec->cfp && (func = jit_compile(ec))) { \ val = func(ec, ec->cfp); \ RESTORE_REGS(); /* fix cfp for tailcall */ \ if (ec->tag->state) THROW_EXCEPTION(val); \