static inline void vm_pop_frame(rb_thread_t *th) { #if COLLECT_PROFILE rb_control_frame_t *cfp = th->cfp; if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { VALUE current_time = clock(); rb_control_frame_t *cfp = th->cfp; cfp->prof_time_self = current_time - cfp->prof_time_self; (cfp+1)->prof_time_chld += cfp->prof_time_self; cfp->iseq->profile.count++; cfp->iseq->profile.time_cumu = cfp->prof_time_self; cfp->iseq->profile.time_self = cfp->prof_time_self - cfp->prof_time_chld; } else if (0 /* c method? */) { } #endif th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); if (VMDEBUG == 2) { SDR(); } }
static VALUE proc_to_s(VALUE self) { VALUE str = 0; rb_proc_t *proc; char *cname = rb_obj_classname(self); rb_iseq_t *iseq; GetProcPtr(self, proc); iseq = proc->block.iseq; if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { int line_no = 0; if (iseq->insn_info_tbl) { line_no = iseq->insn_info_tbl[0].line_no; } str = rb_sprintf("#<%s:%lx@%s:%d>", cname, self, RSTRING_PTR(iseq->filename), line_no); } else { str = rb_sprintf("#<%s:%p>", cname, proc->block.iseq); } if (OBJ_TAINTED(self)) { OBJ_TAINT(str); } return str; }
static VALUE proc_to_s(VALUE self) { VALUE str = 0; rb_proc_t *proc; const char *cname = rb_obj_classname(self); rb_iseq_t *iseq; const char *is_lambda; GetProcPtr(self, proc); iseq = proc->block.iseq; is_lambda = proc->is_lambda ? " (lambda)" : ""; if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { int line_no = 0; if (iseq->insn_info_table) { line_no = rb_iseq_first_lineno(iseq); } str = rb_sprintf("#<%s:%p@%s:%d%s>", cname, (void *)self, RSTRING_PTR(iseq->filename), line_no, is_lambda); } else { str = rb_sprintf("#<%s:%p%s>", cname, (void *)proc->block.iseq, is_lambda); } if (OBJ_TAINTED(self)) { OBJ_TAINT(str); } return str; }
rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, rb_control_frame_t *cfp) { while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) { if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { return cfp; } cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } return 0; }
int rb_vm_get_sourceline(const rb_control_frame_t *cfp) { int lineno = 0; const rb_iseq_t *iseq = cfp->iseq; if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { lineno = calc_lineno(cfp->iseq, cfp->pc); } return lineno; }
static rb_iseq_t * get_proc_iseq(VALUE self) { rb_proc_t *proc; rb_iseq_t *iseq; GetProcPtr(self, proc); iseq = proc->block.iseq; if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) return 0; return iseq; }
static rb_control_frame_t * vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp) { if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { return cfp; } cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) { if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { return cfp; } if ((cfp->flag & VM_FRAME_FLAG_PASSED) == 0) { break; } cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } return 0; }
static rb_iseq_t * get_method_iseq(VALUE method) { struct METHOD *data; NODE *body; rb_iseq_t *iseq; Data_Get_Struct(method, struct METHOD, data); body = data->body; switch (nd_type(body)) { case RUBY_VM_METHOD_NODE: GetISeqPtr((VALUE)body->nd_body, iseq); if (RUBY_VM_NORMAL_ISEQ_P(iseq)) break; default: return 0; } return iseq; }
void rb_vmdebug_debug_print_register(rb_thread_t *th) { rb_control_frame_t *cfp = th->cfp; ptrdiff_t pc = -1; ptrdiff_t ep = cfp->ep - th->stack; ptrdiff_t cfpi; if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { pc = cfp->pc - cfp->iseq->iseq_encoded; } if (ep < 0 || (size_t)ep > th->stack_size) { ep = -1; } cfpi = ((rb_control_frame_t *)(th->stack + th->stack_size)) - cfp; fprintf(stderr, " [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n", pc, (cfp->sp - th->stack), ep, cfpi); }
int rb_vm_get_sourceline(const rb_control_frame_t *cfp) { int line_no = 0; const rb_iseq_t *iseq = cfp->iseq; if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { rb_num_t i; size_t pos = cfp->pc - cfp->iseq->iseq_encoded; for (i = 0; i < iseq->insn_info_size; i++) { if (iseq->insn_info_table[i].position == pos) { if (i == 0) goto found; line_no = iseq->insn_info_table[i - 1].line_no; goto found; } } line_no = iseq->insn_info_table[i - 1].line_no; } found: return line_no; }
void debug_print_register(rb_thread_t *th) { rb_control_frame_t *cfp = th->cfp; int pc = -1; int lfp = cfp->lfp - th->stack; int dfp = cfp->dfp - th->stack; int cfpi; if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { pc = cfp->pc - cfp->iseq->iseq_encoded; } if (lfp < 0 || lfp > th->stack_size) lfp = -1; if (dfp < 0 || dfp > th->stack_size) dfp = -1; cfpi = ((rb_control_frame_t *)(th->stack + th->stack_size)) - cfp; fprintf(stderr, " [PC] %04d, [SP] %04td, [LFP] %04d, [DFP] %04d, [CFP] %04d\n", pc, cfp->sp - th->stack, lfp, dfp, cfpi); }
static int profiler_source_location(const char **p_srcfile, long *p_line) { #if 0 VALUE thval = rb_thread_current(); rb_thread_t *th = DATA_PTR(thval); rb_control_frame_t *cfp = th->cfp; rb_iseq_t *iseq; const char *srcfile; long line = -1, i, pc; /* find cfp */ while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) { if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { break; } cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) { return 0; } iseq = cfp->iseq; /* find sourcefile */ srcfile = RSTRING_PTR(iseq->filename); if (!srcfile) { return 0; } /* find line */ if (iseq->insn_info_size <= 0) { return 0; } pc = cfp->pc - iseq->iseq_encoded; for (i = 0; i < iseq->insn_info_size; i++) { if (iseq->insn_info_table[i].position == pc) { line = iseq->insn_info_table[i - 1].line_no; break; } } if (line < 0) { line = iseq->insn_info_table[i - 1].line_no; } if (line < 0) { rb_bug("pline_callback_info: should not be reached"); } #else const char *srcfile; long line; srcfile = rb_sourcefile(); if (!srcfile) { return 0; } line = rb_sourceline(); if (line < 0) { return 0; } #endif *p_srcfile = srcfile; *p_line = line; return 1; }
static VALUE vm_make_env_each(rb_thread_t * const th, rb_control_frame_t * const cfp, VALUE *envptr, VALUE * const endptr) { VALUE envval, penvval = 0; rb_env_t *env; VALUE *nenvptr; int i, local_size; if (ENV_IN_HEAP_P(th, envptr)) { return ENV_VAL(envptr); } if (envptr != endptr) { VALUE *penvptr = GC_GUARDED_PTR_REF(*envptr); rb_control_frame_t *pcfp = cfp; if (ENV_IN_HEAP_P(th, penvptr)) { penvval = ENV_VAL(penvptr); } else { while (pcfp->dfp != penvptr) { pcfp++; if (pcfp->dfp == 0) { SDR(); rb_bug("invalid dfp"); } } penvval = vm_make_env_each(th, pcfp, penvptr, endptr); cfp->lfp = pcfp->lfp; *envptr = GC_GUARDED_PTR(pcfp->dfp); } } /* allocate env */ envval = env_alloc(); GetEnvPtr(envval, env); if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { local_size = 2; } else { local_size = cfp->iseq->local_size; } env->env_size = local_size + 1 + 2; env->local_size = local_size; env->env = ALLOC_N(VALUE, env->env_size); env->prev_envval = penvval; for (i = 0; i <= local_size; i++) { env->env[i] = envptr[-local_size + i]; #if 0 fprintf(stderr, "%2d ", &envptr[-local_size + i] - th->stack); dp(env->env[i]); if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { /* clear value stack for GC */ envptr[-local_size + i] = 0; } #endif } *envptr = envval; /* GC mark */ nenvptr = &env->env[i - 1]; nenvptr[1] = envval; /* frame self */ nenvptr[2] = penvval; /* frame prev env object */ /* reset lfp/dfp in cfp */ cfp->dfp = nenvptr; if (envptr == endptr) { cfp->lfp = nenvptr; } /* as Binding */ env->block.self = cfp->self; env->block.lfp = cfp->lfp; env->block.dfp = cfp->dfp; env->block.iseq = cfp->iseq; if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { /* TODO */ env->block.iseq = 0; } return envval; }
void rb_thread_mark(void *ptr) { rb_thread_t *th = NULL; RUBY_MARK_ENTER("thread"); if (ptr) { th = ptr; if (th->stack) { VALUE *p = th->stack; VALUE *sp = th->cfp->sp; rb_control_frame_t *cfp = th->cfp; rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size); while (p < sp) { rb_gc_mark(*p++); } rb_gc_mark_locations(p, p + th->mark_stack_len); while (cfp != limit_cfp) { rb_iseq_t *iseq = cfp->iseq; rb_gc_mark(cfp->proc); if (iseq) { rb_gc_mark(RUBY_VM_NORMAL_ISEQ_P(iseq) ? iseq->self : (VALUE)iseq); } if (cfp->me) ((rb_method_entry_t *)cfp->me)->mark = 1; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } } /* mark ruby objects */ RUBY_MARK_UNLESS_NULL(th->first_proc); if (th->first_proc) RUBY_MARK_UNLESS_NULL(th->first_args); RUBY_MARK_UNLESS_NULL(th->thgroup); RUBY_MARK_UNLESS_NULL(th->value); RUBY_MARK_UNLESS_NULL(th->errinfo); RUBY_MARK_UNLESS_NULL(th->thrown_errinfo); RUBY_MARK_UNLESS_NULL(th->local_svar); RUBY_MARK_UNLESS_NULL(th->top_self); RUBY_MARK_UNLESS_NULL(th->top_wrapper); RUBY_MARK_UNLESS_NULL(th->fiber); RUBY_MARK_UNLESS_NULL(th->root_fiber); RUBY_MARK_UNLESS_NULL(th->stat_insn_usage); RUBY_MARK_UNLESS_NULL(th->last_status); RUBY_MARK_UNLESS_NULL(th->locking_mutex); rb_mark_tbl(th->local_storage); if (GET_THREAD() != th && th->machine_stack_start && th->machine_stack_end) { rb_gc_mark_machine_stack(th); rb_gc_mark_locations((VALUE *)&th->machine_regs, (VALUE *)(&th->machine_regs) + sizeof(th->machine_regs) / sizeof(VALUE)); } mark_event_hooks(th->event_hooks); } RUBY_MARK_LEAVE("thread"); }