summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maximechevalierb@gmail.com>2021-04-27 16:27:56 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:34 -0400
commitbce6dea72d0081e4777b80e1de3b76fbfcde9f0a (patch)
treefb94aa93056e0795fca1a284a8b82d0628325d58
parentcfaf6013036bf1294d4dead83155daeb5a95308e (diff)
Fix assertions in `invalidate_block_version()`, add small repro (#14)
* Fix block invalidation assertions * Add Alan's small repro for double invalidation bug
-rw-r--r--bootstraptest/test_yjit.rb22
-rw-r--r--yjit_core.c9
2 files changed, 27 insertions, 4 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 5c7e74635a..d02506b2b8 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -172,6 +172,28 @@ assert_equal '1', %q{
retval
}
+# Code invalidation and opt_getinlinecache
+assert_normal_exit %q{
+ class Foo; end
+
+ # Uses the class constant Foo
+ def use_constant(arg)
+ [Foo.new, arg]
+ end
+
+ def propagate_type
+ i = Array.new
+ i.itself # make it remember that i is on-heap
+ use_constant(i)
+ end
+
+ propagate_type
+ propagate_type
+ use_constant(Foo.new)
+ class Jo; end # bump global constant state
+ use_constant(3)
+}
+
# Method redefinition (code invalidation) and GC
assert_equal '7', %q{
def bar()
diff --git a/yjit_core.c b/yjit_core.c
index 140d0dc64a..eae43c38f7 100644
--- a/yjit_core.c
+++ b/yjit_core.c
@@ -888,7 +888,11 @@ invalidate_block_version(block_t* block)
{
branch_t* branch = rb_darray_get(block->incoming, incoming_idx);
uint32_t target_idx = (branch->dst_addrs[0] == code_ptr)? 0:1;
- RUBY_ASSERT(!branch->blocks[target_idx] || branch->blocks[target_idx] == block);
+ RUBY_ASSERT(branch->dst_addrs[target_idx] == code_ptr);
+ RUBY_ASSERT(branch->blocks[target_idx] == block);
+
+ // Mark this target as being a stub
+ branch->blocks[target_idx] = NULL;
// Create a stub for this branch target
branch->dst_addrs[target_idx] = get_branch_target(
@@ -898,9 +902,6 @@ invalidate_block_version(block_t* block)
target_idx
);
- // Mark this target as being a stub
- branch->blocks[target_idx] = NULL;
-
// Check if the invalidated block immediately follows
bool target_next = block->start_pos == branch->end_pos;