summaryrefslogtreecommitdiff
path: root/iseq.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2021-09-30 16:58:46 +0900
committerKoichi Sasada <ko1@atdot.net>2021-10-21 16:17:39 +0900
commitc7550537f11dcf6450a9d3df3af3fa1f4fe05b15 (patch)
tree9b73c5b1be4e42f0aaf92e64b9c6041777666251 /iseq.c
parent3b16d07e457264d7c171f8d1fcfaddb0dad90f57 (diff)
`RubyVM.keep_script_lines`
`RubyVM.keep_script_lines` enables to keep script lines for each ISeq and AST. This feature is for debugger/REPL support. ```ruby RubyVM.keep_script_lines = true RubyVM::keep_script_lines = true eval("def foo = nil\ndef bar = nil") pp RubyVM::InstructionSequence.of(method(:foo)).script_lines ```
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4913
Diffstat (limited to 'iseq.c')
-rw-r--r--iseq.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/iseq.c b/iseq.c
index 68611798c7..0551e0c99a 100644
--- a/iseq.c
+++ b/iseq.c
@@ -595,7 +595,8 @@ new_arena(void)
static VALUE
prepare_iseq_build(rb_iseq_t *iseq,
VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_location_t *code_location, const int node_id,
- const rb_iseq_t *parent, int isolated_depth, enum iseq_type type, const rb_compile_option_t *option)
+ const rb_iseq_t *parent, int isolated_depth, enum iseq_type type,
+ VALUE script_lines, const rb_compile_option_t *option)
{
VALUE coverage = Qfalse;
VALUE err_info = Qnil;
@@ -616,6 +617,8 @@ prepare_iseq_build(rb_iseq_t *iseq,
ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
body->variable.flip_count = 0;
+ RB_OBJ_WRITE(iseq, &body->variable.script_lines, script_lines);
+
ISEQ_COMPILE_DATA_ALLOC(iseq);
RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info);
RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, Qnil);
@@ -894,7 +897,17 @@ rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE rea
}
if (ast && ast->compile_option) rb_iseq_make_compile_option(&new_opt, ast->compile_option);
- prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1, parent, isolated_depth, type, &new_opt);
+ VALUE script_lines = Qnil;
+
+ if (ast && !FIXNUM_P(ast->script_lines) && ast->script_lines) {
+ script_lines = ast->script_lines;
+ }
+ else if (parent) {
+ script_lines = parent->body->variable.script_lines;
+ }
+
+ prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1,
+ parent, isolated_depth, type, script_lines, &new_opt);
rb_iseq_compile_node(iseq, node);
finish_iseq_build(iseq);
@@ -913,7 +926,7 @@ rb_iseq_new_with_callback(
rb_iseq_t *iseq = iseq_alloc();
if (!option) option = &COMPILE_OPTION_DEFAULT;
- prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, 0, type, option);
+ prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, 0, type, Qnil, option);
rb_iseq_compile_callback(iseq, ifunc);
finish_iseq_build(iseq);
@@ -1026,7 +1039,7 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
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, &tmp_loc, NUM2INT(node_id),
- parent, 0, (enum iseq_type)iseq_type, &option);
+ parent, 0, (enum iseq_type)iseq_type, Qnil, &option);
rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body);
@@ -3680,6 +3693,26 @@ succ_index_lookup(const struct succ_index_table *sd, int x)
}
#endif
+
+/*
+ * call-seq:
+ * iseq.script_lines -> array or nil
+ *
+ * It returns recorded script lines if it is availalble.
+ * The script lines are not limited to the iseq range, but
+ * are entire lines of the source file.
+ *
+ * Note that this is an API for ruby internal use, debugging,
+ * and research. Do not use this for any other purpose.
+ * The compatibility is not guaranteed.
+ */
+static VALUE
+iseqw_script_lines(VALUE self)
+{
+ const rb_iseq_t *iseq = iseqw_check(self);
+ return iseq->body->variable.script_lines;
+}
+
/*
* Document-class: RubyVM::InstructionSequence
*
@@ -3747,6 +3780,9 @@ Init_ISeq(void)
rb_define_singleton_method(rb_cISeq, "disassemble", iseqw_s_disasm, 1);
rb_define_singleton_method(rb_cISeq, "of", iseqw_s_of, 1);
+ // script lines
+ rb_define_method(rb_cISeq, "script_lines", iseqw_script_lines, 0);
+
rb_undef_method(CLASS_OF(rb_cISeq), "translate");
rb_undef_method(CLASS_OF(rb_cISeq), "load_iseq");
}