diff options
Diffstat (limited to 'iseq.c')
-rw-r--r-- | iseq.c | 107 |
1 files changed, 73 insertions, 34 deletions
@@ -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); |