rb_control_frame_t* RPRuby_internal_framePriorTo( rb_control_frame_t* c_control_frame ) { rb_thread_t* c_thread = (rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current()); rb_control_frame_t* c_prior_control_frame = NULL; // get the current frame pointer if ( c_control_frame == NULL ) { c_control_frame = c_thread->cfp; } if ( ( c_prior_control_frame = rb_vm_get_ruby_level_next_cfp( c_thread, c_control_frame ) ) != 0) { // not sure why we have to call this a second time after it was called at the end of rb_vm_get_ruby_level_next_cfp, // but for some reason it seems to be necessary c_prior_control_frame = RUBY_VM_PREVIOUS_CONTROL_FRAME( c_prior_control_frame ); } else { c_prior_control_frame = NULL; } // if we have a nil object we've passed main, we're done if ( c_prior_control_frame->self == Qnil ) { return NULL; } return c_prior_control_frame; }
NODE * rb_vm_cref(void) { rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp); }
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); } }
int rb_sourceline(void) { rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp) { return rb_vm_get_sourceline(cfp); } else { return 0; } }
const char * rb_sourcefile(void) { rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp) { return RSTRING_PTR(cfp->iseq->filename); } else { return 0; } }
rb_method_entry_t * rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex) { rb_thread_t *th; rb_control_frame_t *cfp; int line; rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex); rb_method_definition_t *def = ALLOC(rb_method_definition_t); me->def = def; def->type = type; def->original_id = mid; def->alias_count = 0; switch (type) { case VM_METHOD_TYPE_ISEQ: def->body.iseq = (rb_iseq_t *)opts; break; case VM_METHOD_TYPE_CFUNC: def->body.cfunc = *(rb_method_cfunc_t *)opts; break; case VM_METHOD_TYPE_ATTRSET: case VM_METHOD_TYPE_IVAR: def->body.attr.id = (ID)opts; def->body.attr.location = Qfalse; th = GET_THREAD(); cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp && (line = rb_vm_get_sourceline(cfp))) { VALUE location = rb_ary_new3(2, cfp->iseq->filename, INT2FIX(line)); def->body.attr.location = rb_ary_freeze(location); } break; case VM_METHOD_TYPE_BMETHOD: def->body.proc = (VALUE)opts; break; case VM_METHOD_TYPE_NOTIMPLEMENTED: def->body.cfunc.func = rb_f_notimplement; def->body.cfunc.argc = -1; break; case VM_METHOD_TYPE_OPTIMIZED: def->body.optimize_type = (enum method_optimized_type)opts; break; case VM_METHOD_TYPE_ZSUPER: case VM_METHOD_TYPE_UNDEF: break; default: rb_bug("rb_add_method: unsupported method type (%d)\n", type); } if (type != VM_METHOD_TYPE_UNDEF) { method_added(klass, mid); } return me; }
static void fill_path_and_lineno(rb_trace_arg_t *trace_arg) { if (trace_arg->path == Qundef) { rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(trace_arg->th, trace_arg->cfp); if (cfp) { trace_arg->path = cfp->iseq->location.path; trace_arg->lineno = rb_vm_get_sourceline(cfp); } else { trace_arg->path = Qnil; trace_arg->lineno = 0; } } }
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; }
/*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; }
rb_method_entry_t * rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex) { rb_thread_t *th; rb_control_frame_t *cfp; int line; rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex, klass); rb_method_definition_t *def = ALLOC(rb_method_definition_t); if (me->def && me->def->type == VM_METHOD_TYPE_REFINED) { me->def->body.orig_me->def = def; } else { me->def = def; } def->type = type; def->original_id = mid; def->alias_count = 0; switch (type) { case VM_METHOD_TYPE_ISEQ: { rb_iseq_t *iseq = (rb_iseq_t *)opts; *(rb_iseq_t **)&def->body.iseq = iseq; RB_OBJ_WRITTEN(klass, Qundef, iseq->self); break; } case VM_METHOD_TYPE_CFUNC: { rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts; setup_method_cfunc_struct(&def->body.cfunc, cfunc->func, cfunc->argc); } break; case VM_METHOD_TYPE_ATTRSET: case VM_METHOD_TYPE_IVAR: def->body.attr.id = (ID)(VALUE)opts; RB_OBJ_WRITE(klass, &def->body.attr.location, Qfalse); th = GET_THREAD(); cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp && (line = rb_vm_get_sourceline(cfp))) { VALUE location = rb_ary_new3(2, cfp->iseq->location.path, INT2FIX(line)); RB_OBJ_WRITE(klass, &def->body.attr.location, rb_ary_freeze(location)); } break; case VM_METHOD_TYPE_BMETHOD: RB_OBJ_WRITE(klass, &def->body.proc, (VALUE)opts); break; case VM_METHOD_TYPE_NOTIMPLEMENTED: setup_method_cfunc_struct(&def->body.cfunc, rb_f_notimplement, -1); break; case VM_METHOD_TYPE_OPTIMIZED: def->body.optimize_type = (enum method_optimized_type)opts; break; case VM_METHOD_TYPE_ZSUPER: case VM_METHOD_TYPE_UNDEF: break; case VM_METHOD_TYPE_REFINED: def->body.orig_me = (rb_method_entry_t *) opts; break; default: rb_bug("rb_add_method: unsupported method type (%d)\n", type); } if (type != VM_METHOD_TYPE_UNDEF && type != VM_METHOD_TYPE_REFINED) { method_added(klass, mid); } return me; }