ruby-changes:48907
From: mame <ko1@a...>
Date: Tue, 5 Dec 2017 17:56:54 +0900 (JST)
Subject: [ruby-changes:48907] mame:r61025 (trunk): vm_core.h (rb_iseq_locatoin_t): add a field `code_range`
mame 2017-12-05 17:56:50 +0900 (Tue, 05 Dec 2017) New Revision: 61025 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61025 Log: 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. Modified files: trunk/compile.c trunk/ext/coverage/coverage.c trunk/iseq.c trunk/method.h trunk/thread.c trunk/vm_core.h Index: method.h =================================================================== --- method.h (revision 61024) +++ method.h (revision 61025) @@ -191,7 +191,7 @@ const rb_method_entry_t *rb_method_entry https://github.com/ruby/ruby/blob/trunk/method.h#L191 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); 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 const rb_callable_method_entry_t *rb_callable_method_entry(VALUE klass, ID id); Index: vm_core.h =================================================================== --- vm_core.h (revision 61024) +++ vm_core.h (revision 61025) @@ -252,6 +252,7 @@ typedef struct rb_iseq_location_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L252 VALUE base_label; /* String */ VALUE label; /* String */ VALUE first_lineno; /* TODO: may be unsigned short */ + rb_code_range_t code_range; } rb_iseq_location_t; #define PATHOBJ_PATH 0 Index: iseq.c =================================================================== --- iseq.c (revision 61024) +++ iseq.c (revision 61025) @@ -240,7 +240,7 @@ rb_iseq_pathobj_set(const rb_iseq_t *ise https://github.com/ruby/ruby/blob/trunk/iseq.c#L240 } 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; @@ -248,6 +248,16 @@ iseq_location_setup(rb_iseq_t *iseq, VAL https://github.com/ruby/ruby/blob/trunk/iseq.c#L248 RB_OBJ_WRITE(iseq, &loc->label, name); RB_OBJ_WRITE(iseq, &loc->base_label, name); 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; } @@ -285,7 +295,7 @@ rb_iseq_add_mark_object(const rb_iseq_t https://github.com/ruby/ruby/blob/trunk/iseq.c#L295 static VALUE 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_compile_option_t *option) { @@ -299,7 +309,7 @@ prepare_iseq_build(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/iseq.c#L309 set_relation(iseq, parent); 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) { 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, V https://github.com/ruby/ruby/blob/trunk/iseq.c#L515 rb_iseq_t *iseq = iseq_alloc(); 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); finish_iseq_build(iseq); @@ -564,12 +574,13 @@ iseq_load(VALUE data, const rb_iseq_t *p https://github.com/ruby/ruby/blob/trunk/iseq.c#L574 rb_iseq_t *iseq = iseq_alloc(); 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; st_data_t iseq_type; rb_compile_option_t option; int i = 0; + rb_code_range_t tmp_loc = { {0, 0}, {-1, -1} }; /* [magic, major_version, minor_version, format_type, misc, * label, path, first_lineno, @@ -604,9 +615,17 @@ iseq_load(VALUE data, const rb_iseq_t *p https://github.com/ruby/ruby/blob/trunk/iseq.c#L615 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); 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); rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body); @@ -2161,6 +2180,12 @@ iseq_data_to_ary(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L2180 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("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, @@ -2499,8 +2524,8 @@ Init_ISeq(void) https://github.com/ruby/ruby/blob/trunk/iseq.c#L2524 rb_define_private_method(rb_cISeq, "marshal_dump", iseqw_marshal_dump, 0); rb_define_private_method(rb_cISeq, "marshal_load", iseqw_marshal_load, 1); /* disable this feature because there is no verifier. */ - rb_define_singleton_method(rb_cISeq, "load", iseq_s_load, -1); #endif + rb_define_singleton_method(rb_cISeq, "load", iseq_s_load, -1); (void)iseq_s_load; rb_define_singleton_method(rb_cISeq, "compile", iseqw_s_compile, -1); Index: compile.c =================================================================== --- compile.c (revision 61024) +++ compile.c (revision 61025) @@ -8566,6 +8566,7 @@ ibf_load_iseq_each(const struct ibf_load https://github.com/ruby/ruby/blob/trunk/compile.c#L8566 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)); 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->ci_entries = ibf_load_ci_entries(load, body); Index: thread.c =================================================================== --- thread.c (revision 61024) +++ thread.c (revision 61025) @@ -5019,24 +5019,33 @@ update_coverage(VALUE data, const rb_tra https://github.com/ruby/ruby/blob/trunk/thread.c#L5019 } 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: switch (me->def->type) { case VM_METHOD_TYPE_ISEQ: { - rb_iseq_location_t loc = me->def->body.iseq.iseqptr->body->location; - path = loc.pathobj; - first_lineno = loc.first_lineno; + const rb_iseq_t *iseq = me->def->body.iseq.iseqptr; + rb_iseq_location_t *loc = &iseq->body->location; + 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; } case VM_METHOD_TYPE_BMETHOD: { const rb_iseq_t *iseq = rb_proc_get_iseq(me->def->body.proc, 0); if (iseq) { + rb_iseq_location_t *loc; rb_iseq_check(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; } return NULL; @@ -5060,6 +5069,9 @@ rb_resolve_me_location(const rb_method_e https://github.com/ruby/ruby/blob/trunk/thread.c#L5069 if (resolved_location) { resolved_location[0] = path; resolved_location[1] = first_lineno; + resolved_location[2] = first_column; + resolved_location[3] = last_lineno; + resolved_location[4] = last_column; } return me; } Index: ext/coverage/coverage.c =================================================================== --- ext/coverage/coverage.c (revision 61024) +++ ext/coverage/coverage.c (revision 61025) @@ -129,7 +129,7 @@ method_coverage_i(void *vstart, void *ve https://github.com/ruby/ruby/blob/trunk/ext/coverage/coverage.c#L129 if (RB_TYPE_P(v, T_IMEMO) && imemo_type(v) == imemo_ment) { const rb_method_entry_t *me = (rb_method_entry_t *) v; VALUE path = Qundef, first_lineno = Qundef; - VALUE data[2], ncoverage, methods; + VALUE data[5], ncoverage, methods; VALUE methods_id = ID2SYM(rb_intern("methods")); VALUE klass; const rb_method_entry_t *me2 = rb_resolve_me_location(me, data); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/