From 775365cbd2bf17195e694771fc1c15698273a640 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Tue, 17 Sep 2019 14:32:19 -0700 Subject: Fix keyword argument separation issues with sym procs when using refinements Make sure that vm_yield_with_cfunc can correctly set the empty keyword flag by passing 2 as the kw_splat value when calling it in vm_invoke_ifunc_block. Make sure calling.kw_splat is set to 1 and not 128 in vm_sendish, so we can safely check for different kw_splat values. vm_args.c needs to call add_empty_keyword, and to make JIT happy, the function needs to be exported. Rename the function to rb_adjust_argv_kw_splat to more accurately reflect what it does, and mark it as MJIT exported. --- vm_insnhelper.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'vm_insnhelper.c') diff --git a/vm_insnhelper.c b/vm_insnhelper.c index a83e3a952a..1dd88781db 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2888,6 +2888,7 @@ vm_yield_with_cfunc(rb_execution_context_t *ec, { int is_lambda = FALSE; /* TODO */ VALUE val, arg, blockarg; + int frame_flag; const struct vm_ifunc *ifunc = captured->code.ifunc; if (is_lambda) { @@ -2902,9 +2903,18 @@ vm_yield_with_cfunc(rb_execution_context_t *ec, blockarg = rb_vm_bh_to_procval(ec, block_handler); + frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0); + switch(kw_splat) { + case 1: + frame_flag |= VM_FRAME_FLAG_CFRAME_KW; + break; + case 2: + frame_flag |= VM_FRAME_FLAG_CFRAME_EMPTY_KW; + break; + } + vm_push_frame(ec, (const rb_iseq_t *)captured->code.ifunc, - VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | - (me ? VM_FRAME_FLAG_BMETHOD : 0) | (kw_splat ? VM_FRAME_FLAG_CFRAME_KW : 0), + frame_flag, self, VM_GUARDED_PREV_EP(captured->ep), (VALUE)me, @@ -3060,9 +3070,17 @@ vm_invoke_ifunc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, { VALUE val; int argc; + int frame_flag = 0; + int kw_splat = calling->kw_splat; CALLER_SETUP_ARG(ec->cfp, calling, ci); + if (kw_splat && !calling->kw_splat) { + kw_splat = 2; + } + else { + kw_splat = calling->kw_splat; + } argc = calling->argc; - val = vm_yield_with_cfunc(ec, captured, captured->self, argc, STACK_ADDR_FROM_TOP(argc), calling->kw_splat, calling->block_handler, NULL); + val = vm_yield_with_cfunc(ec, captured, captured->self, argc, STACK_ADDR_FROM_TOP(argc), kw_splat, calling->block_handler, NULL); POPN(argc); /* TODO: should put before C/yield? */ return val; } @@ -3695,7 +3713,7 @@ vm_sendish( struct rb_calling_info calling; calling.block_handler = block_handler; - calling.kw_splat = IS_ARGS_KW_SPLAT(ci); + calling.kw_splat = IS_ARGS_KW_SPLAT(ci) > 0; calling.recv = recv; calling.argc = argc; -- cgit v1.2.3