ZJIT: Fix kwargs handling in invokeblock ifunc specialization (#17971)

gen_invokeblock_ifunc drops the callinfo and passes argv straight to
rb_vm_yield_with_cfunc, which hardcodes kw_splat = 0, so keyword
arguments lost their keyword-ness. Gate the ifunc specialization on
block_call_inlinable, the same check used for the inline ISEQ path.
This commit is contained in:
Daichi Kamiyama 2026-07-29 09:57:20 +09:00 committed by GitHub
parent 2999c81ce2
commit d13a49fc50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2026-07-29 00:57:51 +00:00
Merged-By: k0kubun <takashikkbn@gmail.com>
3 changed files with 41 additions and 1 deletions

View File

@ -6012,6 +6012,18 @@ fn test_invokeblock_ifunc_map() {
assert_snapshot!(assert_compiles("test"), @"[2, 4, 6]");
}
#[test]
fn test_invokeblock_ifunc_kwarg() {
eval("
def foo
yield 1, a: 2
end
def test = enum_for(:foo).to_a
test
");
assert_snapshot!(assert_compiles("test"), @"[[1, {a: 2}]]");
}
#[test]
fn test_ccall_variadic_with_multiple_args() {
eval("

View File

@ -9326,7 +9326,7 @@ fn add_iseq_to_hir(
Some(summary.bucket(0).class())
});
let is_ifunc = (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT)) == 0
let is_ifunc = (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG)) == 0
&& block_handler_class.is_some_and(|obj| unsafe { rb_IMEMO_TYPE_P(obj, imemo_ifunc) == 1 });
// If the block handler is a known simple ISEQ block with exact arity and no

View File

@ -17913,6 +17913,34 @@ mod hir_opt_tests {
");
}
#[test]
fn test_invokeblock_ifunc_kwarg() {
eval("
def foo
yield 1, a: 2
end
def test = enum_for(:foo).to_a
test
");
assert_snapshot!(hir_string("foo"), @"
fn foo@<compiled>:3:
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:Fixnum[2] = Const Value(2)
v14:BasicObject = InvokeBlock v10, v12 # SendFallbackReason: InvokeBlock: not yet specialized
CheckInterrupts
Return v14
");
}
#[test]
fn test_dedup_guard_type() {
// Two subtractions on the same Fixnum operand `n` each require a