From f08581c7b6cfeb3c843257385e9c2611cd473806 Mon Sep 17 00:00:00 2001 From: mame Date: Thu, 3 Jul 2008 12:55:12 +0000 Subject: * ext/coverage/coverage.c, ext/coverage/extconf.rb: eliminate COVERAGE__ and introduce coverage.so instead. How to measure coverage: (1) require "coverage.so", (2) require or load Ruby source file, and (3) Coverage.result will return the same hash as COVERAGE__. [ruby-dev:35324] * thread.c (rb_enable_coverages): start coverage measurement by using rb_add_event_hook. * thread.c (rb_get_coverages): returns current results of coverage measurement. * include/ruby/intern.h: add prototype for above two functions. * vm_core.h, vm.c: add field of coverages to rb_vm_t. * insns.def (trace): remove special handling for COVERAGE__. * iseq.c (prepare_iseq_build): switch COVERAGE__ to rb_get_coverages(). * parse.y (coverage): ditto. * thread.c (clear_coverage): ditto. * lib/coverage.rb: use coverage.so instead of COVERAGE__. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17857 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 29 +++++++++++++++++++++++++++++ ext/coverage/coverage.c | 11 +++++++++++ ext/coverage/extconf.rb | 2 ++ include/ruby/intern.h | 2 ++ insns.def | 18 +----------------- iseq.c | 10 ++++------ lib/coverage.rb | 5 +++-- parse.y | 20 +++++++++----------- thread.c | 41 ++++++++++++++++++++++++++++++++++++----- vm.c | 1 + vm_core.h | 1 + 11 files changed, 99 insertions(+), 41 deletions(-) create mode 100644 ext/coverage/coverage.c create mode 100644 ext/coverage/extconf.rb diff --git a/ChangeLog b/ChangeLog index 721ad4b9d8..c1835d4b93 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +Thu Jul 3 21:51:21 2008 Yusuke Endoh + + * ext/coverage/coverage.c, ext/coverage/extconf.rb: eliminate + COVERAGE__ and introduce coverage.so instead. How to measure + coverage: (1) require "coverage.so", (2) require or load Ruby source + file, and (3) Coverage.result will return the same hash as COVERAGE__. + [ruby-dev:35324] + + * thread.c (rb_enable_coverages): start coverage measurement by using + rb_add_event_hook. + + * thread.c (rb_get_coverages): returns current results of coverage + measurement. + + * include/ruby/intern.h: add prototype for above two functions. + + * vm_core.h, vm.c: add field of coverages to rb_vm_t. + + * insns.def (trace): remove special handling for COVERAGE__. + + * iseq.c (prepare_iseq_build): switch COVERAGE__ to + rb_get_coverages(). + + * parse.y (coverage): ditto. + + * thread.c (clear_coverage): ditto. + + * lib/coverage.rb: use coverage.so instead of COVERAGE__. + Thu Jul 3 21:20:45 2008 Yusuke Endoh * thread.c (thread_initialize): NUM2INT returns long. diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c new file mode 100644 index 0000000000..a56a408665 --- /dev/null +++ b/ext/coverage/coverage.c @@ -0,0 +1,11 @@ +#include "ruby.h" + +VALUE rb_mCoverage; + +void +Init_coverage(void) +{ + rb_enable_coverages(); + rb_mCoverage = rb_define_module("Coverage"); + rb_define_module_function(rb_mCoverage, "result", rb_get_coverages, 0); +} diff --git a/ext/coverage/extconf.rb b/ext/coverage/extconf.rb new file mode 100644 index 0000000000..3ebced54a6 --- /dev/null +++ b/ext/coverage/extconf.rb @@ -0,0 +1,2 @@ +require 'mkmf' +create_makefile('coverage') diff --git a/include/ruby/intern.h b/include/ruby/intern.h index f1d47f654e..c80382b97b 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -626,6 +626,8 @@ VALUE rb_mutex_synchronize(VALUE self); VALUE rb_barrier_new(void); VALUE rb_barrier_wait(VALUE self); VALUE rb_barrier_release(VALUE self); +VALUE rb_get_coverages(void); +void rb_enable_coverages(void); /* time.c */ VALUE rb_time_new(time_t, long); VALUE rb_time_nano_new(time_t, long); diff --git a/insns.def b/insns.def index e378260c4b..62490f248f 100644 --- a/insns.def +++ b/insns.def @@ -853,23 +853,7 @@ trace { rb_event_flag_t flag = nf; - if (flag == RUBY_EVENT_COVERAGE) { - VALUE coverage = GET_ISEQ()->coverage; - if (coverage) { - long line = vm_get_sourceline(GET_CFP()) - 1; - long count; - if (RARRAY_PTR(coverage)[line] == Qnil) { - rb_bug("bug"); - } - count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1; - if (POSFIXABLE(count)) { - RARRAY_PTR(coverage)[line] = LONG2FIX(count); - } - } - } - else { - EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */); - } + EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */); } /**********************************************************/ diff --git a/iseq.c b/iseq.c index 8339073eb9..eb8a4009fd 100644 --- a/iseq.c +++ b/iseq.c @@ -194,12 +194,10 @@ prepare_iseq_build(rb_iseq_t *iseq, iseq->coverage = Qfalse; if (!GET_THREAD()->parse_in_eval) { - if (rb_const_defined_at(rb_cObject, rb_intern("COVERAGE__"))) { - VALUE hash = rb_const_get_at(rb_cObject, rb_intern("COVERAGE__")); - if (TYPE(hash) == T_HASH) { - iseq->coverage = rb_hash_aref(hash, filename); - if (NIL_P(iseq->coverage)) iseq->coverage = Qfalse; - } + VALUE coverages = rb_get_coverages(); + if (RTEST(coverages)) { + iseq->coverage = rb_hash_aref(coverages, filename); + if (NIL_P(iseq->coverage)) iseq->coverage = Qfalse; } } diff --git a/lib/coverage.rb b/lib/coverage.rb index f72473ece3..1a405355ff 100644 --- a/lib/coverage.rb +++ b/lib/coverage.rb @@ -1,4 +1,5 @@ -COVERAGE__ ||= {} +require "coverage.so" + ext = ENV["COVERUBY_EXT"] || ".cov" accum = ENV["COVERUBY_ACCUM"] accum = !accum || accum == "" || !(%w(f n 0).include?(accum[0])) @@ -6,7 +7,7 @@ pwd = Dir.pwd at_exit do Dir.chdir(pwd) do - COVERAGE__.each do |sfile, covs| + Coverage.result.each do |sfile, covs| cfile = sfile + ext writable = proc do |f| diff --git a/parse.y b/parse.y index 54d728a1d0..4d181af861 100644 --- a/parse.y +++ b/parse.y @@ -4672,17 +4672,15 @@ debug_lines(const char *f) static VALUE coverage(const char *f, int n) { - if (rb_const_defined_at(rb_cObject, rb_intern("COVERAGE__"))) { - VALUE hash = rb_const_get_at(rb_cObject, rb_intern("COVERAGE__")); - if (TYPE(hash) == T_HASH) { - VALUE fname = rb_str_new2(f); - VALUE lines = rb_ary_new2(n); - int i; - for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil; - RARRAY(lines)->len = n; - rb_hash_aset(hash, fname, lines); - return lines; - } + VALUE coverages = rb_get_coverages(); + if (RTEST(coverages)) { + VALUE fname = rb_str_new2(f); + VALUE lines = rb_ary_new2(n); + int i; + for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil; + RARRAY(lines)->len = n; + rb_hash_aset(coverages, fname, lines); + return lines; } return 0; } diff --git a/thread.c b/thread.c index 432a91d331..36af5af49d 100644 --- a/thread.c +++ b/thread.c @@ -2116,11 +2116,9 @@ clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy) static void clear_coverage(void) { - if (rb_const_defined_at(rb_cObject, rb_intern("COVERAGE__"))) { - VALUE hash = rb_const_get_at(rb_cObject, rb_intern("COVERAGE__")); - if (TYPE(hash) == T_HASH) { - st_foreach(RHASH_TBL(hash), clear_coverage_i, 0); - } + VALUE coverages = rb_get_coverages(); + if (RTEST(coverages)) { + st_foreach(RHASH_TBL(coverages), clear_coverage_i, 0); } } @@ -3530,3 +3528,36 @@ rb_check_deadlock(rb_vm_t *vm) rb_thread_raise(2, argv, vm->main_thread); } } + +VALUE +rb_get_coverages(void) +{ + return GET_VM()->coverages; +} + +static void +update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass) +{ + rb_control_frame_t *cfp = GET_THREAD()->cfp; + VALUE coverage = cfp->iseq->coverage; + if (coverage) { + long line = vm_get_sourceline(cfp) - 1; + long count; + if (RARRAY_PTR(coverage)[line] == Qnil) { + rb_bug("bug"); + } + count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1; + if (POSFIXABLE(count)) { + RARRAY_PTR(coverage)[line] = LONG2FIX(count); + } + } +} + +void +rb_enable_coverages(void) +{ + if (!RTEST(GET_VM()->coverages)) { + GET_VM()->coverages = rb_hash_new(); + rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil); + } +} diff --git a/vm.c b/vm.c index 793b9fd30a..519c4aba6e 100644 --- a/vm.c +++ b/vm.c @@ -1395,6 +1395,7 @@ rb_vm_mark(void *ptr) RUBY_MARK_UNLESS_NULL(vm->load_path); RUBY_MARK_UNLESS_NULL(vm->loaded_features); RUBY_MARK_UNLESS_NULL(vm->top_self); + RUBY_MARK_UNLESS_NULL(vm->coverages); rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count - 1); if (vm->loading_table) { diff --git a/vm_core.h b/vm_core.h index 700c33f224..f605445604 100644 --- a/vm_core.h +++ b/vm_core.h @@ -333,6 +333,7 @@ struct rb_vm_struct int src_encoding_index; VALUE verbose, debug, progname; + VALUE coverages; #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE struct rb_objspace *objspace; -- cgit v1.2.3