static inline const rb_block_t * check_block(rb_thread_t *th) { const rb_block_t *blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]); if (blockptr == 0) { rb_vm_localjump_error("no block given", Qnil, 0); } return blockptr; }
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; } }