summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstraptest/test_yjit.rb6
-rw-r--r--yjit/src/codegen.rs13
2 files changed, 18 insertions, 1 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 2225423aa1..14be1093e2 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -4586,3 +4586,9 @@ assert_equal 'ok', %q{
splat_nil_kw_splat([:ok])
}
+
+# empty splat and kwsplat into leaf builtins
+assert_equal '[1, 1, 1]', %q{
+ empty = []
+ [1.abs(*empty), 1.abs(**nil), 1.bit_length(*empty, **nil)]
+}
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 0243927f55..e686a61de5 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -6734,7 +6734,8 @@ fn gen_send_iseq(
let builtin_func_raw = unsafe { rb_yjit_builtin_function(iseq) };
let builtin_func = if builtin_func_raw.is_null() { None } else { Some(builtin_func_raw) };
let opt_send_call = flags & VM_CALL_OPT_SEND != 0; // .send call is not currently supported for builtins
- if let (None, Some(builtin_info), true, false) = (block, builtin_func, builtin_attrs & BUILTIN_ATTR_LEAF != 0, opt_send_call) {
+ if let (None, Some(builtin_info), true, false, None | Some(0)) =
+ (block, builtin_func, builtin_attrs & BUILTIN_ATTR_LEAF != 0, opt_send_call, splat_array_length) {
let builtin_argc = unsafe { (*builtin_info).argc };
if builtin_argc + 1 < (C_ARG_OPNDS.len() as i32) {
// We pop the block arg without using it because:
@@ -6749,6 +6750,16 @@ fn gen_send_iseq(
asm.stack_pop(1);
}
+ // Pop empty kw_splat hash which passes nothing (exit_if_kwsplat_non_nil())
+ if kw_splat {
+ asm.stack_pop(1);
+ }
+
+ // Pop empty splat array which passes nothing
+ if let Some(0) = splat_array_length {
+ asm.stack_pop(1);
+ }
+
asm_comment!(asm, "inlined leaf builtin");
gen_counter_incr(asm, Counter::num_send_iseq_leaf);