summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-09-17 14:32:19 -0700
committerJeremy Evans <code@jeremyevans.net>2019-09-17 16:22:44 -0700
commit775365cbd2bf17195e694771fc1c15698273a640 (patch)
treeffed420e45f7a91d203acf2a22ac66650af4e214 /vm_insnhelper.c
parent9b35dc38644c10eed008f9ba19a7224f2fb49af2 (diff)
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.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2462
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c26
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;