YJIT: End the block after OPTIMIZE_METHOD_TYPE_CALL (#13245)
authorTakashi Kokubun <[email protected]>
Mon, 5 May 2025 20:35:28 +0000 (5 13:35 -0700)
committerGitHub <[email protected]>
Mon, 5 May 2025 20:35:28 +0000 (5 13:35 -0700)
test/-ext-/debug/test_debug.rb
yjit/src/codegen.rs

index 98e178e..2229859 100644 (file)
@@ -75,4 +75,19 @@ class TestDebug < Test::Unit::TestCase
     end
     assert_equal true, x, '[Bug #15105]'
   end
+
+  # This is a YJIT test, but we can't test this without a C extension that calls
+  # rb_debug_inspector_open(), so we're testing it using "-test-/debug" here.
+  def test_yjit_invalidates_setlocal_after_inspector_call
+    val = setlocal_after_proc_call(proc { Bug::Debug.inspector; :ok })
+    assert_equal :ok, val
+  end if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
+
+  private
+
+  def setlocal_after_proc_call(block)
+    local = block.call # setlocal followed by OPTIMIZED_METHOD_TYPE_CALL
+    itself # split a block using a C call
+    local # getlocal
+  end
 end
index 0d74f2a..c58917a 100644 (file)
@@ -9375,7 +9375,6 @@ fn gen_send_general(
 
                     }
                     OPTIMIZED_METHOD_TYPE_CALL => {
-
                         if block.is_some() {
                             gen_counter_incr(jit, asm, Counter::send_call_block);
                             return None;
@@ -9427,8 +9426,9 @@ fn gen_send_general(
 
                         let stack_ret = asm.stack_push(Type::Unknown);
                         asm.mov(stack_ret, ret);
-                        return Some(KeepCompiling);
 
+                        // End the block to allow invalidating the next instruction
+                        return jump_to_next_insn(jit, asm);
                     }
                     OPTIMIZED_METHOD_TYPE_BLOCK_CALL => {
                         gen_counter_incr(jit, asm, Counter::send_optimized_method_block_call);