diff options
-rw-r--r-- | compile.c | 3 | ||||
-rw-r--r-- | ext/coverage/coverage.c | 11 | ||||
-rw-r--r-- | internal.h | 8 | ||||
-rw-r--r-- | iseq.h | 3 | ||||
-rw-r--r-- | parse.y | 9 | ||||
-rw-r--r-- | thread.c | 68 | ||||
-rw-r--r-- | vm_core.h | 3 |
7 files changed, 79 insertions, 26 deletions
@@ -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); @@ -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)) @@ -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; } @@ -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(); @@ -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); |