diff options
author | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-09-14 01:55:30 +0000 |
---|---|---|
committer | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-09-14 01:55:30 +0000 |
commit | d1b290d5ba8ef97beb1707dcf30665cb6bc43c16 (patch) | |
tree | 6c5844012dc4f566806730e5678c60386e2d4352 | |
parent | a4eedafb132deefd25fe8dc62b2305213b0bbed7 (diff) | |
download | ruby-d1b290d5ba8ef97beb1707dcf30665cb6bc43c16.tar.gz |
Add a new instruction `trace2` for hooking with custom data
This is needed for passing to the hook function the measuring target
type (line/branch/method) and the site of coverage event fired.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59871 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | compile.c | 13 | ||||
-rw-r--r-- | insns.def | 17 | ||||
-rw-r--r-- | thread.c | 38 |
3 files changed, 48 insertions, 20 deletions
@@ -240,16 +240,20 @@ struct iseq_compile_data_ensure_node_stack { #define ADD_SEND_R(seq, line, id, argc, block, flag, keywords) \ ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords))) -#define ADD_TRACE(seq, line, event) \ +#define ADD_TRACE_LINE_COVERAGE(seq, line) \ do { \ - if ((event) == RUBY_EVENT_LINE && ISEQ_COVERAGE(iseq) && \ + if (ISEQ_COVERAGE(iseq) && \ ISEQ_LINE_COVERAGE(iseq) && \ (line) > 0 && \ (line) != ISEQ_COMPILE_DATA(iseq)->last_coverable_line) { \ 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)); \ + ADD_INSN2((seq), (line), trace2, INT2FIX(RUBY_EVENT_COVERAGE), INT2FIX(COVERAGE_INDEX_LINES)); \ } \ + } while (0) + +#define ADD_TRACE(seq, line, event) \ + do { \ if (ISEQ_COMPILE_DATA(iseq)->option->trace_instruction) { \ ADD_INSN1((seq), (line), trace, INT2FIX(event)); \ } \ @@ -4844,6 +4848,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp else { if (node->flags & NODE_FL_NEWLINE) { ISEQ_COMPILE_DATA(iseq)->last_line = line; + ADD_TRACE_LINE_COVERAGE(ret, line); ADD_TRACE(ret, line, RUBY_EVENT_LINE); saved_last_element = ret->last; } @@ -6594,7 +6599,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp ((INSN *)saved_last_element)->insn_id == BIN(trace)) { POP_ELEMENT(ret); /* remove trace(coverage) */ - if (IS_INSN_ID(ret->last, trace) && + if (IS_INSN_ID(ret->last, trace2) && (FIX2LONG(OPERAND_AT(ret->last, 0)) & RUBY_EVENT_COVERAGE)) { POP_ELEMENT(ret); RARRAY_ASET(ISEQ_LINE_COVERAGE(iseq), line - 1, Qnil); @@ -732,6 +732,23 @@ trace (flag & (RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN)) ? TOPN(0) : Qundef); } +/** + @c setting + @e trace + @j trace 用の命令。 + */ +DEFINE_INSN +trace2 +(rb_num_t nf, VALUE data) +() +() +{ + rb_event_flag_t flag = (rb_event_flag_t)nf; + + vm_dtrace(flag, th); + EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0, 0 /* id and klass are resolved at callee */, data); +} + /**********************************************************/ /* deal with control flow 1: class/module */ /**********************************************************/ @@ -69,6 +69,7 @@ #include "ruby/io.h" #include "ruby/thread.h" #include "ruby/thread_native.h" +#include "ruby/debug.h" #include "internal.h" #ifndef USE_NATIVE_THREAD_PRIORITY @@ -4970,24 +4971,29 @@ rb_check_deadlock(rb_vm_t *vm) } static void -update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass) +update_coverage(VALUE data, const rb_trace_arg_t *trace_arg) { VALUE coverage = rb_iseq_coverage(GET_THREAD()->ec.cfp->iseq); 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 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)); + switch (FIX2INT(trace_arg->data)) { + case COVERAGE_INDEX_LINES: { + 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)); + } } + break; + } } } } @@ -5003,7 +5009,7 @@ 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); + rb_add_event_hook2((rb_event_hook_func_t) update_coverage, RUBY_EVENT_COVERAGE, Qnil, RUBY_EVENT_HOOK_FLAG_SAFE | RUBY_EVENT_HOOK_FLAG_RAW_ARG); } /* Make coverage arrays empty so old covered files are no longer tracked. */ @@ -5022,7 +5028,7 @@ rb_reset_coverages(void) VALUE coverages = rb_get_coverages(); st_foreach(rb_hash_tbl_raw(coverages), reset_coverage_i, 0); GET_VM()->coverages = Qfalse; - rb_remove_event_hook(update_coverage); + rb_remove_event_hook((rb_event_hook_func_t) update_coverage); } VALUE |