aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compile.c3
-rw-r--r--ext/coverage/coverage.c11
-rw-r--r--internal.h8
-rw-r--r--iseq.h3
-rw-r--r--parse.y9
-rw-r--r--thread.c68
-rw-r--r--vm_core.h3
7 files changed, 79 insertions, 26 deletions
diff --git a/compile.c b/compile.c
index 05dcfa8fec..23816a6cfd 100644
--- a/compile.c
+++ b/compile.c
@@ -243,9 +243,10 @@ struct iseq_compile_data_ensure_node_stack {
#define ADD_TRACE(seq, line, event) \
do { \
if ((event) == RUBY_EVENT_LINE && ISEQ_COVERAGE(iseq) && \
+ ISEQ_LINE_COVERAGE(iseq) && \
(line) > 0 && \
(line) != ISEQ_COMPILE_DATA(iseq)->last_coverable_line) { \
- RARRAY_ASET(ISEQ_COVERAGE(iseq), (line) - 1, INT2FIX(0)); \
+ RARRAY_ASET(ISEQ_LINE_COVERAGE(iseq), (line) - 1, INT2FIX(0)); \
ISEQ_COMPILE_DATA(iseq)->last_coverable_line = (line); \
ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
} \
diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c
index d2077a969e..643c2455db 100644
--- a/ext/coverage/coverage.c
+++ b/ext/coverage/coverage.c
@@ -24,7 +24,7 @@ rb_coverage_start(VALUE klass)
if (!RTEST(coverages)) {
coverages = rb_hash_new();
rb_obj_hide(coverages);
- rb_set_coverages(coverages);
+ rb_set_coverages(coverages, COVERAGE_TARGET_LINES);
}
return Qnil;
}
@@ -35,9 +35,12 @@ coverage_peek_result_i(st_data_t key, st_data_t val, st_data_t h)
VALUE path = (VALUE)key;
VALUE coverage = (VALUE)val;
VALUE coverages = (VALUE)h;
- coverage = rb_ary_dup(coverage);
- rb_ary_freeze(coverage);
- rb_hash_aset(coverages, path, coverage);
+ VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
+ if (lines) {
+ lines = rb_ary_dup(lines);
+ rb_ary_freeze(lines);
+ }
+ rb_hash_aset(coverages, path, lines);
return ST_CONTINUE;
}
diff --git a/internal.h b/internal.h
index 895b482d82..6b13725caf 100644
--- a/internal.h
+++ b/internal.h
@@ -1677,11 +1677,19 @@ VALUE rb_struct_lookup(VALUE s, VALUE idx);
struct timeval rb_time_timeval(VALUE);
/* thread.c */
+#define COVERAGE_INDEX_LINES 0
+#define COVERAGE_INDEX_BRANCHES 1
+#define COVERAGE_INDEX_METHODS 2
+#define COVERAGE_TARGET_LINES 1
+#define COVERAGE_TARGET_BRANCHES 2
+#define COVERAGE_TARGET_METHODS 4
+
VALUE rb_obj_is_mutex(VALUE obj);
VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
void rb_thread_execute_interrupts(VALUE th);
void rb_clear_trace_func(void);
VALUE rb_get_coverages(void);
+VALUE rb_default_coverage(int);
VALUE rb_thread_shield_new(void);
VALUE rb_thread_shield_wait(VALUE self);
VALUE rb_thread_shield_release(VALUE self);
diff --git a/iseq.h b/iseq.h
index b47b16aded..752fa838d8 100644
--- a/iseq.h
+++ b/iseq.h
@@ -47,6 +47,9 @@ iseq_mark_ary_create(int flip_cnt)
#define ISEQ_COVERAGE(iseq) RARRAY_AREF(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_COVERAGE)
#define ISEQ_COVERAGE_SET(iseq, cov) RARRAY_ASET(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_COVERAGE, cov)
+#define ISEQ_LINE_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_LINES)
+#define ISEQ_BRANCH_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_BRANCHES)
+#define ISEQ_METHOD_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_METHODS)
#define ISEQ_FLIP_CNT(iseq) FIX2INT(RARRAY_AREF(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_FLIP_CNT))
diff --git a/parse.y b/parse.y
index 14b5e9e3e9..985e9beb7e 100644
--- a/parse.y
+++ b/parse.y
@@ -5237,9 +5237,12 @@ coverage(VALUE fname, int n)
{
VALUE coverages = rb_get_coverages();
if (RTEST(coverages) && RBASIC(coverages)->klass == 0) {
- VALUE lines = n > 0 ? rb_ary_tmp_new_fill(n) : rb_ary_tmp_new(0);
- rb_hash_aset(coverages, fname, lines);
- return lines;
+ VALUE coverage = rb_default_coverage(n);
+ VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
+
+ rb_hash_aset(coverages, fname, coverage);
+
+ return lines == Qnil ? Qfalse : lines;
}
return 0;
}
diff --git a/thread.c b/thread.c
index 2e0713e54f..766b3d4100 100644
--- a/thread.c
+++ b/thread.c
@@ -4090,13 +4090,17 @@ static int
clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
{
int i;
- VALUE lines = (VALUE)val;
+ VALUE coverage = (VALUE)val;
+ VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
- for (i = 0; i < RARRAY_LEN(lines); i++) {
- if (RARRAY_AREF(lines, i) != Qnil) {
- RARRAY_ASET(lines, i, INT2FIX(0));
+ if (lines) {
+ for (i = 0; i < RARRAY_LEN(lines); i++) {
+ if (RARRAY_AREF(lines, i) != Qnil) {
+ RARRAY_ASET(lines, i, INT2FIX(0));
+ }
}
}
+
return ST_CONTINUE;
}
@@ -4970,17 +4974,20 @@ update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klas
{
VALUE coverage = rb_iseq_coverage(GET_THREAD()->ec.cfp->iseq);
if (RB_TYPE_P(coverage, T_ARRAY) && !RBASIC_CLASS(coverage)) {
- long line = rb_sourceline() - 1;
- long count;
- VALUE num;
- if (line >= RARRAY_LEN(coverage)) { /* no longer tracked */
- return;
- }
- num = RARRAY_AREF(coverage, line);
- if (!FIXNUM_P(num)) return;
- count = FIX2LONG(num) + 1;
- if (POSFIXABLE(count)) {
- RARRAY_ASET(coverage, line, LONG2FIX(count));
+ VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
+ if (lines) {
+ long line = rb_sourceline() - 1;
+ long count;
+ VALUE num;
+ if (line >= RARRAY_LEN(lines)) { /* no longer tracked */
+ return;
+ }
+ num = RARRAY_AREF(lines, line);
+ if (!FIXNUM_P(num)) return;
+ count = FIX2LONG(num) + 1;
+ if (POSFIXABLE(count)) {
+ RARRAY_ASET(lines, line, LONG2FIX(count));
+ }
}
}
}
@@ -4992,9 +4999,10 @@ rb_get_coverages(void)
}
void
-rb_set_coverages(VALUE coverages)
+rb_set_coverages(VALUE coverages, int mode)
{
GET_VM()->coverages = coverages;
+ GET_VM()->coverage_mode = mode;
rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
}
@@ -5003,7 +5011,8 @@ static int
reset_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
{
VALUE coverage = (VALUE)val;
- rb_ary_clear(coverage);
+ VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
+ rb_ary_clear(lines);
return ST_CONTINUE;
}
@@ -5017,6 +5026,31 @@ rb_reset_coverages(void)
}
VALUE
+rb_default_coverage(int n)
+{
+ VALUE coverage = rb_ary_tmp_new_fill(3);
+ VALUE lines = Qfalse, branches = Qfalse, methods = Qfalse;
+ int mode = GET_VM()->coverage_mode;
+
+ if (mode & COVERAGE_TARGET_LINES) {
+ lines = n > 0 ? rb_ary_tmp_new_fill(n) : rb_ary_tmp_new(0);
+ }
+ RARRAY_ASET(coverage, COVERAGE_INDEX_LINES, lines);
+
+ if (mode & COVERAGE_TARGET_BRANCHES) {
+ /* not implemented yet */
+ }
+ RARRAY_ASET(coverage, COVERAGE_INDEX_BRANCHES, branches);
+
+ if (mode & COVERAGE_TARGET_METHODS) {
+ /* not implemented yet */
+ }
+ RARRAY_ASET(coverage, COVERAGE_INDEX_METHODS, methods);
+
+ return coverage;
+}
+
+VALUE
rb_uninterruptible(VALUE (*b_proc)(ANYARGS), VALUE data)
{
VALUE interrupt_mask = rb_ident_hash_new();
diff --git a/vm_core.h b/vm_core.h
index 0105488f60..0c25ff74e6 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -566,6 +566,7 @@ typedef struct rb_vm_struct {
VALUE verbose, debug, orig_progname, progname;
VALUE coverages;
+ int coverage_mode;
VALUE defined_module_hash;
@@ -1686,7 +1687,7 @@ RUBY_SYMBOL_EXPORT_BEGIN
int rb_thread_check_trap_pending(void);
extern VALUE rb_get_coverages(void);
-extern void rb_set_coverages(VALUE);
+extern void rb_set_coverages(VALUE, int);
extern void rb_reset_coverages(void);
void rb_postponed_job_flush(rb_vm_t *vm);