mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* vm.c (vm_backtrace_each): now takes an iterator function.
* vm_core.h (rb_make_backtrace, rb_backtrace_each): added prototypes. * vm_dump.c (rb_vm_bugreport), vm_eval.c (rb_backtrace): gets rid of allocating objects. * vm_eval.c (rb_backtrace_each): new function which iterates over each backtrace info. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21932 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1c4e92c185
commit
a7b5c603b4
6 changed files with 76 additions and 57 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
Mon Feb 2 07:36:13 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* vm.c (vm_backtrace_each): now takes an iterator function.
|
||||
|
||||
* vm_core.h (rb_make_backtrace, rb_backtrace_each): added
|
||||
prototypes.
|
||||
|
||||
* vm_dump.c (rb_vm_bugreport), vm_eval.c (rb_backtrace): gets rid
|
||||
of allocating objects.
|
||||
|
||||
* vm_eval.c (rb_backtrace_each): new function which iterates over
|
||||
each backtrace info.
|
||||
|
||||
Mon Feb 2 06:51:36 2009 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* encoding.c (rb_filesystem_encoding): Windows' filesystem encoding is
|
||||
|
|
1
eval.c
1
eval.c
|
@ -330,7 +330,6 @@ rb_frozen_class_p(VALUE klass)
|
|||
}
|
||||
|
||||
NORETURN(static void rb_longjmp(int, VALUE));
|
||||
VALUE rb_make_backtrace(void);
|
||||
|
||||
static void
|
||||
rb_longjmp(int tag, VALUE mesg)
|
||||
|
|
67
vm.c
67
vm.c
|
@ -687,62 +687,59 @@ rb_vm_get_sourceline(const rb_control_frame_t *cfp)
|
|||
return line_no;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
vm_backtrace_each(rb_thread_t *th,
|
||||
const rb_control_frame_t *limit_cfp, const rb_control_frame_t *cfp,
|
||||
const char * file, int line_no, VALUE ary)
|
||||
static int
|
||||
vm_backtrace_each(rb_thread_t *th, int lev, rb_backtrace_iter_func *iter, void *arg)
|
||||
{
|
||||
VALUE str;
|
||||
const rb_control_frame_t *limit_cfp = th->cfp;
|
||||
const rb_control_frame_t *cfp = (void *)(th->stack + th->stack_size);
|
||||
const char *file;
|
||||
int line_no = 0;
|
||||
|
||||
cfp -= 2;
|
||||
while (lev-- >= 0) {
|
||||
if (++limit_cfp >= cfp) {
|
||||
return Qfalse;
|
||||
}
|
||||
}
|
||||
limit_cfp = RUBY_VM_NEXT_CONTROL_FRAME(limit_cfp);
|
||||
file = RSTRING_PTR(th->vm->progname);
|
||||
while (cfp > limit_cfp) {
|
||||
str = 0;
|
||||
if (cfp->iseq != 0) {
|
||||
if (cfp->pc != 0) {
|
||||
rb_iseq_t *iseq = cfp->iseq;
|
||||
|
||||
line_no = rb_vm_get_sourceline(cfp);
|
||||
file = RSTRING_PTR(iseq->filename);
|
||||
str = rb_sprintf("%s:%d:in `%s'",
|
||||
file, line_no, RSTRING_PTR(iseq->name));
|
||||
rb_ary_push(ary, str);
|
||||
if ((*iter)(arg, file, line_no, RSTRING_PTR(iseq->name))) break;
|
||||
}
|
||||
}
|
||||
else if (RUBYVM_CFUNC_FRAME_P(cfp)) {
|
||||
str = rb_sprintf("%s:%d:in `%s'",
|
||||
file, line_no,
|
||||
rb_id2name(cfp->method_id));
|
||||
rb_ary_push(ary, str);
|
||||
if ((*iter)(arg, file, line_no, rb_id2name(cfp->method_id))) break;
|
||||
}
|
||||
cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp);
|
||||
}
|
||||
return rb_ary_reverse(ary);
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
static int
|
||||
vm_backtrace_push(void *arg, const char *file, int line_no, const char *name)
|
||||
{
|
||||
VALUE *aryp = arg;
|
||||
if (!*aryp) {
|
||||
*aryp = rb_ary_new();
|
||||
}
|
||||
rb_ary_push(*aryp, rb_sprintf("%s:%d:in `%s'", file, line_no, name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
vm_backtrace(rb_thread_t *th, int lev)
|
||||
{
|
||||
VALUE ary;
|
||||
const rb_control_frame_t *cfp = th->cfp;
|
||||
const rb_control_frame_t *top_of_cfp = (void *)(th->stack + th->stack_size);
|
||||
top_of_cfp -= 2;
|
||||
VALUE ary = 0;
|
||||
|
||||
if (lev < 0) {
|
||||
/* TODO ?? */
|
||||
ary = rb_ary_new();
|
||||
}
|
||||
else {
|
||||
while (lev-- >= 0) {
|
||||
cfp++;
|
||||
if (cfp >= top_of_cfp) {
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
ary = rb_ary_new();
|
||||
}
|
||||
|
||||
ary = vm_backtrace_each(th, RUBY_VM_NEXT_CONTROL_FRAME(cfp),
|
||||
top_of_cfp, RSTRING_PTR(th->vm->progname), 0, ary);
|
||||
return ary;
|
||||
vm_backtrace_each(th, lev, vm_backtrace_push, &ary);
|
||||
if (!ary) return Qnil;
|
||||
return rb_ary_reverse(ary);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
|
@ -590,6 +590,9 @@ VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
|
|||
|
||||
void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
|
||||
int ruby_thread_has_gvl_p(void);
|
||||
VALUE rb_make_backtrace(void);
|
||||
typedef int rb_backtrace_iter_func(void *, const char *, int, const char *);
|
||||
VALUE rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg);
|
||||
|
||||
NOINLINE(void rb_gc_save_machine_context(rb_thread_t *));
|
||||
|
||||
|
|
27
vm_dump.c
27
vm_dump.c
|
@ -564,28 +564,27 @@ rb_vmdebug_thread_dump_state(VALUE self)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rb_make_backtrace(void);
|
||||
static int
|
||||
bugreport_backtrace(void *arg, const char *file, int line, const char *method)
|
||||
{
|
||||
if (!*(int *)arg) {
|
||||
fprintf(stderr, "-- Ruby level backtrace information"
|
||||
"-----------------------------------------\n");
|
||||
*(int *)arg = 1;
|
||||
}
|
||||
fprintf(stderr, "%s:%d:in `%s'\n", file, line, method);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rb_vm_bugreport(void)
|
||||
{
|
||||
VALUE bt;
|
||||
|
||||
if (GET_THREAD()->vm) {
|
||||
int i;
|
||||
SDR();
|
||||
|
||||
bt = rb_make_backtrace();
|
||||
|
||||
if (bt) {
|
||||
fprintf(stderr, "-- Ruby level backtrace information"
|
||||
"-----------------------------------------\n");
|
||||
|
||||
for (i = 0; i < RARRAY_LEN(bt); i++) {
|
||||
VALUE str = RARRAY_PTR(bt)[i];
|
||||
fprintf(stderr, "%s\n", RSTRING_PTR(str));
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
if (rb_backtrace_each(bugreport_backtrace, &i)) {
|
||||
fputs("\n", stderr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
22
vm_eval.c
22
vm_eval.c
|
@ -16,6 +16,7 @@ static inline VALUE rb_vm_set_finish_env(rb_thread_t * th);
|
|||
static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref);
|
||||
static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
|
||||
static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
|
||||
static int vm_backtrace_each(rb_thread_t *th, int lev, rb_backtrace_iter_func *iter, void *arg);
|
||||
static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex);
|
||||
static VALUE vm_exec(rb_thread_t *th);
|
||||
static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
|
||||
|
@ -1304,16 +1305,17 @@ rb_f_caller(int argc, VALUE *argv)
|
|||
return vm_backtrace(GET_THREAD(), lev);
|
||||
}
|
||||
|
||||
static int
|
||||
print_backtrace(void *arg, const char *file, int line, const char *method)
|
||||
{
|
||||
fprintf((FILE *)arg, "\tfrom %s:%d:in `%s'\n", file, line, method);
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
void
|
||||
rb_backtrace(void)
|
||||
{
|
||||
long i;
|
||||
VALUE ary;
|
||||
|
||||
ary = vm_backtrace(GET_THREAD(), -1);
|
||||
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
||||
printf("\tfrom %s\n", RSTRING_PTR(RARRAY_PTR(ary)[i]));
|
||||
}
|
||||
vm_backtrace_each(GET_THREAD(), -1, print_backtrace, stdout);
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
@ -1322,6 +1324,12 @@ rb_make_backtrace(void)
|
|||
return vm_backtrace(GET_THREAD(), -1);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg)
|
||||
{
|
||||
return vm_backtrace_each(GET_THREAD(), -1, iter, arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* local_variables => array
|
||||
|
|
Loading…
Reference in a new issue