diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index d390a19cbc..6627a78628 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -1074,6 +1074,24 @@ class TestYJIT < Test::Unit::TestCase RUBY end + def test_invalidate_cyclic_branch + assert_compiles(<<~'RUBY', result: 2) + def foo + i = 0 + while i < 2 + i += 1 + end + i + end + + foo + class Integer + def +(x) = self - -x + end + foo + RUBY + end + private def code_gc_helpers diff --git a/yjit/src/core.rs b/yjit/src/core.rs index d10654f125..a8629f7e3e 100644 --- a/yjit/src/core.rs +++ b/yjit/src/core.rs @@ -439,7 +439,7 @@ pub type CmePtr = *const rb_callable_method_entry_t; /// Basic block version /// Represents a portion of an iseq compiled with a given context /// Note: care must be taken to minimize the size of block_t objects -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Block { // Bytecode sequence (iseq, idx) this is a version of blockid: BlockId, @@ -2318,6 +2318,8 @@ pub fn invalidate_block_version(blockref: &BlockRef) { } // For each incoming branch + mem::drop(block); // end borrow: regenerate_branch might mut borrow this + let block = blockref.borrow().clone(); for branchref in &block.incoming { let mut branch = branchref.borrow_mut(); let target_idx = if branch.get_target_address(0) == block_start {