diff options
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; |