compile.c: Pass node instead of nd_line(node) to ADD_INSN* functions

... then, new_insn_core extracts nd_line(node).

Also, if a macro "EXPERIMENTAL_ISEQ_NODE_ID" is defined, this changeset
keeps nd_node_id(node) for each instruction. This is intended for
TypeProf to identify what AST::Node corresponds to each instruction.

This patch is originally authored by @yui-knk for showing which column a
NoMethodError occurred.

https://github.com/ruby/ruby/compare/master...yui-knk:feature/node_id

Co-Authored-By: Yuichiro Kaneko <yui-knk@ruby-lang.org>
This commit is contained in:
Yusuke Endoh 2021-04-30 18:54:46 +09:00
Родитель 578e6416e7
Коммит ff69ef27b0
4 изменённых файлов: 916 добавлений и 818 удалений

14
ast.c
Просмотреть файл

@ -245,6 +245,17 @@ ast_node_type(rb_execution_context_t *ec, VALUE self)
return rb_sym_intern_ascii_cstr(node_type_to_str(data->node));
}
#ifdef EXPERIMENTAL_ISEQ_NODE_ID
static VALUE
ast_node_node_id(VALUE self)
{
struct ASTNodeData *data;
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
return INT2FIX(nd_node_id(data->node));
}
#endif
#define NEW_CHILD(ast, node) node ? ast_new_internal(ast, node) : Qnil
static VALUE
@ -695,4 +706,7 @@ Init_ast(void)
rb_mAST = rb_define_module_under(rb_cRubyVM, "AbstractSyntaxTree");
rb_cNode = rb_define_class_under(rb_mAST, "Node", rb_cObject);
rb_undef_alloc_func(rb_cNode);
#ifdef EXPERIMENTAL_ISEQ_NODE_ID
rb_define_method(rb_cNode, "node_id", ast_node_node_id, 0);
#endif
}

1688
compile.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу

24
iseq.c
Просмотреть файл

@ -1830,6 +1830,21 @@ rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
}
}
#ifdef EXPERIMENTAL_ISEQ_NODE_ID
int
rb_iseq_node_id(const rb_iseq_t *iseq, size_t pos)
{
const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
if (entry) {
return entry->node_id;
}
else {
return 0;
}
}
#endif
MJIT_FUNC_EXPORTED rb_event_flag_t
rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos)
{
@ -2918,6 +2933,9 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
/* make body with labels and insert line number */
body = rb_ary_new();
prev_insn_info = NULL;
#ifdef EXPERIMENTAL_ISEQ_NODE_ID
VALUE node_ids = rb_ary_new();
#endif
for (l=0, pos=0; l<RARRAY_LEN(nbody); l++) {
const struct iseq_insn_info_entry *info;
@ -2929,6 +2947,9 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
}
info = get_insn_info(iseq, pos);
#ifdef EXPERIMENTAL_ISEQ_NODE_ID
rb_ary_push(node_ids, INT2FIX(info->node_id));
#endif
if (prev_insn_info != info) {
int line = info->line_no;
@ -2966,6 +2987,9 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
INT2FIX(iseq_body->location.code_location.beg_pos.column),
INT2FIX(iseq_body->location.code_location.end_pos.lineno),
INT2FIX(iseq_body->location.code_location.end_pos.column)));
#ifdef EXPERIMENTAL_ISEQ_NODE_ID
rb_hash_aset(misc, ID2SYM(rb_intern("node_ids_for_each_insn")), node_ids);
#endif
/*
* [:magic, :major_version, :minor_version, :format_type, :misc,

8
iseq.h
Просмотреть файл

@ -17,6 +17,8 @@ RUBY_EXTERN const int ruby_api_version[];
#define ISEQ_MAJOR_VERSION ((unsigned int)ruby_api_version[0])
#define ISEQ_MINOR_VERSION ((unsigned int)ruby_api_version[1])
//#define EXPERIMENTAL_ISEQ_NODE_ID
#ifndef rb_iseq_t
typedef struct rb_iseq_struct rb_iseq_t;
#define rb_iseq_t rb_iseq_t
@ -176,6 +178,9 @@ void rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *arena);
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt);
VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc);
unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos);
#ifdef EXPERIMENTAL_ISEQ_NODE_ID
int rb_iseq_node_id(const rb_iseq_t *iseq, size_t pos);
#endif
void rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events);
void rb_iseq_trace_set_all(rb_event_flag_t turnon_events);
void rb_iseq_insns_info_encode_positions(const rb_iseq_t *iseq);
@ -213,6 +218,9 @@ struct rb_compile_option_struct {
struct iseq_insn_info_entry {
int line_no;
#ifdef EXPERIMENTAL_ISEQ_NODE_ID
int node_id;
#endif
rb_event_flag_t events;
};