aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--iseq.c13
-rw-r--r--test/ruby/test_settracefunc.rb25
2 files changed, 33 insertions, 5 deletions
diff --git a/iseq.c b/iseq.c
index 36cbe1dc29..af782692be 100644
--- a/iseq.c
+++ b/iseq.c
@@ -3168,13 +3168,16 @@ rb_vm_insn_addr2insn(const void *addr)
}
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)
{
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,
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)
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)
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 9579974407..2caf71c000 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -2175,6 +2175,31 @@ class TestSetTraceFunc < Test::Unit::TestCase
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|