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

ruby-changes:25950

From: ko1 <ko1@a...>
Date: Fri, 30 Nov 2012 07:43:38 +0900 (JST)
Subject: [ruby-changes:25950] ko1:r38007 (trunk): [EXPERIMENTAL: NEED DISCUSS]

ko1	2012-11-30 07:28:16 +0900 (Fri, 30 Nov 2012)

  New Revision: 38007

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

  Log:
    [EXPERIMENTAL: NEED DISCUSS]
    * vm_trace.c: add events
    * :thread_begin - hook at thread beggining.
    * :thead_end - hook at thread ending.
    * :b_call - hook at block enter.
    * :b_return - hook at block leave.
      This change slow down block invocation.
      Please try and give us feedback until 2.0 code freeze.
    * include/ruby/ruby.h: ditto.
    * compile.c (rb_iseq_compile_node): ditto.
    * insns.def: ditto.
    * thread.c: ditto.
    * vm.c: ditto.
    * include/ruby/debug.h: add a comment.
    * test/ruby/test_settracefunc.rb: add a tests.

  Modified files:
    trunk/ChangeLog
    trunk/compile.c
    trunk/include/ruby/debug.h
    trunk/include/ruby/ruby.h
    trunk/insns.def
    trunk/test/ruby/test_settracefunc.rb
    trunk/thread.c
    trunk/vm.c
    trunk/vm_trace.c

Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 38006)
+++ include/ruby/ruby.h	(revision 38007)
@@ -1574,6 +1574,13 @@
 #define RUBY_EVENT_SWITCH   0x20000
 #define RUBY_EVENT_COVERAGE 0x40000
 
+/* for TracePoint extended events */
+#define RUBY_EVENT_B_CALL          0x0100
+#define RUBY_EVENT_B_RETURN        0x0200
+#define RUBY_EVENT_THREAD_BEGIN    0x0400
+#define RUBY_EVENT_THREAD_END      0x0800
+#define RUBY_EVENT_TRACEPOINT_ALL  0xFFFF
+
 typedef unsigned int rb_event_flag_t;
 typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass);
 
Index: include/ruby/debug.h
===================================================================
--- include/ruby/debug.h	(revision 38006)
+++ include/ruby/debug.h	(revision 38007)
@@ -38,8 +38,10 @@
 
 /* Old style set_trace_func APIs */
 
+/* duplicated def of include/ruby/ruby.h */
 void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
 int rb_remove_event_hook(rb_event_hook_func_t func);
+
 int rb_remove_event_hook_with_data(rb_event_hook_func_t func, VALUE data);
 void rb_thread_add_event_hook(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
 int rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 38006)
+++ ChangeLog	(revision 38007)
@@ -1,3 +1,28 @@
+Fri Nov 30 07:21:33 2012  Koichi Sasada  <ko1@a...>
+
+	[EXPERIMENTAL: NEED DISCUSS]
+	* vm_trace.c: add events
+	  * :thread_begin - hook at thread beggining.
+	  * :thead_end - hook at thread ending.
+	  * :b_call - hook at block enter.
+	  * :b_return - hook at block leave.
+	  This change slow down block invocation.
+	  Please try and give us feedback until 2.0 code freeze.
+
+	* include/ruby/ruby.h: ditto.
+
+	* compile.c (rb_iseq_compile_node): ditto.
+
+	* insns.def: ditto.
+
+	* thread.c: ditto.
+
+	* vm.c: ditto.
+
+	* include/ruby/debug.h: add a comment.
+
+	* test/ruby/test_settracefunc.rb: add a tests.
+
 Fri Nov 30 06:56:30 2012  Ryan Davis  <ryand-ruby@z...>
 
 	* test/minitest/*: Imported minitest 4.3.2 (r8027)
Index: insns.def
===================================================================
--- insns.def	(revision 38006)
+++ insns.def	(revision 38007)
@@ -871,8 +871,9 @@
                   rb_sourceline());
         }
     }
+
     EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* id and klass are resolved at callee */,
-		    flag & RUBY_EVENT_RETURN ? TOPN(0) : Qundef);
+		    (flag & RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN) ? TOPN(0) : Qundef);
 }
 
 /**********************************************************/
Index: compile.c
===================================================================
--- compile.c	(revision 38006)
+++ compile.c	(revision 38007)
@@ -475,31 +475,36 @@
 	iseq_set_arguments(iseq, ret, node->nd_args);
 
 	switch (iseq->type) {
-	  case ISEQ_TYPE_BLOCK: {
-	    LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0);
-	    LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0);
+	  case ISEQ_TYPE_BLOCK:
+	    {
+		LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0);
+		LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0);
 
-	    ADD_LABEL(ret, start);
-	    COMPILE(ret, "block body", node->nd_body);
-	    ADD_LABEL(ret, end);
+		ADD_LABEL(ret, start);
+		ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_B_CALL);
+		COMPILE(ret, "block body", node->nd_body);
+		ADD_TRACE(ret, nd_line(node), RUBY_EVENT_B_RETURN);
+		ADD_LABEL(ret, end);
 
-	    /* wide range catch handler must put at last */
-	    ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start);
-	    ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end);
-	    break;
-	  }
-	  case ISEQ_TYPE_CLASS: {
-	    ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CLASS);
-	    COMPILE(ret, "scoped node", node->nd_body);
-	    ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END);
-	    break;
-	  }
-	  case ISEQ_TYPE_METHOD: {
-	    ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CALL);
-	    COMPILE(ret, "scoped node", node->nd_body);
-	    ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN);
-	    break;
-	  }
+		/* wide range catch handler must put at last */
+		ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start);
+		ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end);
+		break;
+	    }
+	  case ISEQ_TYPE_CLASS:
+	    {
+		ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CLASS);
+		COMPILE(ret, "scoped node", node->nd_body);
+		ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END);
+		break;
+	    }
+	  case ISEQ_TYPE_METHOD:
+	    {
+		ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CALL);
+		COMPILE(ret, "scoped node", node->nd_body);
+		ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN);
+		break;
+	    }
 	  default: {
 	    COMPILE(ret, "scoped node", node->nd_body);
 	    break;
Index: thread.c
===================================================================
--- thread.c	(revision 38006)
+++ thread.c	(revision 38007)
@@ -478,8 +478,9 @@
 		    th->errinfo = Qnil;
 		    th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
 		    th->root_svar = Qnil;
-		    th->value = rb_vm_invoke_proc(th, proc,
-						  (int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
+		    EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_BEGIN, proc->block.self, 0, 0, th->self);
+		    th->value = rb_vm_invoke_proc(th, proc, (int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
+		    EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_END, proc->block.self, 0, 0, th->self);
 		}
 		else {
 		    th->value = (*th->first_func)((void *)args);
Index: vm_trace.c
===================================================================
--- vm_trace.c	(revision 38006)
+++ vm_trace.c	(revision 38007)
@@ -507,6 +507,10 @@
 	C(c_call, C_CALL);
 	C(c_return, C_RETURN);
 	C(raise, RAISE);
+	C(b_call, B_CALL);
+	C(b_return, B_RETURN);
+	C(thread_begin, THREAD_BEGIN);
+	C(thread_end, THREAD_END);
 #undef C
       default:
 	return 0;
@@ -610,6 +614,10 @@
     C(c_call, C_CALL);
     C(c_return, C_RETURN);
     C(raise, RAISE);
+    C(b_call, B_CALL);
+    C(b_return, B_RETURN);
+    C(thread_begin, THREAD_BEGIN);
+    C(thread_end, THREAD_END);
 #undef C
     rb_raise(rb_eArgError, "unknown event: %s", rb_id2name(SYM2ID(sym)));
 }
@@ -736,7 +744,7 @@
 VALUE
 rb_tracearg_return_value(rb_trace_arg_t *trace_arg)
 {
-    if (trace_arg->event & (RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN)) {
+    if (trace_arg->event & (RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN | RUBY_EVENT_B_RETURN)) {
 	/* ok */
     }
     else {
@@ -975,7 +983,7 @@
 	}
     }
     else {
-	events = RUBY_EVENT_ALL;
+	events = RUBY_EVENT_TRACEPOINT_ALL;
     }
 
     if (!rb_block_given_p()) {
Index: vm.c
===================================================================
--- vm.c	(revision 38006)
+++ vm.c	(revision 38007)
@@ -1353,6 +1353,9 @@
 		RUBY_DTRACE_METHOD_RETURN_HOOK(th, 0, 0)
 		EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, th->cfp->self, 0, 0, Qnil);
 		break;
+	      case VM_FRAME_MAGIC_BLOCK:
+		EXEC_EVENT_HOOK(th, RUBY_EVENT_B_RETURN, th->cfp->self, 0, 0, Qnil);
+		break;
 	      case VM_FRAME_MAGIC_CLASS:
 		EXEC_EVENT_HOOK(th, RUBY_EVENT_END, th->cfp->self, 0, 0, Qnil);
 		break;
Index: test/ruby/test_settracefunc.rb
===================================================================
--- test/ruby/test_settracefunc.rb	(revision 38006)
+++ test/ruby/test_settracefunc.rb	(revision 38007)
@@ -532,9 +532,14 @@
   end
 
   def test_tracepoint
-    events1, answer_events = *trace_by_tracepoint()
+    events1, answer_events = *trace_by_tracepoint(:line, :class, :end, :call, :return, :c_call, :c_return, :raise)
 
     mesg = events1.map{|e|
+      if false
+        p [:event, e[0]]
+        p [:line_file, e[1], e[2]]
+        p [:id, e[4]]
+      end
       "#{e[0]} - #{e[2]}:#{e[1]} id: #{e[4]}"
     }.join("\n")
     answer_events.zip(events1){|answer, event|
@@ -682,4 +687,54 @@
       end
     }
   end
+
+  def method_for_test_tracepoint_block
+    yield
+  end
+
+  def test_tracepoint_block
+    events = []
+    TracePoint.new(:call, :return, :c_call, :b_call, :c_return, :b_return){|tp|
+      events << [
+        tp.event, tp.method_id, tp.defined_class, tp.self.class,
+        /return/ =~ tp.event ? tp.return_value : nil
+      ]
+    }.enable{
+      1.times{
+        3
+      }
+      method_for_test_tracepoint_block{
+        4
+      }
+    }
+    # pp events
+    expected_events =
+    [[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
+     [:c_call, :times, Integer, Fixnum, nil],
+     [:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
+     [:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 3],
+     [:c_return, :times, Integer, Fixnum, 1],
+     [:call, :method_for_test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
+     [:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
+     [:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4],
+     [:return, :method_for_test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4],
+     [:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4]
+    ].zip(events){|expected, actual|
+      assert_equal(expected, actual)
+    }
+  end
+
+  def test_tracepoint_thread
+    events = []
+    created_thread = nil
+    TracePoint.new(:thread_begin, :thread_end){|tp|
+      events << [Thread.current, tp.event, tp.self]
+    }.enable{
+      created_thread = Thread.new{}
+      created_thread.join
+    }
+    assert_equal([created_thread, :thread_begin, self], events[0])
+    assert_equal([created_thread, :thread_end, self], events[1])
+    assert_equal(2, events.size)
+  end
 end

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

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