Refactor the internal data format for coverage measurement
To prepare new measuring targets: branch and method coverages. So far, iseq->coverage was an array of counts executed for line coverage. Now, it is a three-element array for each measuring target, whose first element is an array for line coverage. The second element is planned for branch coverage, and the third will be for method coverage. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59738 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c10baca4ae
commit
cd6df5fb3c
@ -243,9 +243,10 @@ struct iseq_compile_data_ensure_node_stack {
|
|||||||
#define ADD_TRACE(seq, line, event) \
|
#define ADD_TRACE(seq, line, event) \
|
||||||
do { \
|
do { \
|
||||||
if ((event) == RUBY_EVENT_LINE && ISEQ_COVERAGE(iseq) && \
|
if ((event) == RUBY_EVENT_LINE && ISEQ_COVERAGE(iseq) && \
|
||||||
|
ISEQ_LINE_COVERAGE(iseq) && \
|
||||||
(line) > 0 && \
|
(line) > 0 && \
|
||||||
(line) != ISEQ_COMPILE_DATA(iseq)->last_coverable_line) { \
|
(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); \
|
ISEQ_COMPILE_DATA(iseq)->last_coverable_line = (line); \
|
||||||
ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
|
ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
|
||||||
} \
|
} \
|
||||||
|
@ -24,7 +24,7 @@ rb_coverage_start(VALUE klass)
|
|||||||
if (!RTEST(coverages)) {
|
if (!RTEST(coverages)) {
|
||||||
coverages = rb_hash_new();
|
coverages = rb_hash_new();
|
||||||
rb_obj_hide(coverages);
|
rb_obj_hide(coverages);
|
||||||
rb_set_coverages(coverages);
|
rb_set_coverages(coverages, COVERAGE_TARGET_LINES);
|
||||||
}
|
}
|
||||||
return Qnil;
|
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 path = (VALUE)key;
|
||||||
VALUE coverage = (VALUE)val;
|
VALUE coverage = (VALUE)val;
|
||||||
VALUE coverages = (VALUE)h;
|
VALUE coverages = (VALUE)h;
|
||||||
coverage = rb_ary_dup(coverage);
|
VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
|
||||||
rb_ary_freeze(coverage);
|
if (lines) {
|
||||||
rb_hash_aset(coverages, path, coverage);
|
lines = rb_ary_dup(lines);
|
||||||
|
rb_ary_freeze(lines);
|
||||||
|
}
|
||||||
|
rb_hash_aset(coverages, path, lines);
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1677,11 +1677,19 @@ VALUE rb_struct_lookup(VALUE s, VALUE idx);
|
|||||||
struct timeval rb_time_timeval(VALUE);
|
struct timeval rb_time_timeval(VALUE);
|
||||||
|
|
||||||
/* thread.c */
|
/* 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_obj_is_mutex(VALUE obj);
|
||||||
VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
|
VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
|
||||||
void rb_thread_execute_interrupts(VALUE th);
|
void rb_thread_execute_interrupts(VALUE th);
|
||||||
void rb_clear_trace_func(void);
|
void rb_clear_trace_func(void);
|
||||||
VALUE rb_get_coverages(void);
|
VALUE rb_get_coverages(void);
|
||||||
|
VALUE rb_default_coverage(int);
|
||||||
VALUE rb_thread_shield_new(void);
|
VALUE rb_thread_shield_new(void);
|
||||||
VALUE rb_thread_shield_wait(VALUE self);
|
VALUE rb_thread_shield_wait(VALUE self);
|
||||||
VALUE rb_thread_shield_release(VALUE self);
|
VALUE rb_thread_shield_release(VALUE self);
|
||||||
|
3
iseq.h
3
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(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_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))
|
#define ISEQ_FLIP_CNT(iseq) FIX2INT(RARRAY_AREF(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_FLIP_CNT))
|
||||||
|
|
||||||
|
9
parse.y
9
parse.y
@ -5237,9 +5237,12 @@ coverage(VALUE fname, int n)
|
|||||||
{
|
{
|
||||||
VALUE coverages = rb_get_coverages();
|
VALUE coverages = rb_get_coverages();
|
||||||
if (RTEST(coverages) && RBASIC(coverages)->klass == 0) {
|
if (RTEST(coverages) && RBASIC(coverages)->klass == 0) {
|
||||||
VALUE lines = n > 0 ? rb_ary_tmp_new_fill(n) : rb_ary_tmp_new(0);
|
VALUE coverage = rb_default_coverage(n);
|
||||||
rb_hash_aset(coverages, fname, lines);
|
VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
|
||||||
return lines;
|
|
||||||
|
rb_hash_aset(coverages, fname, coverage);
|
||||||
|
|
||||||
|
return lines == Qnil ? Qfalse : lines;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
46
thread.c
46
thread.c
@ -4090,13 +4090,17 @@ static int
|
|||||||
clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
|
clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
VALUE lines = (VALUE)val;
|
VALUE coverage = (VALUE)val;
|
||||||
|
VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
|
||||||
|
|
||||||
|
if (lines) {
|
||||||
for (i = 0; i < RARRAY_LEN(lines); i++) {
|
for (i = 0; i < RARRAY_LEN(lines); i++) {
|
||||||
if (RARRAY_AREF(lines, i) != Qnil) {
|
if (RARRAY_AREF(lines, i) != Qnil) {
|
||||||
RARRAY_ASET(lines, i, INT2FIX(0));
|
RARRAY_ASET(lines, i, INT2FIX(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ST_CONTINUE;
|
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);
|
VALUE coverage = rb_iseq_coverage(GET_THREAD()->ec.cfp->iseq);
|
||||||
if (RB_TYPE_P(coverage, T_ARRAY) && !RBASIC_CLASS(coverage)) {
|
if (RB_TYPE_P(coverage, T_ARRAY) && !RBASIC_CLASS(coverage)) {
|
||||||
|
VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
|
||||||
|
if (lines) {
|
||||||
long line = rb_sourceline() - 1;
|
long line = rb_sourceline() - 1;
|
||||||
long count;
|
long count;
|
||||||
VALUE num;
|
VALUE num;
|
||||||
if (line >= RARRAY_LEN(coverage)) { /* no longer tracked */
|
if (line >= RARRAY_LEN(lines)) { /* no longer tracked */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
num = RARRAY_AREF(coverage, line);
|
num = RARRAY_AREF(lines, line);
|
||||||
if (!FIXNUM_P(num)) return;
|
if (!FIXNUM_P(num)) return;
|
||||||
count = FIX2LONG(num) + 1;
|
count = FIX2LONG(num) + 1;
|
||||||
if (POSFIXABLE(count)) {
|
if (POSFIXABLE(count)) {
|
||||||
RARRAY_ASET(coverage, line, LONG2FIX(count));
|
RARRAY_ASET(lines, line, LONG2FIX(count));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4992,9 +4999,10 @@ rb_get_coverages(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_set_coverages(VALUE coverages)
|
rb_set_coverages(VALUE coverages, int mode)
|
||||||
{
|
{
|
||||||
GET_VM()->coverages = coverages;
|
GET_VM()->coverages = coverages;
|
||||||
|
GET_VM()->coverage_mode = mode;
|
||||||
rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
|
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)
|
reset_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
|
||||||
{
|
{
|
||||||
VALUE coverage = (VALUE)val;
|
VALUE coverage = (VALUE)val;
|
||||||
rb_ary_clear(coverage);
|
VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
|
||||||
|
rb_ary_clear(lines);
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5016,6 +5025,31 @@ rb_reset_coverages(void)
|
|||||||
rb_remove_event_hook(update_coverage);
|
rb_remove_event_hook(update_coverage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
VALUE
|
||||||
rb_uninterruptible(VALUE (*b_proc)(ANYARGS), VALUE data)
|
rb_uninterruptible(VALUE (*b_proc)(ANYARGS), VALUE data)
|
||||||
{
|
{
|
||||||
|
@ -566,6 +566,7 @@ typedef struct rb_vm_struct {
|
|||||||
|
|
||||||
VALUE verbose, debug, orig_progname, progname;
|
VALUE verbose, debug, orig_progname, progname;
|
||||||
VALUE coverages;
|
VALUE coverages;
|
||||||
|
int coverage_mode;
|
||||||
|
|
||||||
VALUE defined_module_hash;
|
VALUE defined_module_hash;
|
||||||
|
|
||||||
@ -1686,7 +1687,7 @@ RUBY_SYMBOL_EXPORT_BEGIN
|
|||||||
int rb_thread_check_trap_pending(void);
|
int rb_thread_check_trap_pending(void);
|
||||||
|
|
||||||
extern VALUE rb_get_coverages(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);
|
extern void rb_reset_coverages(void);
|
||||||
|
|
||||||
void rb_postponed_job_flush(rb_vm_t *vm);
|
void rb_postponed_job_flush(rb_vm_t *vm);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user