mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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]
This commit is contained in:
parent
1271782f9d
commit
084e7e31b2
Notes:
git
2020-11-17 07:34:08 +09:00
2 changed files with 33 additions and 5 deletions
13
iseq.c
13
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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|
|
||||
|
|
Loading…
Reference in a new issue