diff options
-rw-r--r-- | bootstraptest/test_yjit.rb | 6 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 13 |
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); |