diff --git a/compile.c b/compile.c index 7ceb936f06..605ca79228 100644 --- a/compile.c +++ b/compile.c @@ -1326,7 +1326,8 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node, rb_ast_body_t ast; ast.root = node; - ast.compile_option = 0; + ast.frozen_string_literal = -1; + ast.coverage_enabled = -1; ast.script_lines = ISEQ_BODY(iseq)->variable.script_lines; debugs("[new_child_iseq]> ---------------------------------------\n"); @@ -8372,7 +8373,8 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N rb_ast_body_t ast = { .root = &scope_node, - .compile_option = 0, + .frozen_string_literal = -1, + .coverage_enabled = -1, .script_lines = ISEQ_BODY(iseq)->variable.script_lines, }; diff --git a/iseq.c b/iseq.c index 6d8596528e..0878ba9f84 100644 --- a/iseq.c +++ b/iseq.c @@ -741,6 +741,15 @@ set_compile_option_from_hash(rb_compile_option_t *option, VALUE opt) #undef SET_COMPILE_OPTION_NUM } +static VALUE +make_compile_option_from_ast(const rb_ast_body_t *ast) +{ + VALUE opt = rb_obj_hide(rb_ident_hash_new()); + if (ast->frozen_string_literal >= 0) rb_hash_aset(opt, rb_sym_intern_ascii_cstr("frozen_string_literal"), RBOOL(ast->frozen_string_literal)); + if (ast->coverage_enabled >= 0) rb_hash_aset(opt, rb_sym_intern_ascii_cstr("coverage_enabled"), RBOOL(ast->coverage_enabled)); + return opt; +} + static void rb_iseq_make_compile_option(rb_compile_option_t *option, VALUE opt) { @@ -908,7 +917,7 @@ rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE rea else { new_opt = COMPILE_OPTION_DEFAULT; } - if (ast && ast->compile_option) rb_iseq_make_compile_option(&new_opt, ast->compile_option); + if (ast) rb_iseq_make_compile_option(&new_opt, make_compile_option_from_ast(ast)); VALUE script_lines = Qnil; diff --git a/node.c b/node.c index 1d3b7b75e4..bd03454bef 100644 --- a/node.c +++ b/node.c @@ -392,7 +392,6 @@ rb_ast_mark(rb_ast_t *ast) if (ast->node_buffer) { rb_gc_mark(ast->node_buffer->mark_hash); rb_gc_mark(ast->node_buffer->tokens); - if (ast->body.compile_option) rb_gc_mark(ast->body.compile_option); node_buffer_t *nb = ast->node_buffer; iterate_node_values(ast, &nb->markable, mark_ast_value, NULL); if (ast->body.script_lines) rb_gc_mark(ast->body.script_lines); diff --git a/parse.y b/parse.y index e5182639c9..0e1717e7c4 100644 --- a/parse.y +++ b/parse.y @@ -416,7 +416,6 @@ struct parser_params { rb_encoding *enc; token_info *token_info; VALUE case_labels; - VALUE compile_option; VALUE debug_buffer; VALUE debug_output; @@ -441,6 +440,9 @@ struct parser_params { #ifdef UNIVERSAL_PARSER rb_parser_config_t *config; #endif + /* compile_option */ + int frozen_string_literal:2; /* -1: not specified, 0: false, 1: true */ + int coverage_enabled:2; /* -1: not specified, 0: false, 1: true */ unsigned int command_start:1; unsigned int eofp: 1; @@ -6773,7 +6775,7 @@ yycompile0(VALUE arg) int n; NODE *tree; struct parser_params *p = (struct parser_params *)arg; - VALUE cov = Qfalse; + int cov = FALSE; if (!compile_for_eval && !NIL_P(p->ruby_sourcefile_string)) { p->debug_lines = debug_lines(p, p->ruby_sourcefile_string); @@ -6786,7 +6788,7 @@ yycompile0(VALUE arg) } if (!e_option_supplied(p)) { - cov = Qtrue; + cov = TRUE; } } @@ -6825,15 +6827,14 @@ yycompile0(VALUE arg) tree = NEW_NIL(&NULL_LOC); } else { - VALUE opt = p->compile_option; VALUE tokens = p->tokens; NODE *prelude; NODE *body = parser_append_options(p, tree->nd_body); - if (!opt) opt = rb_obj_hide(rb_ident_hash_new()); - rb_hash_aset(opt, rb_sym_intern_ascii_cstr("coverage_enabled"), cov); + p->coverage_enabled = cov; prelude = block_append(p, p->eval_tree_begin, body); tree->nd_body = prelude; - RB_OBJ_WRITE(p->ast, &p->ast->body.compile_option, opt); + p->ast->body.frozen_string_literal = p->frozen_string_literal; + p->ast->body.coverage_enabled = p->coverage_enabled; if (p->keep_tokens) { rb_obj_freeze(tokens); rb_ast_set_tokens(p->ast, tokens); @@ -8656,7 +8657,7 @@ parser_set_token_info(struct parser_params *p, const char *name, const char *val } static void -parser_set_compile_option_flag(struct parser_params *p, const char *name, const char *val) +parser_set_frozen_string_literal(struct parser_params *p, const char *name, const char *val) { int b; @@ -8668,10 +8669,7 @@ parser_set_compile_option_flag(struct parser_params *p, const char *name, const b = parser_get_bool(p, name, val); if (b < 0) return; - if (!p->compile_option) - p->compile_option = rb_obj_hide(rb_ident_hash_new()); - rb_hash_aset(p->compile_option, ID2SYM(rb_intern(name)), - RBOOL(b)); + p->frozen_string_literal = b; } static void @@ -8729,7 +8727,7 @@ struct magic_comment { static const struct magic_comment magic_comments[] = { {"coding", magic_comment_encoding, parser_encode_length}, {"encoding", magic_comment_encoding, parser_encode_length}, - {"frozen_string_literal", parser_set_compile_option_flag}, + {"frozen_string_literal", parser_set_frozen_string_literal}, {"shareable_constant_value", parser_set_shareable_constant_value}, {"warn_indent", parser_set_token_info}, # if WARN_PAST_SCOPE @@ -13674,6 +13672,8 @@ parser_initialize(struct parser_params *p) p->lex.lpar_beg = -1; /* make lambda_beginning_p() == FALSE at first */ p->node_id = 0; p->delayed.token = Qnil; + p->frozen_string_literal = -1; /* not specified */ + p->coverage_enabled = -1; /* not specified */ #ifdef RIPPER p->result = Qnil; p->parsing_thread = Qnil; @@ -13709,7 +13709,6 @@ rb_ruby_parser_mark(void *ptr) rb_gc_mark(p->delayed.token); #ifndef RIPPER rb_gc_mark(p->debug_lines); - rb_gc_mark(p->compile_option); rb_gc_mark(p->error_buffer); rb_gc_mark(p->end_expect_token_locations); rb_gc_mark(p->tokens); diff --git a/rubyparser.h b/rubyparser.h index c3e3d870e2..ab70176fc4 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -309,11 +309,12 @@ typedef struct node_buffer_struct node_buffer_t; /* T_IMEMO/ast */ typedef struct rb_ast_body_struct { const NODE *root; - VALUE compile_option; VALUE script_lines; // script_lines is either: // - a Fixnum that represents the line count of the original source, or // - an Array that contains the lines of the original source + int frozen_string_literal:2; /* -1: not specified, 0: false, 1: true */ + int coverage_enabled:2; /* -1: not specified, 0: false, 1: true */ } rb_ast_body_t; typedef struct rb_ast_struct { VALUE flags; diff --git a/vm.c b/vm.c index 39fb7dc821..f94be00187 100644 --- a/vm.c +++ b/vm.c @@ -1350,7 +1350,8 @@ rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const I rb_node_init(&tmp_node, NODE_SCOPE, (VALUE)dyns, 0, 0); ast.root = &tmp_node; - ast.compile_option = 0; + ast.frozen_string_literal = -1; + ast.coverage_enabled = -1; ast.script_lines = INT2FIX(-1); if (base_iseq) { diff --git a/vm_eval.c b/vm_eval.c index d5fbcf5f56..9beae74731 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -1626,7 +1626,7 @@ eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind, int isolated_depth = 0; // Conditionally enable coverage depending on the current mode: - VALUE coverage_enabled = RBOOL(rb_get_coverage_mode() & COVERAGE_TARGET_EVAL); + int coverage_enabled = (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) != 0; { int depth = 1; @@ -1659,17 +1659,13 @@ eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind, rb_gc_register_mark_object(eval_default_path); } fname = eval_default_path; - coverage_enabled = Qfalse; + coverage_enabled = FALSE; } rb_parser_set_context(parser, parent, FALSE); ast = rb_parser_compile_string_path(parser, fname, src, line); if (ast->body.root) { - if (ast->body.compile_option == Qnil) { - ast->body.compile_option = rb_obj_hide(rb_ident_hash_new()); - } - rb_hash_aset(ast->body.compile_option, rb_sym_intern_ascii_cstr("coverage_enabled"), coverage_enabled); - + ast->body.coverage_enabled = coverage_enabled; iseq = rb_iseq_new_eval(&ast->body, ISEQ_BODY(parent)->location.label, fname, Qnil, line,