Permalink
Browse files

* vm.c: add RubyVM::Backtrace object (btobj).

  Backtrace information contains an array consists of location
  information for each frames by string.
  RubyVM::Backtrace object is lightweight backtrace information,
  which contains complete information to generate traditional style
  backtrace (an array of strings) with faster generation.
  If someone accesses to backtrace information via
  Exception#backtrace, then convert a RubyVM::Backtrace object to
  traditonal style backtrace.
  This change causes incompatibility on marshal dumpped binary
  of Exception.  If you have any trouble on it, please tell us
  before Ruby 2.0 release.
  Note that RubyVM::Backtrace object should not expose Ruby level.
* error.c, eval.c, vm_eval.c: ditto.
* internal.h: ditto.
* eval_error.c: fix to skip "set_backtrace" method invocation in
  creating an exception object if it call a normal set_backtrace
  method (defined by core).
* test/ruby/test_settracefunc.rb: fix for above change.
* vm_method.c (rb_method_defined_by): added.  This function
  checks that the given object responds with the given method
  by the given cfunc.
* benchmark/bm_vm2_raise1.rb, benchmark/bm_vm2_raise2.rb:
  add to measure exception creation speed. raise1 create
  exception objects from shallow stack frame.  raise2 create
  exception objects from deep stack frame.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information...
1 parent bd5c750 commit 3dcebce5235276e99a75c6b0c71f4f3c4f4e225c @ko1 ko1 committed May 24, 2012
Showing with 426 additions and 28 deletions.
  1. +35 −0 ChangeLog
  2. +18 −0 benchmark/bm_vm2_raise1.rb
  3. +18 −0 benchmark/bm_vm2_raise2.rb
  4. +13 −4 error.c
  5. +1 −1 eval.c
  6. +11 −0 eval_error.c
  7. +5 −0 internal.h
  8. +0 −4 test/ruby/test_settracefunc.rb
  9. +294 −11 vm.c
  10. +16 −8 vm_eval.c
  11. +15 −0 vm_method.c
View
@@ -1,3 +1,38 @@
+Thu May 24 14:30:13 2012 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c: add RubyVM::Backtrace object (btobj).
+ Backtrace information contains an array consists of location
+ information for each frames by string.
+ RubyVM::Backtrace object is lightweight backtrace information,
+ which contains complete information to generate traditional style
+ backtrace (an array of strings) with faster generation.
+ If someone accesses to backtrace information via
+ Exception#backtrace, then convert a RubyVM::Backtrace object to
+ traditonal style backtrace.
+ This change causes incompatibility on marshal dumpped binary
+ of Exception. If you have any trouble on it, please tell us
+ before Ruby 2.0 release.
+ Note that RubyVM::Backtrace object should not expose Ruby level.
+
+ * error.c, eval.c, vm_eval.c: ditto.
+
+ * internal.h: ditto.
+
+ * eval_error.c: fix to skip "set_backtrace" method invocation in
+ creating an exception object if it call a normal set_backtrace
+ method (defined by core).
+
+ * test/ruby/test_settracefunc.rb: fix for above change.
+
+ * vm_method.c (rb_method_defined_by): added. This function
+ checks that the given object responds with the given method
+ by the given cfunc.
+
+ * benchmark/bm_vm2_raise1.rb, benchmark/bm_vm2_raise2.rb:
+ add to measure exception creation speed. raise1 create
+ exception objects from shallow stack frame. raise2 create
+ exception objects from deep stack frame.
+
Thu May 24 12:07:46 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* io.c (io_strip_bom): check EOF. [Bug #6487][ruby-core:45203]
@@ -0,0 +1,18 @@
+def rec n
+ if n > 0
+ rec n-1
+ else
+ raise
+ end
+end
+
+i=0
+while i<6_000_000 # benchmark loop 2
+ i+=1
+
+ begin
+ rec 1
+ rescue
+ # ignore
+ end
+end
@@ -0,0 +1,18 @@
+def rec n
+ if n > 0
+ rec n-1
+ else
+ raise
+ end
+end
+
+i=0
+while i<6_000_000 # benchmark loop 2
+ i+=1
+
+ begin
+ rec 10
+ rescue
+ # ignore
+ end
+end
View
@@ -673,9 +673,17 @@ static VALUE
exc_backtrace(VALUE exc)
{
ID bt;
+ VALUE obj;
CONST_ID(bt, "bt");
- return rb_attr_get(exc, bt);
+ obj = rb_attr_get(exc, bt);
+
+ if (rb_backtrace_p(obj)) {
+ obj = rb_backtrace_to_str_ary(obj);
+ /* rb_iv_set(exc, "bt", obj); */
+ }
+
+ return obj;
}
VALUE
@@ -686,6 +694,7 @@ rb_check_backtrace(VALUE bt)
if (!NIL_P(bt)) {
if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt);
+ if (rb_backtrace_p(bt)) return bt;
if (!RB_TYPE_P(bt, T_ARRAY)) {
rb_raise(rb_eTypeError, err);
}
@@ -708,8 +717,8 @@ rb_check_backtrace(VALUE bt)
*
*/
-static VALUE
-exc_set_backtrace(VALUE exc, VALUE bt)
+VALUE
+rb_exc_set_backtrace(VALUE exc, VALUE bt)
{
return rb_iv_set(exc, "bt", rb_check_backtrace(bt));
}
@@ -1669,7 +1678,7 @@ Init_Exception(void)
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, "set_backtrace", exc_set_backtrace, 1);
+ rb_define_method(rb_eException, "set_backtrace", rb_exc_set_backtrace, 1);
rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
View
@@ -387,7 +387,7 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
else {
at = get_backtrace(mesg);
if (NIL_P(at)) {
- at = rb_make_backtrace();
+ at = rb_vm_backtrace_object();
if (OBJ_FROZEN(mesg)) {
mesg = rb_obj_dup(mesg);
}
View
@@ -58,6 +58,17 @@ rb_get_backtrace(VALUE info)
static void
set_backtrace(VALUE info, VALUE bt)
{
+ ID set_backtrace = rb_intern("set_backtrace");
+
+ if (rb_backtrace_p(bt)) {
+ if (rb_method_defined_by(info, set_backtrace, rb_exc_set_backtrace)) {
+ rb_exc_set_backtrace(info, bt);
+ return;
+ }
+ else {
+ bt = rb_backtrace_to_str_ary(bt);
+ }
+ }
rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
}
View
@@ -83,6 +83,7 @@ void rb_gc_mark_encodings(void);
NORETURN(PRINTF_ARGS(void rb_compile_bug(const char*, int, const char*, ...), 3, 4));
VALUE rb_check_backtrace(VALUE);
NORETURN(void rb_async_bug_errno(const char *,int));
+VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt);
/* eval_error.c */
void ruby_error_print(void);
@@ -207,6 +208,9 @@ void rb_vm_inc_const_missing_count(void);
void rb_thread_mark(void *th);
const void **rb_vm_get_insns_address_table(void);
VALUE rb_sourcefilename(void);
+int rb_backtrace_p(VALUE obj);
+VALUE rb_backtrace_to_str_ary(VALUE obj);
+VALUE rb_vm_backtrace_object();
/* vm_dump.c */
void rb_vm_bugreport(void);
@@ -217,6 +221,7 @@ VALUE rb_current_realfilepath(void);
/* vm_method.c */
void Init_eval_method(void);
+int rb_method_defined_by(VALUE obj, ID mid, VALUE (*cfunc)(ANYARGS));
/* miniprelude.c, prelude.c */
void Init_prelude(void);
@@ -250,10 +250,6 @@ def test_raise
events.shift)
assert_equal(["c-return", 5, :backtrace, Exception],
events.shift)
- assert_equal(["c-call", 5, :set_backtrace, Exception],
- events.shift)
- assert_equal(["c-return", 5, :set_backtrace, Exception],
- events.shift)
assert_equal(["raise", 5, :test_raise, TestSetTraceFunc],
events.shift)
assert_equal(["c-return", 5, :raise, Kernel],
Oops, something went wrong.

0 comments on commit 3dcebce

Please sign in to comment.