Пример #1
0
static inline VALUE
invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
		    VALUE self, int argc, const VALUE *argv,
		    const rb_block_t *blockptr, const NODE *cref)
{
    if (SPECIAL_CONST_P(block->iseq))
	return Qnil;
    else if (BUILTIN_TYPE(block->iseq) != T_NODE) {
	const rb_iseq_t *iseq = block->iseq;
	const rb_control_frame_t *cfp;
	rb_control_frame_t *ncfp;
	int i, opt_pc, arg_size = iseq->arg_size;
	int type = block_proc_is_lambda(block->proc) ?
	  VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK;

	rb_vm_set_finish_env(th);

	cfp = th->cfp;
	CHECK_STACK_OVERFLOW(cfp, argc + iseq->stack_max);

	for (i=0; i<argc; i++) {
	    cfp->sp[i] = argv[i];
	}

	opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, blockptr,
				     type == VM_FRAME_MAGIC_LAMBDA);

	ncfp = vm_push_frame(th, iseq, type,
			     self, GC_GUARDED_PTR(block->dfp),
			     iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp,
			     iseq->local_size - arg_size);
	ncfp->me = th->passed_me;
	th->passed_me = 0;
	th->passed_block = blockptr;

	if (cref) {
	    th->cfp->dfp[-1] = (VALUE)cref;
	}

	return vm_exec(th);
    }
    else {
	return vm_yield_with_cfunc(th, block, self, argc, argv, blockptr);
    }
}
Пример #2
0
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;
    }
}