Пример #1
0
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();
    }
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
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;
}
Пример #9
0
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);
}
Пример #10
0
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;
}
Пример #11
0
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);
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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");
}