diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-02-01 22:36:15 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-02-01 22:36:15 +0000 |
commit | a7b5c603b4747704d8ed7ce22c342649e88f6993 (patch) | |
tree | 9ec74b2215a215f0364e0ec3adec42bdb18405dc /vm.c | |
parent | 1c4e92c1851d1027f22b64cdd6e4d40d212609b6 (diff) | |
download | ruby-a7b5c603b4747704d8ed7ce22c342649e88f6993.tar.gz |
* 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
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 67 |
1 files changed, 32 insertions, 35 deletions
@@ -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 * |