diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 258eef48dc3302..2865c0ec09e5be 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4454,3 +4454,14 @@ def body body } + +# regression test for splatting empty array to cfunc +assert_normal_exit %q{ + def test_body(args) = Array(1, *args) + test_body([]) + 0x100.times do + array = Array.new(100) + array.clear + test_body(array) + end +} diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index ea00889c0c7c15..ca987eaf78ca1d 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -5814,20 +5814,20 @@ fn push_splat_args(required_args: u32, asm: &mut Assembler) { asm.cmp(array_len_opnd, required_args.into()); asm.jne(Target::side_exit(Counter::guard_send_splatarray_length_not_equal)); - asm_comment!(asm, "Check last argument is not ruby2keyword hash"); - - // Need to repeat this here to deal with register allocation - let array_reg = asm.load(asm.stack_opnd(0)); - - let ary_opnd = get_array_ptr(asm, array_reg); - - let last_array_value = asm.load(Opnd::mem(64, ary_opnd, (required_args as i32 - 1) * (SIZEOF_VALUE as i32))); + // Check last element of array if present + if required_args > 0 { + asm_comment!(asm, "Check last argument is not ruby2keyword hash"); - guard_object_is_not_ruby2_keyword_hash( - asm, - last_array_value, - Counter::guard_send_splatarray_last_ruby_2_keywords, - ); + // Need to repeat this here to deal with register allocation + let array_reg = asm.load(asm.stack_opnd(0)); + let ary_opnd = get_array_ptr(asm, array_reg); + let last_array_value = asm.load(Opnd::mem(64, ary_opnd, (required_args as i32 - 1) * (SIZEOF_VALUE as i32))); + guard_object_is_not_ruby2_keyword_hash( + asm, + last_array_value, + Counter::guard_send_splatarray_last_ruby_2_keywords, + ); + } asm_comment!(asm, "Push arguments from array"); let array_opnd = asm.stack_pop(1);