[前][次][番号順一覧][スレッド一覧]

ruby-changes:10388

From: nobu <ko1@a...>
Date: Mon, 2 Feb 2009 07:36:29 +0900 (JST)
Subject: [ruby-changes:10388] Ruby:r21932 (trunk): * vm.c (vm_backtrace_each): now takes an iterator function.

nobu	2009-02-02 07:36:15 +0900 (Mon, 02 Feb 2009)

  New Revision: 21932

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=21932

  Log:
    * 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.

  Modified files:
    trunk/ChangeLog
    trunk/eval.c
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_dump.c
    trunk/vm_eval.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 21931)
+++ ChangeLog	(revision 21932)
@@ -1,3 +1,16 @@
+Mon Feb  2 07:36:13 2009  Nobuyoshi Nakada  <nobu@r...>
+
+	* 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@r...>
 
 	* encoding.c (rb_filesystem_encoding): Windows' filesystem encoding is
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 21931)
+++ vm_core.h	(revision 21932)
@@ -590,6 +590,9 @@
 
 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 *));
 
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 21931)
+++ vm_eval.c	(revision 21932)
@@ -16,6 +16,7 @@
 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 @@
     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 @@
     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
Index: eval.c
===================================================================
--- eval.c	(revision 21931)
+++ eval.c	(revision 21932)
@@ -330,7 +330,6 @@
 }
 
 NORETURN(static void rb_longjmp(int, VALUE));
-VALUE rb_make_backtrace(void);
 
 static void
 rb_longjmp(int tag, VALUE mesg)
Index: vm.c
===================================================================
--- vm.c	(revision 21931)
+++ vm.c	(revision 21932)
@@ -687,62 +687,59 @@
     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 *
Index: vm_dump.c
===================================================================
--- vm_dump.c	(revision 21931)
+++ vm_dump.c	(revision 21932)
@@ -564,28 +564,27 @@
     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);
 	}
     }
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]