summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--eval.c1
-rw-r--r--vm.c67
-rw-r--r--vm_core.h3
-rw-r--r--vm_dump.c27
-rw-r--r--vm_eval.c22
6 files changed, 76 insertions, 57 deletions
diff --git a/ChangeLog b/ChangeLog
index 52811c0..c4f5bc6 100644
--- a/ChangeLog
+++ b/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
diff --git a/eval.c b/eval.c
index c9aaa1d..603504e 100644
--- a/eval.c
+++ b/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)
diff --git a/vm.c b/vm.c
index a549f02..daed3bc 100644
--- a/vm.c
+++ b/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 *
diff --git a/vm_core.h b/vm_core.h
index 68f83ff..4d6ddcc 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -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 *));
diff --git a/vm_dump.c b/vm_dump.c
index 5bfd382..0a56d81 100644
--- a/vm_dump.c
+++ b/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);
}
}
diff --git a/vm_eval.c b/vm_eval.c
index e9774d2..ed0e34a 100644
--- a/vm_eval.c
+++ b/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