зеркало из https://github.com/github/ruby.git
RJIT: Support splat args
This commit is contained in:
Родитель
6f2535deda
Коммит
cd1cd8030c
|
@ -4217,7 +4217,7 @@ module RubyVM::RJIT
|
|||
return CantCompile
|
||||
end
|
||||
|
||||
# block_arg = flags & C::VM_CALL_ARGS_BLOCKARG != 0
|
||||
block_arg = flags & C::VM_CALL_ARGS_BLOCKARG != 0
|
||||
# jit_caller_setup_arg_block already handled send_blockarg_not_nil_or_proxy
|
||||
|
||||
# If we have unfilled optional arguments and keyword arguments then we
|
||||
|
@ -4318,9 +4318,17 @@ module RubyVM::RJIT
|
|||
end
|
||||
end
|
||||
if flags & C::VM_CALL_ARGS_SPLAT != 0 && !iseq_has_rest
|
||||
splat_array_length = false
|
||||
asm.incr_counter(:send_iseq_splat)
|
||||
return CantCompile
|
||||
array = jit.peek_at_stack(block_arg ? 1 : 0)
|
||||
splat_array_length = if array.nil?
|
||||
0
|
||||
else
|
||||
array.length
|
||||
end
|
||||
|
||||
if opt_num == 0 && required_num != splat_array_length + argc - 1
|
||||
asm.incr_counter(:send_iseq_splat_arity_error)
|
||||
return CantCompile
|
||||
end
|
||||
end
|
||||
|
||||
# We will not have CantCompile from here.
|
||||
|
@ -4350,8 +4358,25 @@ module RubyVM::RJIT
|
|||
|
||||
# push_splat_args does stack manipulation so we can no longer side exit
|
||||
if splat_array_length
|
||||
asm.incr_counter(:send_iseq_splat)
|
||||
return CantCompile
|
||||
remaining_opt = (opt_num + required_num) - (splat_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.
|
||||
offset = opt_num - remaining_opt
|
||||
start_pc_offset = iseq.body.param.opt_table[offset]
|
||||
end
|
||||
# We are going to assume that the splat fills
|
||||
# all the remaining arguments. In the generated code
|
||||
# we test if this is true and if not side exit.
|
||||
argc = argc - 1 + splat_array_length + remaining_opt
|
||||
push_splat_args(splat_array_length, jit, ctx, asm)
|
||||
|
||||
remaining_opt.times do
|
||||
# We need to push nil for the optional arguments
|
||||
stack_ret = ctx.stack_push
|
||||
asm.mov(stack_ret, Qnil)
|
||||
end
|
||||
end
|
||||
|
||||
# This is a .send call and we need to adjust the stack
|
||||
|
@ -4730,7 +4755,7 @@ module RubyVM::RJIT
|
|||
# So the number of args should just equal the number of args the cfunc takes.
|
||||
# In the generated code we test if this is true and if not side exit.
|
||||
argc = cfunc.argc
|
||||
jit_caller_setup_arg_splat(jit, ctx, asm, required_args)
|
||||
push_splat_args(required_args, jit, ctx, asm)
|
||||
end
|
||||
|
||||
# We will not have side exits from here. Adjust the stack, which was skipped in jit_call_opt_send.
|
||||
|
@ -5344,7 +5369,7 @@ module RubyVM::RJIT
|
|||
# @param jit [RubyVM::RJIT::JITState]
|
||||
# @param ctx [RubyVM::RJIT::Context]
|
||||
# @param asm [RubyVM::RJIT::Assembler]
|
||||
def jit_caller_setup_arg_splat(jit, ctx, asm, required_args)
|
||||
def push_splat_args(required_args, jit, ctx, asm)
|
||||
side_exit = side_exit(jit, ctx)
|
||||
|
||||
asm.comment('push_splat_args')
|
||||
|
|
3
rjit_c.h
3
rjit_c.h
|
@ -64,7 +64,6 @@ RJIT_RUNTIME_COUNTERS(
|
|||
send_iseq_has_no_kw,
|
||||
send_iseq_zsuper,
|
||||
send_iseq_materialized_block,
|
||||
send_iseq_splat_with_kw,
|
||||
send_iseq_has_rest,
|
||||
send_iseq_block_arg0_splat,
|
||||
send_iseq_kw_call,
|
||||
|
@ -74,6 +73,8 @@ RJIT_RUNTIME_COUNTERS(
|
|||
send_iseq_missing_optional_kw,
|
||||
send_iseq_too_many_kwargs,
|
||||
send_iseq_kwargs_mismatch,
|
||||
send_iseq_splat_with_kw,
|
||||
send_iseq_splat_arity_error,
|
||||
|
||||
send_cfunc_variadic,
|
||||
send_cfunc_too_many_args,
|
||||
|
|
|
@ -1350,7 +1350,6 @@ module RubyVM::RJIT # :nodoc: all
|
|||
send_iseq_has_no_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_no_kw)")],
|
||||
send_iseq_zsuper: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_zsuper)")],
|
||||
send_iseq_materialized_block: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_materialized_block)")],
|
||||
send_iseq_splat_with_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_splat_with_kw)")],
|
||||
send_iseq_has_rest: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_rest)")],
|
||||
send_iseq_block_arg0_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_block_arg0_splat)")],
|
||||
send_iseq_kw_call: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kw_call)")],
|
||||
|
@ -1360,6 +1359,8 @@ module RubyVM::RJIT # :nodoc: all
|
|||
send_iseq_missing_optional_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_missing_optional_kw)")],
|
||||
send_iseq_too_many_kwargs: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_too_many_kwargs)")],
|
||||
send_iseq_kwargs_mismatch: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kwargs_mismatch)")],
|
||||
send_iseq_splat_with_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_splat_with_kw)")],
|
||||
send_iseq_splat_arity_error: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_splat_arity_error)")],
|
||||
send_cfunc_variadic: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_variadic)")],
|
||||
send_cfunc_too_many_args: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_too_many_args)")],
|
||||
send_cfunc_ruby_array_varg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_ruby_array_varg)")],
|
||||
|
|
Загрузка…
Ссылка в новой задаче