summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Wu <[email protected]>2025-06-26 22:11:35 +0900
committerAlan Wu <[email protected]>2025-06-27 20:42:38 +0900
commit8e75a36129ed8168326ec7cc67ae019637fccfa5 (patch)
tree4d4bb81d71c7ba6a88efddae3537e3771ff25b49
parentb125fb56c98509bb1c0d2eba901a0238f2e3a5f3 (diff)
ZJIT: Add TODOs and omitted test for nested scope local access
-rw-r--r--test/ruby/test_zjit.rb22
-rw-r--r--zjit/src/hir.rs22
2 files changed, 36 insertions, 8 deletions
diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb
index be8b910fd6..5cb6d1f03e 100644
--- a/test/ruby/test_zjit.rb
+++ b/test/ruby/test_zjit.rb
@@ -81,6 +81,28 @@ class TestZJIT < Test::Unit::TestCase
}, call_threshold: 3, insns: [:getlocal, :setlocal, :getlocal_WC_0, :setlocal_WC_1]
end
+ def test_read_local_written_by_children_iseqs
+ omit "This test fails right now because Send doesn't compile."
+
+ assert_compiles '[1, 2]', %q{
+ def test
+ l1 = nil
+ l2 = nil
+ tap do |_|
+ l1 = 1
+ tap do |_|
+ l2 = 2
+ end
+ end
+
+ [l1, l2]
+ end
+
+ test
+ test
+ }, call_threshold: 2
+ end
+
def test_send_without_block
assert_compiles '[1, 2, 3]', %q{
def foo = 1
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs
index e965d42380..ad32d06f3e 100644
--- a/zjit/src/hir.rs
+++ b/zjit/src/hir.rs
@@ -2543,11 +2543,17 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
break; // Don't enqueue the next block as a successor
}
YARVINSN_getlocal_WC_0 => {
+ // TODO(alan): This implementation doesn't read from EP, so will miss writes
+ // from nested ISeqs. This will need to be amended when we add codegen for
+ // Send.
let ep_offset = get_arg(pc, 0).as_u32();
let val = state.getlocal(ep_offset);
state.stack_push(val);
}
YARVINSN_setlocal_WC_0 => {
+ // TODO(alan): This implementation doesn't write to EP, where nested scopes
+ // read, so they'll miss these writes. This will need to be amended when we
+ // add codegen for Send.
let ep_offset = get_arg(pc, 0).as_u32();
let val = state.stack_pop()?;
state.setlocal(ep_offset, val);
@@ -3527,16 +3533,16 @@ mod tests {
expect![[r#"
fn block (3 levels) in <compiled>:
bb0(v0:BasicObject):
- v2:BasicObject = GetLocal l2, 4
- SetLocal l1, 3, v2
- v4:BasicObject = GetLocal l1, 3
- v5:BasicObject = GetLocal l2, 4
+ v2:BasicObject = GetLocal l2, EP@4
+ SetLocal l1, EP@3, v2
+ v4:BasicObject = GetLocal l1, EP@3
+ v5:BasicObject = GetLocal l2, EP@4
v7:BasicObject = SendWithoutBlock v4, :+, v5
- SetLocal l2, 4, v7
- v9:BasicObject = GetLocal l2, 4
- v10:BasicObject = GetLocal l3, 5
+ SetLocal l2, EP@4, v7
+ v9:BasicObject = GetLocal l2, EP@4
+ v10:BasicObject = GetLocal l3, EP@5
v12:BasicObject = SendWithoutBlock v9, :+, v10
- SetLocal l3, 5, v12
+ SetLocal l3, EP@5, v12
Return v12
"#]]
);