diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index 5fb2a5fa7a..395c0ba227 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -4078,15 +4078,19 @@ module RubyVM::RJIT def jit_call_iseq_setup_normal(jit, ctx, asm, cme, flags, argc, iseq, block_handler, opt_pc, send_shift:, frame_type:, prev_ep: nil) # Push splat args, which was skipped in jit_caller_setup_arg. if flags & C::VM_CALL_ARGS_SPLAT != 0 - if iseq.body.param.opt_num != 0 - asm.incr_counter(:send_args_splat_opt_num) # not supported yet + lead_num = iseq.body.param.lead_num + opt_num = iseq.body.param.opt_num + + array_length = jit.peek_at_stack(flags & C::VM_CALL_ARGS_BLOCKARG != 0 ? 1 : 0)&.length || 0 # blockarg is not popped yet + if opt_num == 0 && lead_num != array_length + argc - 1 + asm.incr_counter(:send_args_splat_arity_error) return CantCompile end - array_length = jit.peek_at_stack(flags & C::VM_CALL_ARGS_BLOCKARG != 0 ? 1 : 0)&.length || 0 # blockarg is not popped yet - if iseq.body.param.lead_num != array_length + argc - 1 - asm.incr_counter(:send_args_splat_arity_error) - return CantCompile + remaining_opt = (opt_num + lead_num) - (array_length + argc - 1) + if opt_num > 0 + # We are going to jump to the correct offset based on how many optional params are remaining. + opt_pc = iseq.body.param.opt_table[opt_num - remaining_opt] end # We are going to assume that the splat fills all the remaining arguments. @@ -4694,7 +4698,7 @@ module RubyVM::RJIT return 0 elsif C.rb_iseq_only_optparam_p(iseq) - if jit_caller_setup_arg(jit, ctx, asm, flags) == CantCompile + if jit_caller_setup_arg(jit, ctx, asm, flags, splat: true) == CantCompile return CantCompile end if jit_caller_remove_empty_kw_splat(jit, ctx, asm, flags) == CantCompile @@ -4728,7 +4732,7 @@ module RubyVM::RJIT # @param asm [RubyVM::RJIT::Assembler] def jit_callee_setup_block_arg(jit, ctx, asm, calling, iseq, arg_setup_type:) if C.rb_simple_iseq_p(iseq) - if jit_caller_setup_arg(jit, ctx, asm, calling.flags) == CantCompile + if jit_caller_setup_arg(jit, ctx, asm, calling.flags, splat: true) == CantCompile return CantCompile end diff --git a/rjit_c.h b/rjit_c.h index eaa455d4da..5ab902ba55 100644 --- a/rjit_c.h +++ b/rjit_c.h @@ -24,7 +24,6 @@ RJIT_RUNTIME_COUNTERS( send_args_splat, send_args_splat_not_array, send_args_splat_length_not_equal, - send_args_splat_opt_num, send_args_splat_arity_error, send_args_splat_ruby2_hash, send_kw_splat, diff --git a/rjit_c.rb b/rjit_c.rb index 65a4b3e899..d89453b934 100644 --- a/rjit_c.rb +++ b/rjit_c.rb @@ -1278,7 +1278,6 @@ module RubyVM::RJIT # :nodoc: all send_args_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat)")], send_args_splat_not_array: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_not_array)")], send_args_splat_length_not_equal: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_length_not_equal)")], - send_args_splat_opt_num: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_opt_num)")], send_args_splat_arity_error: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_arity_error)")], send_args_splat_ruby2_hash: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_ruby2_hash)")], send_kw_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_kw_splat)")],