summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Wu <[email protected]>2025-06-18 00:57:01 +0900
committerAlan Wu <[email protected]>2025-06-19 23:29:37 +0900
commit34eaa6418e5c5b8639add323dbfd531b32a7d4a3 (patch)
treedd32e72ba87fc45555032023182d0229efbf9181
parent82dfd44f937616ff31971f2d1e12a35bd022612c (diff)
ZJIT: Add `dupn` support
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/13641
-rw-r--r--test/ruby/test_zjit.rb10
-rw-r--r--zjit/src/hir.rs30
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)]