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

ruby-changes:32091

From: ko1 <ko1@a...>
Date: Fri, 13 Dec 2013 13:31:16 +0900 (JST)
Subject: [ruby-changes:32091] ko1:r44170 (trunk): * error.c: add Exception#backtrace_locations.

ko1	2013-12-13 13:31:06 +0900 (Fri, 13 Dec 2013)

  New Revision: 44170

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

  Log:
    * error.c: add Exception#backtrace_locations.
      Now, there are no setter and independent from Exception#backtrace.
      [Feature #8960]
    * eval.c (setup_exception): set backtrace locations for `bt_location'
      special attribute.
    * vm_backtrace.c (rb_backtrace_to_location_ary): added.
    * internal.h: ditto.
    * test/ruby/test_backtrace.rb: add a test for
      Exception#backtrace_locations.

  Modified files:
    trunk/ChangeLog
    trunk/error.c
    trunk/eval.c
    trunk/internal.h
    trunk/test/ruby/test_backtrace.rb
    trunk/vm_backtrace.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 44169)
+++ ChangeLog	(revision 44170)
@@ -1,3 +1,19 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Dec 13 13:25:30 2013  Koichi Sasada  <ko1@a...>
+
+	* error.c: add Exception#backtrace_locations.
+	  Now, there are no setter and independent from Exception#backtrace.
+	  [Feature #8960]
+
+	* eval.c (setup_exception): set backtrace locations for `bt_location'
+	  special attribute.
+
+	* vm_backtrace.c (rb_backtrace_to_location_ary): added.
+
+	* internal.h: ditto.
+
+	* test/ruby/test_backtrace.rb: add a test for
+	  Exception#backtrace_locations.
+
 Fri Dec 13 12:01:07 2013  Koichi Sasada  <ko1@a...>
 
 	* gc.c (garbage_collect_body): use rb_bug() and explicit error message
Index: vm_backtrace.c
===================================================================
--- vm_backtrace.c	(revision 44169)
+++ vm_backtrace.c	(revision 44170)
@@ -372,6 +372,7 @@ typedef struct rb_backtrace_struct { https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L372
     rb_backtrace_location_t *backtrace_base;
     int backtrace_size;
     VALUE strary;
+    VALUE locary;
 } rb_backtrace_t;
 
 static void
@@ -383,8 +384,9 @@ backtrace_mark(void *ptr) https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L384
 
 	for (i=0; i<s; i++) {
 	    location_mark_entry(&bt->backtrace[i]);
-	    rb_gc_mark(bt->strary);
 	}
+	rb_gc_mark(bt->strary);
+	rb_gc_mark(bt->locary);
     }
 }
 
@@ -631,6 +633,18 @@ backtrace_to_location_ary(VALUE self, lo https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L633
     return r;
 }
 
+VALUE
+rb_backtrace_to_location_ary(VALUE self)
+{
+    rb_backtrace_t *bt;
+    GetCoreDataFromValue(self, rb_backtrace_t, bt);
+
+    if (!bt->locary) {
+	bt->locary = backtrace_to_location_ary(self, 0, 0);
+    }
+    return bt->locary;
+}
+
 static VALUE
 backtrace_dump_data(VALUE self)
 {
Index: eval.c
===================================================================
--- eval.c	(revision 44169)
+++ eval.c	(revision 44170)
@@ -493,10 +493,12 @@ setup_exception(rb_thread_t *th, int tag https://github.com/ruby/ruby/blob/trunk/eval.c#L493
 		if (OBJ_FROZEN(mesg)) {
 		    mesg = rb_obj_dup(mesg);
 		}
+		rb_iv_set(mesg, "bt_locations", at);
 		set_backtrace(mesg, at);
 	    }
 	}
     }
+
     if (!NIL_P(mesg)) {
 	th->errinfo = mesg;
     }
Index: error.c
===================================================================
--- error.c	(revision 44169)
+++ error.c	(revision 44170)
@@ -736,6 +736,30 @@ exc_backtrace(VALUE exc) https://github.com/ruby/ruby/blob/trunk/error.c#L736
     return obj;
 }
 
+/*
+ *  call-seq:
+ *     exception.backtrace_locations    -> array
+ *
+ *  Returns any backtrace associated with the exception. This method is
+ *  similar to Exception#backtrace, but the backtrace is an array of
+ *   Thread::Backtrace::Location.
+ *
+ *  Now, this method is not affected by Exception#set_backtrace().
+ */
+static VALUE
+exc_backtrace_locations(VALUE exc)
+{
+    ID bt_locations;
+    VALUE obj;
+
+    CONST_ID(bt_locations, "bt_locations");
+    obj = rb_attr_get(exc, bt_locations);
+    if (!NIL_P(obj)) {
+	obj = rb_backtrace_to_location_ary(obj);
+    }
+    return obj;
+}
+
 VALUE
 rb_check_backtrace(VALUE bt)
 {
@@ -1749,6 +1773,7 @@ Init_Exception(void) https://github.com/ruby/ruby/blob/trunk/error.c#L1773
     rb_define_method(rb_eException, "message", exc_message, 0);
     rb_define_method(rb_eException, "inspect", exc_inspect, 0);
     rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
+    rb_define_method(rb_eException, "backtrace_locations", exc_backtrace_locations, 0);
     rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
     rb_define_method(rb_eException, "cause", exc_cause, 0);
 
Index: internal.h
===================================================================
--- internal.h	(revision 44169)
+++ internal.h	(revision 44170)
@@ -800,6 +800,7 @@ VALUE rb_make_backtrace(void); https://github.com/ruby/ruby/blob/trunk/internal.h#L800
 void rb_backtrace_print_as_bugreport(void);
 int rb_backtrace_p(VALUE obj);
 VALUE rb_backtrace_to_str_ary(VALUE obj);
+VALUE rb_backtrace_to_location_ary(VALUE obj);
 void rb_backtrace_print_to(VALUE output);
 VALUE rb_vm_backtrace_object(void);
 
Index: test/ruby/test_backtrace.rb
===================================================================
--- test/ruby/test_backtrace.rb	(revision 44169)
+++ test/ruby/test_backtrace.rb	(revision 44170)
@@ -14,6 +14,36 @@ class TestBacktrace < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/test/ruby/test_backtrace.rb#L14
     assert_match(/.+:\d+:.+/, bt[0])
   end
 
+  def helper_test_exception_backtrace_locations
+    raise
+  end
+
+  def test_exception_backtrace_locations
+    bt = Fiber.new{
+      begin
+        raise
+      rescue => e
+        e.backtrace_locations
+      end
+    }.resume
+    assert_equal(1, bt.size)
+    assert_match(/.+:\d+:.+/, bt[0].to_s)
+
+    bt = Fiber.new{
+      begin
+        begin
+          helper_test_exception_backtrace_locations
+        rescue
+          raise
+        end
+      rescue => e
+        e.backtrace_locations
+      end
+    }.resume
+    assert_equal(2, bt.size)
+    assert_match(/helper_test_exception_backtrace_locations/, bt[0].to_s)
+  end
+
   def test_caller_lev
     cs = []
     Fiber.new{

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

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