зеркало из https://github.com/github/ruby.git
vm_core.h (rb_iseq_locatoin_t): add a field `code_range`
This change makes each ISeq keep NODE's code range. This information is needed for method coverage. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61025 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
2d592329e0
Коммит
a5e02f249d
|
@ -8566,6 +8566,7 @@ ibf_load_iseq_each(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t of
|
||||||
RB_OBJ_WRITE(iseq, &load_body->location.base_label, ibf_load_location_str(load, body->location.base_label));
|
RB_OBJ_WRITE(iseq, &load_body->location.base_label, ibf_load_location_str(load, body->location.base_label));
|
||||||
RB_OBJ_WRITE(iseq, &load_body->location.label, ibf_load_location_str(load, body->location.label));
|
RB_OBJ_WRITE(iseq, &load_body->location.label, ibf_load_location_str(load, body->location.label));
|
||||||
load_body->location.first_lineno = body->location.first_lineno;
|
load_body->location.first_lineno = body->location.first_lineno;
|
||||||
|
load_body->location.code_range = body->location.code_range;
|
||||||
|
|
||||||
load_body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, body->is_size);
|
load_body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, body->is_size);
|
||||||
load_body->ci_entries = ibf_load_ci_entries(load, body);
|
load_body->ci_entries = ibf_load_ci_entries(load, body);
|
||||||
|
|
|
@ -129,7 +129,7 @@ method_coverage_i(void *vstart, void *vend, size_t stride, void *data)
|
||||||
if (RB_TYPE_P(v, T_IMEMO) && imemo_type(v) == imemo_ment) {
|
if (RB_TYPE_P(v, T_IMEMO) && imemo_type(v) == imemo_ment) {
|
||||||
const rb_method_entry_t *me = (rb_method_entry_t *) v;
|
const rb_method_entry_t *me = (rb_method_entry_t *) v;
|
||||||
VALUE path = Qundef, first_lineno = Qundef;
|
VALUE path = Qundef, first_lineno = Qundef;
|
||||||
VALUE data[2], ncoverage, methods;
|
VALUE data[5], ncoverage, methods;
|
||||||
VALUE methods_id = ID2SYM(rb_intern("methods"));
|
VALUE methods_id = ID2SYM(rb_intern("methods"));
|
||||||
VALUE klass;
|
VALUE klass;
|
||||||
const rb_method_entry_t *me2 = rb_resolve_me_location(me, data);
|
const rb_method_entry_t *me2 = rb_resolve_me_location(me, data);
|
||||||
|
|
39
iseq.c
39
iseq.c
|
@ -240,7 +240,7 @@ rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
static rb_iseq_location_t *
|
static rb_iseq_location_t *
|
||||||
iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno)
|
iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_range_t *code_range)
|
||||||
{
|
{
|
||||||
rb_iseq_location_t *loc = &iseq->body->location;
|
rb_iseq_location_t *loc = &iseq->body->location;
|
||||||
|
|
||||||
|
@ -248,6 +248,16 @@ iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VAL
|
||||||
RB_OBJ_WRITE(iseq, &loc->label, name);
|
RB_OBJ_WRITE(iseq, &loc->label, name);
|
||||||
RB_OBJ_WRITE(iseq, &loc->base_label, name);
|
RB_OBJ_WRITE(iseq, &loc->base_label, name);
|
||||||
loc->first_lineno = first_lineno;
|
loc->first_lineno = first_lineno;
|
||||||
|
if (code_range) {
|
||||||
|
loc->code_range = *code_range;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
loc->code_range.first_loc.lineno = 0;
|
||||||
|
loc->code_range.first_loc.column = 0;
|
||||||
|
loc->code_range.last_loc.lineno = -1;
|
||||||
|
loc->code_range.last_loc.column = -1;
|
||||||
|
}
|
||||||
|
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +295,7 @@ rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj)
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
prepare_iseq_build(rb_iseq_t *iseq,
|
prepare_iseq_build(rb_iseq_t *iseq,
|
||||||
VALUE name, VALUE path, VALUE realpath, VALUE first_lineno,
|
VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_range_t *code_range,
|
||||||
const rb_iseq_t *parent, enum iseq_type type,
|
const rb_iseq_t *parent, enum iseq_type type,
|
||||||
const rb_compile_option_t *option)
|
const rb_compile_option_t *option)
|
||||||
{
|
{
|
||||||
|
@ -299,7 +309,7 @@ prepare_iseq_build(rb_iseq_t *iseq,
|
||||||
set_relation(iseq, parent);
|
set_relation(iseq, parent);
|
||||||
|
|
||||||
name = rb_fstring(name);
|
name = rb_fstring(name);
|
||||||
iseq_location_setup(iseq, name, path, realpath, first_lineno);
|
iseq_location_setup(iseq, name, path, realpath, first_lineno, code_range);
|
||||||
if (iseq != iseq->body->local_iseq) {
|
if (iseq != iseq->body->local_iseq) {
|
||||||
RB_OBJ_WRITE(iseq, &iseq->body->location.base_label, iseq->body->local_iseq->body->location.label);
|
RB_OBJ_WRITE(iseq, &iseq->body->location.base_label, iseq->body->local_iseq->body->location.label);
|
||||||
}
|
}
|
||||||
|
@ -505,7 +515,7 @@ rb_iseq_new_with_opt(const NODE *node, VALUE name, VALUE path, VALUE realpath,
|
||||||
rb_iseq_t *iseq = iseq_alloc();
|
rb_iseq_t *iseq = iseq_alloc();
|
||||||
|
|
||||||
if (!option) option = &COMPILE_OPTION_DEFAULT;
|
if (!option) option = &COMPILE_OPTION_DEFAULT;
|
||||||
prepare_iseq_build(iseq, name, path, realpath, first_lineno, parent, type, option);
|
prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, parent, type, option);
|
||||||
|
|
||||||
rb_iseq_compile_node(iseq, node);
|
rb_iseq_compile_node(iseq, node);
|
||||||
finish_iseq_build(iseq);
|
finish_iseq_build(iseq);
|
||||||
|
@ -564,12 +574,13 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
|
||||||
rb_iseq_t *iseq = iseq_alloc();
|
rb_iseq_t *iseq = iseq_alloc();
|
||||||
|
|
||||||
VALUE magic, version1, version2, format_type, misc;
|
VALUE magic, version1, version2, format_type, misc;
|
||||||
VALUE name, path, realpath, first_lineno;
|
VALUE name, path, realpath, first_lineno, code_range;
|
||||||
VALUE type, body, locals, params, exception;
|
VALUE type, body, locals, params, exception;
|
||||||
|
|
||||||
st_data_t iseq_type;
|
st_data_t iseq_type;
|
||||||
rb_compile_option_t option;
|
rb_compile_option_t option;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
rb_code_range_t tmp_loc = { {0, 0}, {-1, -1} };
|
||||||
|
|
||||||
/* [magic, major_version, minor_version, format_type, misc,
|
/* [magic, major_version, minor_version, format_type, misc,
|
||||||
* label, path, first_lineno,
|
* label, path, first_lineno,
|
||||||
|
@ -604,9 +615,17 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
|
||||||
rb_raise(rb_eTypeError, "unsupport type: :%"PRIsVALUE, rb_sym2str(type));
|
rb_raise(rb_eTypeError, "unsupport type: :%"PRIsVALUE, rb_sym2str(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code_range = rb_hash_aref(misc, ID2SYM(rb_intern("code_range")));
|
||||||
|
if (RB_TYPE_P(code_range, T_ARRAY) && RARRAY_LEN(code_range) == 4) {
|
||||||
|
tmp_loc.first_loc.lineno = NUM2LONG(rb_ary_entry(code_range, 0));
|
||||||
|
tmp_loc.first_loc.column = NUM2LONG(rb_ary_entry(code_range, 1));
|
||||||
|
tmp_loc.last_loc.lineno = NUM2LONG(rb_ary_entry(code_range, 2));
|
||||||
|
tmp_loc.last_loc.column = NUM2LONG(rb_ary_entry(code_range, 3));
|
||||||
|
}
|
||||||
|
|
||||||
make_compile_option(&option, opt);
|
make_compile_option(&option, opt);
|
||||||
option.peephole_optimization = FALSE; /* because peephole optimization can modify original iseq */
|
option.peephole_optimization = FALSE; /* because peephole optimization can modify original iseq */
|
||||||
prepare_iseq_build(iseq, name, path, realpath, first_lineno,
|
prepare_iseq_build(iseq, name, path, realpath, first_lineno, &tmp_loc,
|
||||||
parent, (enum iseq_type)iseq_type, &option);
|
parent, (enum iseq_type)iseq_type, &option);
|
||||||
|
|
||||||
rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body);
|
rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body);
|
||||||
|
@ -2161,6 +2180,12 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
|
||||||
rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(iseq->body->param.size));
|
rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(iseq->body->param.size));
|
||||||
rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq->body->local_table_size));
|
rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq->body->local_table_size));
|
||||||
rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq->body->stack_max));
|
rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq->body->stack_max));
|
||||||
|
rb_hash_aset(misc, ID2SYM(rb_intern("code_range")),
|
||||||
|
rb_ary_new_from_args(4,
|
||||||
|
LONG2FIX(iseq->body->location.code_range.first_loc.lineno),
|
||||||
|
LONG2FIX(iseq->body->location.code_range.first_loc.column),
|
||||||
|
LONG2FIX(iseq->body->location.code_range.last_loc.lineno),
|
||||||
|
LONG2FIX(iseq->body->location.code_range.last_loc.column)));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [:magic, :major_version, :minor_version, :format_type, :misc,
|
* [:magic, :major_version, :minor_version, :format_type, :misc,
|
||||||
|
@ -2499,8 +2524,8 @@ Init_ISeq(void)
|
||||||
rb_define_private_method(rb_cISeq, "marshal_dump", iseqw_marshal_dump, 0);
|
rb_define_private_method(rb_cISeq, "marshal_dump", iseqw_marshal_dump, 0);
|
||||||
rb_define_private_method(rb_cISeq, "marshal_load", iseqw_marshal_load, 1);
|
rb_define_private_method(rb_cISeq, "marshal_load", iseqw_marshal_load, 1);
|
||||||
/* disable this feature because there is no verifier. */
|
/* disable this feature because there is no verifier. */
|
||||||
rb_define_singleton_method(rb_cISeq, "load", iseq_s_load, -1);
|
|
||||||
#endif
|
#endif
|
||||||
|
rb_define_singleton_method(rb_cISeq, "load", iseq_s_load, -1);
|
||||||
(void)iseq_s_load;
|
(void)iseq_s_load;
|
||||||
|
|
||||||
rb_define_singleton_method(rb_cISeq, "compile", iseqw_s_compile, -1);
|
rb_define_singleton_method(rb_cISeq, "compile", iseqw_s_compile, -1);
|
||||||
|
|
2
method.h
2
method.h
|
@ -191,7 +191,7 @@ const rb_method_entry_t *rb_method_entry(VALUE klass, ID id);
|
||||||
const rb_method_entry_t *rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class);
|
const rb_method_entry_t *rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class);
|
||||||
const rb_method_entry_t *rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
|
const rb_method_entry_t *rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
|
||||||
RUBY_SYMBOL_EXPORT_BEGIN
|
RUBY_SYMBOL_EXPORT_BEGIN
|
||||||
const rb_method_entry_t *rb_resolve_me_location(const rb_method_entry_t *, VALUE[2]);
|
const rb_method_entry_t *rb_resolve_me_location(const rb_method_entry_t *, VALUE[5]);
|
||||||
RUBY_SYMBOL_EXPORT_END
|
RUBY_SYMBOL_EXPORT_END
|
||||||
|
|
||||||
const rb_callable_method_entry_t *rb_callable_method_entry(VALUE klass, ID id);
|
const rb_callable_method_entry_t *rb_callable_method_entry(VALUE klass, ID id);
|
||||||
|
|
24
thread.c
24
thread.c
|
@ -5019,24 +5019,33 @@ update_coverage(VALUE data, const rb_trace_arg_t *trace_arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rb_method_entry_t *
|
const rb_method_entry_t *
|
||||||
rb_resolve_me_location(const rb_method_entry_t *me, VALUE resolved_location[2])
|
rb_resolve_me_location(const rb_method_entry_t *me, VALUE resolved_location[5])
|
||||||
{
|
{
|
||||||
VALUE path, first_lineno;
|
VALUE path, first_lineno, first_column, last_lineno, last_column;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
switch (me->def->type) {
|
switch (me->def->type) {
|
||||||
case VM_METHOD_TYPE_ISEQ: {
|
case VM_METHOD_TYPE_ISEQ: {
|
||||||
rb_iseq_location_t loc = me->def->body.iseq.iseqptr->body->location;
|
const rb_iseq_t *iseq = me->def->body.iseq.iseqptr;
|
||||||
path = loc.pathobj;
|
rb_iseq_location_t *loc = &iseq->body->location;
|
||||||
first_lineno = loc.first_lineno;
|
path = rb_iseq_path(iseq);
|
||||||
|
first_lineno = INT2FIX(loc->code_range.first_loc.lineno);
|
||||||
|
first_column = INT2FIX(loc->code_range.first_loc.column);
|
||||||
|
last_lineno = INT2FIX(loc->code_range.last_loc.lineno);
|
||||||
|
last_column = INT2FIX(loc->code_range.last_loc.column);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VM_METHOD_TYPE_BMETHOD: {
|
case VM_METHOD_TYPE_BMETHOD: {
|
||||||
const rb_iseq_t *iseq = rb_proc_get_iseq(me->def->body.proc, 0);
|
const rb_iseq_t *iseq = rb_proc_get_iseq(me->def->body.proc, 0);
|
||||||
if (iseq) {
|
if (iseq) {
|
||||||
|
rb_iseq_location_t *loc;
|
||||||
rb_iseq_check(iseq);
|
rb_iseq_check(iseq);
|
||||||
path = rb_iseq_path(iseq);
|
path = rb_iseq_path(iseq);
|
||||||
first_lineno = iseq->body->location.first_lineno;
|
loc = &iseq->body->location;
|
||||||
|
first_lineno = INT2FIX(loc->code_range.first_loc.lineno);
|
||||||
|
first_column = INT2FIX(loc->code_range.first_loc.column);
|
||||||
|
last_lineno = INT2FIX(loc->code_range.last_loc.lineno);
|
||||||
|
last_column = INT2FIX(loc->code_range.last_loc.column);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -5060,6 +5069,9 @@ rb_resolve_me_location(const rb_method_entry_t *me, VALUE resolved_location[2])
|
||||||
if (resolved_location) {
|
if (resolved_location) {
|
||||||
resolved_location[0] = path;
|
resolved_location[0] = path;
|
||||||
resolved_location[1] = first_lineno;
|
resolved_location[1] = first_lineno;
|
||||||
|
resolved_location[2] = first_column;
|
||||||
|
resolved_location[3] = last_lineno;
|
||||||
|
resolved_location[4] = last_column;
|
||||||
}
|
}
|
||||||
return me;
|
return me;
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,6 +252,7 @@ typedef struct rb_iseq_location_struct {
|
||||||
VALUE base_label; /* String */
|
VALUE base_label; /* String */
|
||||||
VALUE label; /* String */
|
VALUE label; /* String */
|
||||||
VALUE first_lineno; /* TODO: may be unsigned short */
|
VALUE first_lineno; /* TODO: may be unsigned short */
|
||||||
|
rb_code_range_t code_range;
|
||||||
} rb_iseq_location_t;
|
} rb_iseq_location_t;
|
||||||
|
|
||||||
#define PATHOBJ_PATH 0
|
#define PATHOBJ_PATH 0
|
||||||
|
|
Загрузка…
Ссылка в новой задаче