diff options
author | Jeremy Evans <code@jeremyevans.net> | 2019-09-17 14:32:19 -0700 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2019-09-17 16:22:44 -0700 |
commit | 775365cbd2bf17195e694771fc1c15698273a640 (patch) | |
tree | ffed420e45f7a91d203acf2a22ac66650af4e214 /vm_insnhelper.c | |
parent | 9b35dc38644c10eed008f9ba19a7224f2fb49af2 (diff) | |
download | ruby-775365cbd2bf17195e694771fc1c15698273a640.tar.gz |
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.
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 26 |
1 files changed, 22 insertions, 4 deletions
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; |