void rb_vm_stack_to_heap(rb_thread_t * const th) { rb_control_frame_t *cfp = th->cfp; while ((cfp = rb_vm_get_ruby_level_next_cfp(th, cfp)) != 0) { rb_vm_make_env_object(th, cfp); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } }
VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass) { VALUE procval, envval, blockprocval = 0; rb_proc_t *proc; rb_control_frame_t *cfp = RUBY_VM_GET_CFP_FROM_BLOCK_PTR(block); if (block->proc) { rb_bug("rb_vm_make_proc: Proc value is already created."); } if (GC_GUARDED_PTR_REF(cfp->lfp[0])) { rb_proc_t *p; blockprocval = vm_make_proc_from_block( th, (rb_block_t *)GC_GUARDED_PTR_REF(*cfp->lfp)); GetProcPtr(blockprocval, p); *cfp->lfp = GC_GUARDED_PTR(&p->block); } envval = rb_vm_make_env_object(th, cfp); if (PROCDEBUG) { check_env_value(envval); } procval = rb_proc_alloc(klass); GetProcPtr(procval, proc); proc->blockprocval = blockprocval; proc->block.self = block->self; proc->block.lfp = block->lfp; proc->block.dfp = block->dfp; proc->block.iseq = block->iseq; proc->block.proc = procval; proc->envval = envval; proc->safe_level = th->safe_level; if (VMDEBUG) { if (th->stack < block->dfp && block->dfp < th->stack + th->stack_size) { rb_bug("invalid ptr: block->dfp"); } if (th->stack < block->lfp && block->lfp < th->stack + th->stack_size) { rb_bug("invalid ptr: block->lfp"); } } return procval; }
VALUE rb_binding_new(void) { rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); VALUE bindval = binding_alloc(rb_cBinding); rb_binding_t *bind; if (cfp == 0) { rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber."); } GetBindingPtr(bindval, bind); bind->env = rb_vm_make_env_object(th, cfp); return bindval; }
static void vm_set_main_stack(rb_thread_t *th, VALUE iseqval) { VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")); rb_binding_t *bind; rb_iseq_t *iseq; rb_env_t *env; GetBindingPtr(toplevel_binding, bind); GetEnvPtr(bind->env, env); th->base_block = &env->block; vm_set_eval_stack(th, iseqval, 0); th->base_block = 0; /* save binding */ GetISeqPtr(iseqval, iseq); if (bind && iseq->local_size > 0) { bind->env = rb_vm_make_env_object(th, th->cfp); } CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max); }
static VALUE binding_of_caller(VALUE self, VALUE rb_level) { rb_thread_t *th; GetThreadPtr(rb_thread_current(), th); rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size); int level = FIX2INT(rb_level); // attempt to locate the nth parent control frame for (int i = 0; i < level; i++) { cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); if (cfp >= limit_cfp) rb_raise(rb_eRuntimeError, "Invalid frame, gone beyond end of stack!"); // skip invalid frames if (!valid_frame_p(cfp, limit_cfp)) cfp = find_valid_frame(cfp, limit_cfp); } VALUE bindval = binding_alloc(rb_cBinding); rb_binding_t *bind; if (cfp == 0) rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber."); GetBindingPtr(bindval, bind); bind->env = rb_vm_make_env_object(th, cfp); bind->filename = cfp->iseq->filename; bind->line_no = rb_vm_get_sourceline(cfp); rb_iv_set(bindval, "@frame_type", frametype_name(cfp->flag)); rb_iv_set(bindval, "@frame_description", cfp->iseq->name); return bindval; }
/*RHO static*/ VALUE eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *file, int line) { int state; VALUE result = Qundef; VALUE envval; rb_binding_t *bind = 0; rb_thread_t *th = GET_THREAD(); rb_env_t *env = NULL; rb_block_t block; volatile int parse_in_eval; volatile int mild_compile_error; if (file == 0) { file = rb_sourcefile(); line = rb_sourceline(); } parse_in_eval = th->parse_in_eval; mild_compile_error = th->mild_compile_error; PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { rb_iseq_t *iseq; volatile VALUE iseqval; if (scope != Qnil) { if (rb_obj_is_kind_of(scope, rb_cBinding)) { GetBindingPtr(scope, bind); envval = bind->env; } else { rb_raise(rb_eTypeError, "wrong argument type %s (expected Binding)", rb_obj_classname(scope)); } GetEnvPtr(envval, env); th->base_block = &env->block; } else { rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp != 0) { block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp); th->base_block = █ th->base_block->self = self; th->base_block->iseq = cfp->iseq; /* TODO */ } else { rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread"); } } //RHO if ( TYPE(src) != T_STRING ){ iseqval = src; }else //RHO { /* make eval iseq */ th->parse_in_eval++; th->mild_compile_error++; iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line)); th->mild_compile_error--; th->parse_in_eval--; } vm_set_eval_stack(th, iseqval, cref); th->base_block = 0; if (0) { /* for debug */ printf("%s\n", RSTRING_PTR(rb_iseq_disasm(iseqval))); } /* save new env */ GetISeqPtr(iseqval, iseq); if (bind && iseq->local_size > 0) { bind->env = rb_vm_make_env_object(th, th->cfp); } /* kick */ CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max); result = vm_exec(th); } POP_TAG(); th->mild_compile_error = mild_compile_error; th->parse_in_eval = parse_in_eval; if (state) { if (state == TAG_RAISE) { VALUE errinfo = th->errinfo; if (strcmp(file, "(eval)") == 0) { VALUE mesg, errat, bt2; extern VALUE rb_get_backtrace(VALUE info); ID id_mesg; CONST_ID(id_mesg, "mesg"); errat = rb_get_backtrace(errinfo); mesg = rb_attr_get(errinfo, id_mesg); if (!NIL_P(errat) && TYPE(errat) == T_ARRAY && (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) { if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) { if (OBJ_FROZEN(mesg)) { VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2); rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg)); } else { rb_str_update(mesg, 0, 0, rb_str_new2(": ")); rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]); } } RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0]; } } rb_exc_raise(errinfo); } JUMP_TAG(state); } return result; }