summaryrefslogtreecommitdiff
path: root/iseq.c
diff options
context:
space:
mode:
Diffstat (limited to 'iseq.c')
-rw-r--r--iseq.c107
1 files changed, 73 insertions, 34 deletions
diff --git a/iseq.c b/iseq.c
index 34381c6a46..2c02043d55 100644
--- a/iseq.c
+++ b/iseq.c
@@ -194,7 +194,9 @@ rb_iseq_free(const rb_iseq_t *iseq)
if (body->param.keyword != NULL) {
if (body->param.keyword->table != &body->local_table[body->param.keyword->bits_start - body->param.keyword->num])
ruby_xfree((void *)body->param.keyword->table);
- ruby_xfree((void *)body->param.keyword->default_values);
+ if (body->param.keyword->default_values) {
+ ruby_xfree((void *)body->param.keyword->default_values);
+ }
ruby_xfree((void *)body->param.keyword);
}
compile_data_free(ISEQ_COMPILE_DATA(iseq));
@@ -346,7 +348,7 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
if (cc_is_active(cds[i].cc, reference_updating)) {
rb_gc_mark_and_move_ptr(&cds[i].cc);
}
- else {
+ else if (cds[i].cc != rb_vm_empty_cc()) {
cds[i].cc = rb_vm_empty_cc();
}
}
@@ -521,7 +523,7 @@ rb_iseq_pathobj_new(VALUE path, VALUE realpath)
else {
if (!NIL_P(realpath)) realpath = rb_fstring(realpath);
pathobj = rb_ary_new_from_args(2, rb_fstring(path), realpath);
- rb_obj_freeze(pathobj);
+ rb_ary_freeze(pathobj);
}
return pathobj;
}
@@ -839,18 +841,18 @@ make_compile_option_value(rb_compile_option_t *option)
}
rb_iseq_t *
-rb_iseq_new(const VALUE vast, VALUE name, VALUE path, VALUE realpath,
+rb_iseq_new(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath,
const rb_iseq_t *parent, enum rb_iseq_type type)
{
- return rb_iseq_new_with_opt(vast, name, path, realpath, 0, parent,
+ return rb_iseq_new_with_opt(ast_value, name, path, realpath, 0, parent,
0, type, &COMPILE_OPTION_DEFAULT,
Qnil);
}
static int
-ast_line_count(const VALUE vast)
+ast_line_count(const VALUE ast_value)
{
- rb_ast_t *ast = rb_ruby_ast_data_get(vast);
+ rb_ast_t *ast = rb_ruby_ast_data_get(ast_value);
return ast->body.line_count;
}
@@ -880,11 +882,11 @@ iseq_new_setup_coverage(VALUE path, int line_count)
}
rb_iseq_t *
-rb_iseq_new_top(const VALUE vast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
+rb_iseq_new_top(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
{
- iseq_new_setup_coverage(path, ast_line_count(vast));
+ iseq_new_setup_coverage(path, ast_line_count(ast_value));
- return rb_iseq_new_with_opt(vast, name, path, realpath, 0, parent, 0,
+ return rb_iseq_new_with_opt(ast_value, name, path, realpath, 0, parent, 0,
ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT,
Qnil);
}
@@ -902,11 +904,11 @@ pm_iseq_new_top(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, c
}
rb_iseq_t *
-rb_iseq_new_main(const VALUE vast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
+rb_iseq_new_main(const VALUE ast_value, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
{
- iseq_new_setup_coverage(path, ast_line_count(vast));
+ iseq_new_setup_coverage(path, ast_line_count(ast_value));
- return rb_iseq_new_with_opt(vast, rb_fstring_lit("<main>"),
+ return rb_iseq_new_with_opt(ast_value, rb_fstring_lit("<main>"),
path, realpath, 0,
parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE,
Qnil);
@@ -927,16 +929,16 @@ pm_iseq_new_main(pm_scope_node_t *node, VALUE path, VALUE realpath, const rb_ise
}
rb_iseq_t *
-rb_iseq_new_eval(const VALUE vast, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth)
+rb_iseq_new_eval(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth)
{
if (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) {
VALUE coverages = rb_get_coverages();
if (RTEST(coverages) && RTEST(path) && !RTEST(rb_hash_has_key(coverages, path))) {
- iseq_setup_coverage(coverages, path, ast_line_count(vast) + first_lineno - 1);
+ iseq_setup_coverage(coverages, path, ast_line_count(ast_value) + first_lineno - 1);
}
}
- return rb_iseq_new_with_opt(vast, name, path, realpath, first_lineno,
+ return rb_iseq_new_with_opt(ast_value, name, path, realpath, first_lineno,
parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT,
Qnil);
}
@@ -971,12 +973,12 @@ iseq_translate(rb_iseq_t *iseq)
}
rb_iseq_t *
-rb_iseq_new_with_opt(const VALUE vast, VALUE name, VALUE path, VALUE realpath,
+rb_iseq_new_with_opt(VALUE ast_value, VALUE name, VALUE path, VALUE realpath,
int first_lineno, const rb_iseq_t *parent, int isolated_depth,
enum rb_iseq_type type, const rb_compile_option_t *option,
VALUE script_lines)
{
- rb_ast_t *ast = rb_ruby_ast_data_get(vast);
+ rb_ast_t *ast = rb_ruby_ast_data_get(ast_value);
rb_ast_body_t *body = ast ? &ast->body : NULL;
const NODE *node = body ? body->root : 0;
/* TODO: argument check */
@@ -1004,6 +1006,7 @@ rb_iseq_new_with_opt(const VALUE vast, VALUE name, VALUE path, VALUE realpath,
rb_iseq_compile_node(iseq, node);
finish_iseq_build(iseq);
+ RB_GC_GUARD(ast_value);
return iseq_translate(iseq);
}
@@ -1027,10 +1030,14 @@ pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpa
{
rb_iseq_t *iseq = iseq_alloc();
ISEQ_BODY(iseq)->prism = true;
- ISEQ_BODY(iseq)->param.flags.use_block = true; // unused block warning is not supported yet
+ rb_compile_option_t next_option;
if (!option) option = &COMPILE_OPTION_DEFAULT;
+ next_option = *option;
+ next_option.coverage_enabled = node->coverage_enabled < 0 ? 0 : node->coverage_enabled > 0;
+ option = &next_option;
+
pm_location_t *location = &node->base.location;
int32_t start_line = node->parser->start_line;
@@ -1043,7 +1050,7 @@ pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpa
};
prepare_iseq_build(iseq, name, path, realpath, first_lineno, &code_location, -1,
- parent, isolated_depth, type, Qnil, option);
+ parent, isolated_depth, type, node->script_lines == NULL ? Qnil : *node->script_lines, option);
pm_iseq_compile_node(iseq, node);
finish_iseq_build(iseq);
@@ -1217,7 +1224,7 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
#endif
VALUE (*parse)(VALUE vparser, VALUE fname, VALUE file, int start);
int ln;
- VALUE INITIALIZED vast;
+ VALUE INITIALIZED ast_value;
rb_ast_t *ast;
VALUE name = rb_fstring_lit("<compiled>");
@@ -1239,17 +1246,17 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
rb_parser_set_context(parser, outer_scope, FALSE);
if (ruby_vm_keep_script_lines) rb_parser_set_script_lines(parser);
RB_GC_GUARD(outer_scope_v);
- vast = (*parse)(parser, file, src, ln);
+ ast_value = (*parse)(parser, file, src, ln);
}
- ast = rb_ruby_ast_data_get(vast);
+ ast = rb_ruby_ast_data_get(ast_value);
if (!ast || !ast->body.root) {
rb_ast_dispose(ast);
rb_exc_raise(GET_EC()->errinfo);
}
else {
- iseq = rb_iseq_new_with_opt(vast, name, file, realpath, ln,
+ iseq = rb_iseq_new_with_opt(ast_value, name, file, realpath, ln,
NULL, 0, ISEQ_TYPE_TOP, &option,
Qnil);
rb_ast_dispose(ast);
@@ -1273,16 +1280,34 @@ pm_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
pm_parse_result_t result = { 0 };
pm_options_line_set(&result.options, NUM2INT(line));
+ pm_options_scopes_init(&result.options, 1);
+ result.node.coverage_enabled = 1;
+ switch (option.frozen_string_literal) {
+ case ISEQ_FROZEN_STRING_LITERAL_UNSET:
+ break;
+ case ISEQ_FROZEN_STRING_LITERAL_DISABLED:
+ pm_options_frozen_string_literal_set(&result.options, false);
+ break;
+ case ISEQ_FROZEN_STRING_LITERAL_ENABLED:
+ pm_options_frozen_string_literal_set(&result.options, true);
+ break;
+ default:
+ rb_bug("pm_iseq_compile_with_option: invalid frozen_string_literal=%d", option.frozen_string_literal);
+ break;
+ }
+
+ VALUE script_lines;
VALUE error;
+
if (RB_TYPE_P(src, T_FILE)) {
VALUE filepath = rb_io_path(src);
- error = pm_load_parse_file(&result, filepath);
+ error = pm_load_parse_file(&result, filepath, ruby_vm_keep_script_lines ? &script_lines : NULL);
RB_GC_GUARD(filepath);
}
else {
src = StringValue(src);
- error = pm_parse_string(&result, src, file);
+ error = pm_parse_string(&result, src, file, ruby_vm_keep_script_lines ? &script_lines : NULL);
}
if (error == Qnil) {
@@ -1610,7 +1635,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
VALUE file, opt = Qnil;
VALUE parser, f, exc = Qnil, ret;
rb_ast_t *ast;
- VALUE vast;
+ VALUE ast_value;
rb_compile_option_t option;
int i;
@@ -1629,8 +1654,8 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
parser = rb_parser_new();
rb_parser_set_context(parser, NULL, FALSE);
- vast = rb_parser_load_file(parser, file);
- ast = rb_ruby_ast_data_get(vast);
+ ast_value = rb_parser_load_file(parser, file);
+ ast = rb_ruby_ast_data_get(ast_value);
if (!ast->body.root) exc = GET_EC()->errinfo;
rb_io_close(f);
@@ -1641,7 +1666,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
make_compile_option(&option, opt);
- ret = iseqw_new(rb_iseq_new_with_opt(vast, rb_fstring_lit("<main>"),
+ ret = iseqw_new(rb_iseq_new_with_opt(ast_value, rb_fstring_lit("<main>"),
file,
rb_realpath_internal(Qnil, file, 1),
1, NULL, 0, ISEQ_TYPE_TOP, &option,
@@ -1694,8 +1719,10 @@ iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self)
pm_parse_result_t result = { 0 };
result.options.line = 1;
+ result.node.coverage_enabled = 1;
- VALUE error = pm_load_parse_file(&result, file);
+ VALUE script_lines;
+ VALUE error = pm_load_parse_file(&result, file, ruby_vm_keep_script_lines ? &script_lines : NULL);
if (error == Qnil) {
make_compile_option(&option, opt);
@@ -2428,6 +2455,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
CALL_FLAG(KWARG);
CALL_FLAG(KW_SPLAT);
CALL_FLAG(KW_SPLAT_MUT);
+ CALL_FLAG(FORWARDING);
CALL_FLAG(OPT_SEND); /* maybe not reachable */
rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|")));
}
@@ -2710,11 +2738,11 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
}
snprintf(argi, sizeof(argi), "%s%s%s%s%s%s", /* arg, opts, rest, post, kwrest, block */
- body->param.lead_num > li ? "Arg" : "",
+ (body->param.lead_num > li) ? (body->param.flags.ambiguous_param0 ? "AmbiguousArg" : "Arg") : "",
opti,
- (body->param.flags.has_rest && body->param.rest_start == li) ? "Rest" : "",
+ (body->param.flags.has_rest && body->param.rest_start == li) ? (body->param.flags.anon_rest ? "AnonRest" : "Rest") : "",
(body->param.flags.has_post && body->param.post_start <= li && li < body->param.post_start + body->param.post_num) ? "Post" : "",
- (body->param.flags.has_kwrest && keyword->rest_start == li) ? "Kwrest" : "",
+ (body->param.flags.has_kwrest && keyword->rest_start == li) ? (body->param.flags.anon_kwrest ? "AnonKwrest" : "Kwrest") : "",
(body->param.flags.has_block && body->param.block_start == li) ? "Block" : "");
rb_str_cat(str, indent_str, indent_len);
@@ -3474,6 +3502,17 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
CONST_ID(req, "req");
CONST_ID(opt, "opt");
+
+ if (body->param.flags.forwardable) {
+ // [[:rest, :*], [:keyrest, :**], [:block, :&]]
+ CONST_ID(rest, "rest");
+ CONST_ID(keyrest, "keyrest");
+ CONST_ID(block, "block");
+ rb_ary_push(args, rb_ary_new_from_args(2, ID2SYM(rest), ID2SYM(idMULT)));
+ rb_ary_push(args, rb_ary_new_from_args(2, ID2SYM(keyrest), ID2SYM(idPow)));
+ rb_ary_push(args, rb_ary_new_from_args(2, ID2SYM(block), ID2SYM(idAnd)));
+ }
+
if (is_proc) {
for (i = 0; i < body->param.lead_num; i++) {
PARAM_TYPE(opt);