From 47ea999b4689fc591478a05da1670d2008a4a705 Mon Sep 17 00:00:00 2001 From: mame Date: Sat, 20 Oct 2018 05:33:04 +0000 Subject: ext/coverage/: add the oneshot mode This patch introduces "oneshot_lines" mode for `Coverage.start`, which checks "whether each line was executed at least once or not", instead of "how many times each line was executed". A hook for each line is fired at most once, and after it is fired, the hook flag was removed; it runs with zero overhead. See [Feature #15022] in detail. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65195 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- iseq.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'iseq.c') diff --git a/iseq.c b/iseq.c index 343fc9e5b8..243afc2534 100644 --- a/iseq.c +++ b/iseq.c @@ -656,7 +656,8 @@ rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath VALUE coverages = rb_get_coverages(); if (RTEST(coverages)) { if (ast->line_count >= 0) { - VALUE coverage = rb_default_coverage(ast->line_count); + int len = (rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES) ? 0 : ast->line_count; + VALUE coverage = rb_default_coverage(len); rb_hash_aset(coverages, path, coverage); } } @@ -1655,6 +1656,19 @@ rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos) } } +void +rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t reset) +{ + struct iseq_insn_info_entry *entry = (struct iseq_insn_info_entry *)get_insn_info(iseq, pos); + if (entry) { + entry->events &= ~reset; + if (!(entry->events & iseq->aux.trace_events)) { + void rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, int pos); + rb_iseq_trace_flag_cleared(iseq, pos); + } + } +} + static VALUE local_var_name(const rb_iseq_t *diseq, VALUE level, VALUE op) { @@ -2934,6 +2948,14 @@ encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon) rb_bug("trace_instrument: invalid insn address: %p", (void *)*iseq_encoded_insn); } +void +rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, int 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); +} + void rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events) { -- cgit v1.2.3