static inline void vm_method_missing_args(rb_thread_t *th, VALUE *argv, int num, const rb_block_t *blockptr, int opt) { rb_control_frame_t * const reg_cfp = th->cfp; MEMCPY(argv, STACK_ADDR_FROM_TOP(num + 1), VALUE, num + 1); th->method_missing_reason = opt; th->passed_block = blockptr; POPN(num + 1); }
static inline VALUE vm_method_missing(rb_thread_t *th, ID id, VALUE recv, int num, rb_block_t *blockptr, int opt) { VALUE val; rb_control_frame_t * const reg_cfp = th->cfp; VALUE *argv = ALLOCA_N(VALUE, num + 1); MEMCPY(argv, STACK_ADDR_FROM_TOP(num + 1), VALUE, num + 1); argv[0] = ID2SYM(id); th->method_missing_reason = opt; th->passed_block = blockptr; POPN(num + 1); val = rb_funcall2(recv, idMethodMissing, num + 1, argv); return val; }
static VALUE vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_num_t flag) { const rb_block_t *block = GET_BLOCK_PTR(); rb_iseq_t *iseq; int argc = (int)num; VALUE type = GET_ISEQ()->local_iseq->type; if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) { rb_vm_localjump_error("no block given (yield)", Qnil, 0); } iseq = block->iseq; argc = caller_setup_args(th, GET_CFP(), flag, argc, 0, 0); if (BUILTIN_TYPE(iseq) != T_NODE) { int opt_pc; const int arg_size = iseq->arg_size; VALUE * const rsp = GET_SP() - argc; SET_SP(rsp); CHECK_STACK_OVERFLOW(GET_CFP(), iseq->stack_max); opt_pc = vm_yield_setup_args(th, iseq, argc, rsp, 0, block_proc_is_lambda(block->proc)); vm_push_frame(th, iseq, VM_FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp, iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp, iseq->local_size - arg_size); return Qundef; } else { VALUE val = vm_yield_with_cfunc(th, block, block->self, argc, STACK_ADDR_FROM_TOP(argc), 0); POPN(argc); /* TODO: should put before C/yield? */ return val; } }