summaryrefslogtreecommitdiff
path: root/zjit
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2026-03-27 13:23:03 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2026-03-27 15:33:51 -0700
commit16e96105a75d455e9f6666ff63bf854e6ccb619d (patch)
tree57ba2a8465f4a62f9bf3f45eac39427297c99e01 /zjit
parent6519a7749631538a74b63e182be9a171c1afdc84 (diff)
ZJIT: Add tests for invokeblock IFUNC specialization
Test Enumerable#map on a class with a Ruby `each` that uses `yield`. This exercises the IFUNC block handler path in invokeblock, where Enumerable C code creates an IFUNC wrapping the user's block.
Diffstat (limited to 'zjit')
-rw-r--r--zjit/src/codegen_tests.rs17
-rw-r--r--zjit/src/hir/opt_tests.rs40
2 files changed, 57 insertions, 0 deletions
diff --git a/zjit/src/codegen_tests.rs b/zjit/src/codegen_tests.rs
index 3a21b001cd..db94a32036 100644
--- a/zjit/src/codegen_tests.rs
+++ b/zjit/src/codegen_tests.rs
@@ -4701,6 +4701,23 @@ fn test_invokeblock_multiple_yields() {
}
#[test]
+fn test_invokeblock_ifunc_map() {
+ eval("
+ class MyList
+ include Enumerable
+ def each
+ yield 1
+ yield 2
+ yield 3
+ end
+ end
+ def test = MyList.new.map { |x| x * 2 }
+ test
+ ");
+ assert_snapshot!(assert_compiles("test"), @"[2, 4, 6]");
+}
+
+#[test]
fn test_ccall_variadic_with_multiple_args() {
eval("
def test
diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs
index 40d126d56f..315467ca72 100644
--- a/zjit/src/hir/opt_tests.rs
+++ b/zjit/src/hir/opt_tests.rs
@@ -15075,4 +15075,44 @@ mod hir_opt_tests {
Return v36
");
}
+
+ #[test]
+ fn test_invokeblock_ifunc() {
+ eval("
+ class IFuncTestList
+ include Enumerable
+ def each
+ yield 1
+ yield 2
+ end
+ end
+ IFuncTestList.new.map { |x| x }
+ ");
+ assert_snapshot!(hir_string_proc("IFuncTestList.instance_method(:each)"), @"
+ fn each@<compiled>:5:
+ bb1():
+ EntryPoint interpreter
+ v1:BasicObject = LoadSelf
+ Jump bb3(v1)
+ bb2():
+ EntryPoint JIT(0)
+ v4:BasicObject = LoadArg :self@0
+ Jump bb3(v4)
+ bb3(v6:BasicObject):
+ v10:Fixnum[1] = Const Value(1)
+ v12:CPtr = GetEP 0
+ v13:CInt64 = LoadField v12, :_env_data_index_specval@0x1000
+ v14:CInt64 = GuardAnyBitSet v13, CUInt64(1)
+ v15:CInt64 = GuardAnyBitSet v13, CUInt64(2)
+ v16:BasicObject = InvokeBlockIfunc v13, v10
+ v20:Fixnum[2] = Const Value(2)
+ v22:CPtr = GetEP 0
+ v23:CInt64 = LoadField v22, :_env_data_index_specval@0x1000
+ v24:CInt64 = GuardAnyBitSet v23, CUInt64(1)
+ v25:CInt64 = GuardAnyBitSet v23, CUInt64(2)
+ v26:BasicObject = InvokeBlockIfunc v23, v20
+ CheckInterrupts
+ Return v26
+ ");
+ }
}