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
This commit is contained in:
parent
a4eedafb13
commit
d1b290d5ba
13
compile.c
13
compile.c
@ -240,16 +240,20 @@ struct iseq_compile_data_ensure_node_stack {
|
|||||||
#define ADD_SEND_R(seq, line, id, argc, block, flag, keywords) \
|
#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)))
|
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 { \
|
do { \
|
||||||
if ((event) == RUBY_EVENT_LINE && ISEQ_COVERAGE(iseq) && \
|
if (ISEQ_COVERAGE(iseq) && \
|
||||||
ISEQ_LINE_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_LINE_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_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) { \
|
if (ISEQ_COMPILE_DATA(iseq)->option->trace_instruction) { \
|
||||||
ADD_INSN1((seq), (line), trace, INT2FIX(event)); \
|
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 {
|
else {
|
||||||
if (node->flags & NODE_FL_NEWLINE) {
|
if (node->flags & NODE_FL_NEWLINE) {
|
||||||
ISEQ_COMPILE_DATA(iseq)->last_line = line;
|
ISEQ_COMPILE_DATA(iseq)->last_line = line;
|
||||||
|
ADD_TRACE_LINE_COVERAGE(ret, line);
|
||||||
ADD_TRACE(ret, line, RUBY_EVENT_LINE);
|
ADD_TRACE(ret, line, RUBY_EVENT_LINE);
|
||||||
saved_last_element = ret->last;
|
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)) {
|
((INSN *)saved_last_element)->insn_id == BIN(trace)) {
|
||||||
POP_ELEMENT(ret);
|
POP_ELEMENT(ret);
|
||||||
/* remove trace(coverage) */
|
/* 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)) {
|
(FIX2LONG(OPERAND_AT(ret->last, 0)) & RUBY_EVENT_COVERAGE)) {
|
||||||
POP_ELEMENT(ret);
|
POP_ELEMENT(ret);
|
||||||
RARRAY_ASET(ISEQ_LINE_COVERAGE(iseq), line - 1, Qnil);
|
RARRAY_ASET(ISEQ_LINE_COVERAGE(iseq), line - 1, Qnil);
|
||||||
|
17
insns.def
17
insns.def
@ -732,6 +732,23 @@ trace
|
|||||||
(flag & (RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN)) ? TOPN(0) : Qundef);
|
(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 */
|
/* deal with control flow 1: class/module */
|
||||||
/**********************************************************/
|
/**********************************************************/
|
||||||
|
38
thread.c
38
thread.c
@ -69,6 +69,7 @@
|
|||||||
#include "ruby/io.h"
|
#include "ruby/io.h"
|
||||||
#include "ruby/thread.h"
|
#include "ruby/thread.h"
|
||||||
#include "ruby/thread_native.h"
|
#include "ruby/thread_native.h"
|
||||||
|
#include "ruby/debug.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#ifndef USE_NATIVE_THREAD_PRIORITY
|
#ifndef USE_NATIVE_THREAD_PRIORITY
|
||||||
@ -4970,24 +4971,29 @@ rb_check_deadlock(rb_vm_t *vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
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);
|
switch (FIX2INT(trace_arg->data)) {
|
||||||
if (lines) {
|
case COVERAGE_INDEX_LINES: {
|
||||||
long line = rb_sourceline() - 1;
|
VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
|
||||||
long count;
|
if (lines) {
|
||||||
VALUE num;
|
long line = rb_sourceline() - 1;
|
||||||
if (line >= RARRAY_LEN(lines)) { /* no longer tracked */
|
long count;
|
||||||
return;
|
VALUE num;
|
||||||
}
|
if (line >= RARRAY_LEN(lines)) { /* no longer tracked */
|
||||||
num = RARRAY_AREF(lines, line);
|
return;
|
||||||
if (!FIXNUM_P(num)) return;
|
}
|
||||||
count = FIX2LONG(num) + 1;
|
num = RARRAY_AREF(lines, line);
|
||||||
if (POSFIXABLE(count)) {
|
if (!FIXNUM_P(num)) return;
|
||||||
RARRAY_ASET(lines, line, LONG2FIX(count));
|
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()->coverages = coverages;
|
||||||
GET_VM()->coverage_mode = mode;
|
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. */
|
/* 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();
|
VALUE coverages = rb_get_coverages();
|
||||||
st_foreach(rb_hash_tbl_raw(coverages), reset_coverage_i, 0);
|
st_foreach(rb_hash_tbl_raw(coverages), reset_coverage_i, 0);
|
||||||
GET_VM()->coverages = Qfalse;
|
GET_VM()->coverages = Qfalse;
|
||||||
rb_remove_event_hook(update_coverage);
|
rb_remove_event_hook((rb_event_hook_func_t) update_coverage);
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user