diff options
author | Alan Wu <[email protected]> | 2025-06-18 00:57:01 +0900 |
---|---|---|
committer | Alan Wu <[email protected]> | 2025-06-19 23:29:37 +0900 |
commit | 34eaa6418e5c5b8639add323dbfd531b32a7d4a3 (patch) | |
tree | dd32e72ba87fc45555032023182d0229efbf9181 | |
parent | 82dfd44f937616ff31971f2d1e12a35bd022612c (diff) |
ZJIT: Add `dupn` support
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/13641
-rw-r--r-- | test/ruby/test_zjit.rb | 10 | ||||
-rw-r--r-- | zjit/src/hir.rs | 30 |
2 files changed, 40 insertions, 0 deletions
diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb index e10e9a8742..6e0f274c30 100644 --- a/test/ruby/test_zjit.rb +++ b/test/ruby/test_zjit.rb @@ -714,6 +714,16 @@ class TestZJIT < Test::Unit::TestCase end end + def test_dupn + assert_compiles '[[1], [1, 1], :rhs, [nil, :rhs]]', <<~RUBY, insns: [:dupn] + def test(array) = (array[1, 2] ||= :rhs) + + one = [1, 1] + start_empty = [] + [test(one), one, test(start_empty), start_empty] + RUBY + end + def test_send_backtrace backtrace = [ "-e:2:in 'Object#jit_frame1'", diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index fca8c237fd..2be6031805 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -2405,6 +2405,14 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { } YARVINSN_pop => { state.stack_pop()?; } YARVINSN_dup => { state.stack_push(state.stack_top()?); } + YARVINSN_dupn => { + // Duplicate the top N element of the stack. As we push, n-1 naturally + // points higher in the original stack. + let n = get_arg(pc, 0).as_usize(); + for _ in 0..n { + state.stack_push(state.stack_topn(n-1)?); + } + } YARVINSN_swap => { let right = state.stack_pop()?; let left = state.stack_pop()?; @@ -4314,6 +4322,28 @@ mod tests { Return v8 "#]]); } + + #[test] + fn dupn() { + eval(" + def test(x) = (x[0, 1] ||= 2) + "); + assert_method_hir_with_opcode("test", YARVINSN_dupn, expect![[r#" + fn test: + bb0(v0:BasicObject, v1:BasicObject): + v3:NilClassExact = Const Value(nil) + v4:Fixnum[0] = Const Value(0) + v5:Fixnum[1] = Const Value(1) + v7:BasicObject = SendWithoutBlock v1, :[], v4, v5 + v8:CBool = Test v7 + IfTrue v8, bb1(v0, v1, v3, v1, v4, v5, v7) + v10:Fixnum[2] = Const Value(2) + v12:BasicObject = SendWithoutBlock v1, :[]=, v4, v5, v10 + Return v10 + bb1(v14:BasicObject, v15:BasicObject, v16:NilClassExact, v17:BasicObject, v18:Fixnum[0], v19:Fixnum[1], v20:BasicObject): + Return v20 + "#]]); + } } #[cfg(test)] |