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

ruby-changes:23748

From: ko1 <ko1@a...>
Date: Sat, 26 May 2012 11:10:46 +0900 (JST)
Subject: [ruby-changes:23748] ko1:r35799 (trunk): * vm.c (rb_frame_info_t): keep previous ISEQ frame info for CFUNC

ko1	2012-05-26 11:10:37 +0900 (Sat, 26 May 2012)

  New Revision: 35799

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

  Log:
    * vm.c (rb_frame_info_t): keep previous ISEQ frame info for CFUNC
      frame info.  And fix to cache a calculated line_no of ISEQ frame
      info.

  Modified files:
    trunk/ChangeLog
    trunk/vm.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 35798)
+++ ChangeLog	(revision 35799)
@@ -1,3 +1,9 @@
+Sat May 26 11:05:09 2012  Koichi Sasada  <ko1@a...>
+
+	* vm.c (rb_frame_info_t): keep previous ISEQ frame info for CFUNC
+	  frame info.  And fix to cache a calculated line_no of ISEQ frame
+	  info.
+
 Sat May 26 09:54:53 2012  Martin Bosslet  <Martin.Bosslet@g...>
 
 	* ext/openssl/ossl_ssl.c: Allow disabling client-side renegotiation.
Index: vm.c
===================================================================
--- vm.c	(revision 35798)
+++ vm.c	(revision 35799)
@@ -756,17 +756,27 @@
 typedef struct rb_frame_info_struct {
     enum FRAME_INFO_TYPE {
 	FRAME_INFO_TYPE_ISEQ = 1,
+	FRAME_INFO_TYPE_ISEQ_CALCED,
 	FRAME_INFO_TYPE_CFUNC,
 	FRAME_INFO_TYPE_IFUNC,
     } type;
 
+    enum FRAME_INFO_STORAGE {
+	FRAME_INFO_STORAGE_BACKTRACE,
+	FRAME_INFO_STORAGE_VALUE,
+    } storage;
+
     union {
 	struct {
 	    const rb_iseq_t *iseq;
-	    const VALUE *pc;
+	    union {
+		const VALUE *pc;
+		int line_no;
+	    } line_no;
 	} iseq;
 	struct {
 	    ID mid;
+	    struct rb_frame_info_struct *prev_fi;
 	} cfunc;
     } body;
 } rb_frame_info_t;
@@ -779,9 +789,14 @@
 
 	switch (fi->type) {
 	  case FRAME_INFO_TYPE_ISEQ:
+	  case FRAME_INFO_TYPE_ISEQ_CALCED:
 	    rb_gc_mark(fi->body.iseq.iseq->self);
 	    break;
 	  case FRAME_INFO_TYPE_CFUNC:
+	    if (fi->body.cfunc.prev_fi && fi->body.cfunc.prev_fi->storage == FRAME_INFO_STORAGE_VALUE) {
+		/* TODO: rb_gc_mark(fi->body.cfunc.prev_fi->self) */
+	    }
+	    break;
 	  case FRAME_INFO_TYPE_IFUNC:
 	  default:
 	    break;
@@ -790,11 +805,11 @@
 }
 
 static VALUE
-frame_info_format(VALUE file, VALUE line_no, VALUE name)
+frame_info_format(VALUE file, int line_no, VALUE name)
 {
-    if (line_no != INT2FIX(0)) {
+    if (line_no != 0) {
 	return rb_enc_sprintf(rb_enc_compatible(file, name), "%s:%d:in `%s'",
-			      RSTRING_PTR(file), FIX2INT(line_no), RSTRING_PTR(name));
+			      RSTRING_PTR(file), line_no, RSTRING_PTR(name));
     }
     else {
 	return rb_enc_sprintf(rb_enc_compatible(file, name), "%s:in `%s'",
@@ -802,24 +817,58 @@
     }
 }
 
+static int
+frame_info_line_no(rb_frame_info_t *fi)
+{
+    switch (fi->type) {
+      case FRAME_INFO_TYPE_ISEQ:
+	fi->type = FRAME_INFO_TYPE_ISEQ_CALCED;
+	return (fi->body.iseq.line_no.line_no = calc_line_no(fi->body.iseq.iseq, fi->body.iseq.line_no.pc));
+      case FRAME_INFO_TYPE_ISEQ_CALCED:
+	return fi->body.iseq.line_no.line_no;
+      case FRAME_INFO_TYPE_CFUNC:
+      case FRAME_INFO_TYPE_IFUNC:
+	break;
+    }
+    return 0;
+}
+
 static VALUE
-frame_info_to_str_override(rb_frame_info_t *fi, VALUE *args)
+frame_info_to_str(rb_frame_info_t *fi)
 {
+    VALUE file, name;
+    int line_no;
+
     switch (fi->type) {
       case FRAME_INFO_TYPE_ISEQ:
-	args[0] = fi->body.iseq.iseq->location.filename;
-	args[1] = INT2FIX(calc_line_no(fi->body.iseq.iseq, fi->body.iseq.pc));
-	args[2] = fi->body.iseq.iseq->location.name;
+	file = fi->body.iseq.iseq->location.filename;
+	name = fi->body.iseq.iseq->location.name;
+
+	line_no = fi->body.iseq.line_no.line_no = calc_line_no(fi->body.iseq.iseq, fi->body.iseq.line_no.pc);
+	fi->type = FRAME_INFO_TYPE_ISEQ_CALCED;
 	break;
+      case FRAME_INFO_TYPE_ISEQ_CALCED:
+	file = fi->body.iseq.iseq->location.filename;
+	line_no = fi->body.iseq.line_no.line_no;
+	name = fi->body.iseq.iseq->location.name;
       case FRAME_INFO_TYPE_CFUNC:
-	args[2] = rb_id2str(fi->body.cfunc.mid);
+	if (fi->body.cfunc.prev_fi) {
+	    file = fi->body.cfunc.prev_fi->body.iseq.iseq->location.filename;
+	    line_no = frame_info_line_no(fi->body.cfunc.prev_fi);
+	}
+	else {
+	    rb_thread_t *th = GET_THREAD();
+	    file = th->vm->progname ? th->vm->progname : ruby_engine_name;
+	    line_no = INT2FIX(0);
+	}
+	name = rb_id2str(fi->body.cfunc.mid);
 	break;
       case FRAME_INFO_TYPE_IFUNC:
       default:
-	rb_bug("frame_info_to_str_overwrite: unreachable");
+	rb_bug("frame_info_to_str: unreachable");
     }
 
-    return frame_info_format(args[0], args[1], args[2]);
+    return frame_info_format(file, line_no, name);
 }
 
 typedef struct rb_backtrace_struct {
@@ -936,6 +985,7 @@
 struct bt_iter_arg {
     rb_backtrace_t *bt;
     VALUE btobj;
+    rb_frame_info_t *prev_fi;
 };
 
 static void
@@ -954,8 +1004,10 @@
     struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
     rb_frame_info_t *fi = &arg->bt->backtrace[arg->bt->backtrace_size++];
     fi->type = FRAME_INFO_TYPE_ISEQ;
+    fi->storage = FRAME_INFO_STORAGE_BACKTRACE;
     fi->body.iseq.iseq = iseq;
-    fi->body.iseq.pc = pc;
+    fi->body.iseq.line_no.pc = pc;
+    arg->prev_fi = fi;
 }
 
 static void
@@ -964,13 +1016,16 @@
     struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
     rb_frame_info_t *fi = &arg->bt->backtrace[arg->bt->backtrace_size++];
     fi->type = FRAME_INFO_TYPE_CFUNC;
+    fi->storage = FRAME_INFO_STORAGE_BACKTRACE;
     fi->body.cfunc.mid = mid;
+    fi->body.cfunc.prev_fi = arg->prev_fi;
 }
 
 static VALUE
 backtrace_object(rb_thread_t *th, size_t lev, size_t n)
 {
     struct bt_iter_arg arg;
+    arg.prev_fi = 0;
 
     backtrace_each(th,
 		   bt_init,
@@ -1006,23 +1061,17 @@
 }
 
 static VALUE
-backtreace_collect(rb_backtrace_t *bt, VALUE (*func)(rb_frame_info_t *, VALUE *))
+backtreace_collect(rb_backtrace_t *bt, VALUE (*func)(rb_frame_info_t *))
 {
     VALUE btary;
     size_t i;
-    VALUE args[3];
-    rb_thread_t *th = GET_THREAD();
 
     btary = rb_ary_new2(bt->backtrace_size);
     rb_ary_store(btary, bt->backtrace_size-1, Qnil); /* create places */
 
-    args[0] = th->vm->progname ? th->vm->progname : ruby_engine_name;;
-    args[1] = INT2FIX(0);
-    args[2] = Qnil;
-
     for (i=0; i<bt->backtrace_size; i++) {
 	rb_frame_info_t *fi = &bt->backtrace[i];
-	RARRAY_PTR(btary)[bt->backtrace_size - i - 1] = func(fi, args);
+	RARRAY_PTR(btary)[bt->backtrace_size - i - 1] = func(fi);
     }
 
     return btary;
@@ -1038,7 +1087,7 @@
 	return bt->strary;
     }
     else {
-	bt->strary = backtreace_collect(bt, frame_info_to_str_override);
+	bt->strary = backtreace_collect(bt, frame_info_to_str);
 	return bt->strary;
     }
 }

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

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