diff options
-rw-r--r-- | iseq.c | 13 | ||||
-rw-r--r-- | test/ruby/test_settracefunc.rb | 25 |
2 files changed, 33 insertions, 5 deletions
@@ -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| |