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

ruby-changes:63618

From: Koichi <ko1@a...>
Date: Tue, 17 Nov 2020 07:34:02 +0900 (JST)
Subject: [ruby-changes:63618] 084e7e31b2 (master): remain enabled and line specified trace points

https://git.ruby-lang.org/ruby.git/commit/?id=084e7e31b2

From 084e7e31b257f6ac859769553b4c1c6ca2930152 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Mon, 16 Nov 2020 16:40:04 +0900
Subject: remain enabled and line specified trace points

If two or more tracepoints enabled with the same target and with
different target lines, the only last line is activated.
This patch fixes this issue by remaining existing trace instructions.
[Bug #17302]

diff --git a/iseq.c b/iseq.c
index 36cbe1d..af78269 100644
--- a/iseq.c
+++ b/iseq.c
@@ -3168,13 +3168,16 @@ rb_vm_insn_addr2insn(const void *addr) https://github.com/ruby/ruby/blob/trunk/iseq.c#L3168
 }
 
 static inline int
-encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon)
+encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon, bool remain_current_trace)
 {
     st_data_t key = (st_data_t)*iseq_encoded_insn;
     st_data_t val;
 
     if (st_lookup(encoded_insn_data, key, &val)) {
         insn_data_t *e = (insn_data_t *)val;
+        if (remain_current_trace && key == (st_data_t)e->trace_encoded_insn) {
+            turnon = 1;
+        }
         *iseq_encoded_insn = (VALUE) (turnon ? e->trace_encoded_insn : e->notrace_encoded_insn);
         return e->insn_len;
     }
@@ -3187,7 +3190,7 @@ rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos) https://github.com/ruby/ruby/blob/trunk/iseq.c#L3190
 {
     const struct rb_iseq_constant_body *const body = iseq->body;
     VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
-    encoded_iseq_trace_instrument(&iseq_encoded[pos], 0);
+    encoded_iseq_trace_instrument(&iseq_encoded[pos], 0, false);
 }
 
 static int
@@ -3216,7 +3219,7 @@ iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, https://github.com/ruby/ruby/blob/trunk/iseq.c#L3219
         if (pc_events & target_events) {
             n++;
         }
-        pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events));
+        pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events), true);
     }
 
     if (n > 0) {
@@ -3281,7 +3284,7 @@ iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval) https://github.com/ruby/ruby/blob/trunk/iseq.c#L3284
 
         for (pc = 0; pc<body->iseq_size;) {
             rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc);
-            pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events));
+            pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events), false);
         }
     }
     return n;
@@ -3333,7 +3336,7 @@ rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events) https://github.com/ruby/ruby/blob/trunk/iseq.c#L3336
 
         for (pc=0; pc<body->iseq_size;) {
             rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc);
-            pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & enabled_events);
+            pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & enabled_events, true);
 	}
     }
 }
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 9579974..2caf71c 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -2175,6 +2175,31 @@ class TestSetTraceFunc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L2175
     assert_equal 'target_line is specified, but line event is not specified', e.message
   end
 
+  def test_tracepoint_enable_with_target_line_two_times
+    events = []
+    line_0 = __LINE__
+    code1 = proc{
+      events << 1 # tp1
+      events << 2
+      events << 3 # tp2
+    }
+
+    tp1 = TracePoint.new(:line) do |tp|
+      events << :tp1
+    end
+    tp2 = TracePoint.new(:line) do |tp|
+      events << :tp2
+    end
+
+    tp1.enable(target: code1, target_line: line_0 + 2) do
+      tp2.enable(target: code1, target_line: line_0 + 4) do
+        # two hooks
+        code1.call
+      end
+    end
+    assert_equal [:tp1, 1, 2, :tp2, 3], events
+  end
+
   def test_script_compiled
     events = []
     tp = TracePoint.new(:script_compiled){|tp|
-- 
cgit v0.10.2


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

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