diff options
Diffstat (limited to 'ruby.c')
| -rw-r--r-- | ruby.c | 350 |
1 files changed, 235 insertions, 115 deletions
@@ -105,9 +105,9 @@ void rb_warning_category_update(unsigned int mask, unsigned int bits); SEP \ X(frozen_string_literal) \ SEP \ - X(rjit) \ - SEP \ X(yjit) \ + SEP \ + X(zjit) \ /* END OF FEATURES */ #define EACH_DEBUG_FEATURES(X, SEP) \ X(frozen_string_literal) \ @@ -117,13 +117,14 @@ void rb_warning_category_update(unsigned int mask, unsigned int bits); #define DEFINE_DEBUG_FEATURE(bit) feature_debug_##bit enum feature_flag_bits { EACH_FEATURES(DEFINE_FEATURE, COMMA), + DEFINE_FEATURE(frozen_string_literal_set), feature_debug_flag_first, -#if defined(RJIT_FORCE_ENABLE) || !USE_YJIT - DEFINE_FEATURE(jit) = feature_rjit, +#if !USE_YJIT && USE_ZJIT + DEFINE_FEATURE(jit) = feature_zjit, #else DEFINE_FEATURE(jit) = feature_yjit, #endif - feature_jit_mask = FEATURE_BIT(rjit) | FEATURE_BIT(yjit), + feature_jit_mask = FEATURE_BIT(yjit) | FEATURE_BIT(zjit), feature_debug_flag_begin = feature_debug_flag_first - 1, EACH_DEBUG_FEATURES(DEFINE_DEBUG_FEATURE, COMMA), @@ -189,6 +190,7 @@ enum { COMPILATION_FEATURES = ( 0 | FEATURE_BIT(frozen_string_literal) + | FEATURE_BIT(frozen_string_literal_set) | FEATURE_BIT(debug_frozen_string_literal) ), DEFAULT_FEATURES = ( @@ -197,6 +199,7 @@ enum { & ~FEATURE_BIT(gems) #endif & ~FEATURE_BIT(frozen_string_literal) + & ~FEATURE_BIT(frozen_string_literal_set) & ~feature_jit_mask ) }; @@ -214,9 +217,7 @@ cmdline_options_init(ruby_cmdline_options_t *opt) opt->ext.enc.index = -1; opt->intern.enc.index = -1; opt->features.set = DEFAULT_FEATURES; -#ifdef RJIT_FORCE_ENABLE /* to use with: ./configure cppflags="-DRJIT_FORCE_ENABLE" */ - opt->features.set |= FEATURE_BIT(rjit); -#elif defined(YJIT_FORCE_ENABLE) +#if defined(YJIT_FORCE_ENABLE) opt->features.set |= FEATURE_BIT(yjit); #endif opt->dump |= DUMP_BIT(opt_optimize); @@ -304,15 +305,17 @@ ruby_show_usage_line(const char *name, const char *secondary, const char *descri description, help, highlight, width, columns); } +RUBY_EXTERN const char ruby_api_version_name[]; + static void usage(const char *name, int help, int highlight, int columns) { #define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc) #if USE_YJIT -# define PLATFORM_JIT_OPTION "--yjit" -#else -# define PLATFORM_JIT_OPTION "--rjit (experimental)" +# define DEFAULT_JIT_OPTION "--yjit" +#elif USE_ZJIT +# define DEFAULT_JIT_OPTION "--zjit" #endif /* This message really ought to be max 23 lines. @@ -323,14 +326,14 @@ usage(const char *name, int help, int highlight, int columns) M("-a", "", "Split each input line ($_) into fields ($F)."), M("-c", "", "Check syntax (no execution)."), M("-Cdirpath", "", "Execute program in specified directory."), - M("-d", ", --debug", "Set debugging flag ($DEBUG) to true."), + M("-d", ", --debug", "Set debugging flag ($DEBUG) and $VERBOSE to true."), M("-e 'code'", "", "Execute given Ruby code; multiple -e allowed."), M("-Eex[:in]", ", --encoding=ex[:in]", "Set default external and internal encodings."), M("-Fpattern", "", "Set input field separator ($;); used with -a."), M("-i[extension]", "", "Set ARGF in-place mode;\n" "create backup files with given extension."), - M("-Idirpath", "", "Add specified directory to load paths ($LOAD_PATH);\n" - "multiple -I allowed."), + M("-Idirpath", "", "Prepend specified directory to load paths ($LOAD_PATH);\n" + "relative paths are expanded; multiple -I are allowed."), M("-l", "", "Set output record separator ($\\) to $/;\n" "used for line-oriented output."), M("-n", "", "Run program in gets loop."), @@ -343,16 +346,18 @@ usage(const char *name, int help, int highlight, int columns) M("-W[level=2|:category]", "", "Set warning flag ($-W):\n" "0 for silent; 1 for moderate; 2 for verbose."), M("-x[dirpath]", "", "Execute Ruby code starting from a #!ruby line."), - M("--jit", "", "Enable JIT for the platform; same as " PLATFORM_JIT_OPTION "."), +#if USE_YJIT || USE_ZJIT + M("--jit", "", "Enable the default JIT for the build; same as " DEFAULT_JIT_OPTION "."), +#endif #if USE_YJIT M("--yjit", "", "Enable in-process JIT compiler."), #endif -#if USE_RJIT - M("--rjit", "", "Enable pure-Ruby JIT compiler (experimental)."), +#if USE_ZJIT + M("--zjit", "", "Enable method-based JIT compiler."), #endif M("-h", "", "Print this help message; use --help for longer message."), }; - STATIC_ASSERT(usage_msg_size, numberof(usage_msg) < 25); + STATIC_ASSERT(usage_msg_size, numberof(usage_msg) < 26); static const struct ruby_opt_message help_msg[] = { M("--backtrace-limit=num", "", "Set backtrace limit."), @@ -375,7 +380,7 @@ usage(const char *name, int help, int highlight, int columns) M("parsetree", "", "Abstract syntax tree (AST)."), M("-optimize", "", "Disable optimization (affects insns)."), M("+error-tolerant", "", "Error-tolerant parsing (affects yydebug, parsetree)."), - M("+comment", "", "Add comments to AST (affects parsetree)."), + M("+comment", "", "Add comments to AST (affects parsetree with --parser=parse.y)."), }; static const struct ruby_opt_message features[] = { M("gems", "", "Rubygems (only for debugging, default: "DEFAULT_RUBYGEMS_ENABLED")."), @@ -387,18 +392,16 @@ usage(const char *name, int help, int highlight, int columns) #if USE_YJIT M("yjit", "", "In-process JIT compiler (default: disabled)."), #endif -#if USE_RJIT - M("rjit", "", "Pure-Ruby JIT compiler (experimental, default: disabled)."), +#if USE_ZJIT + M("zjit", "", "Method-based JIT compiler (default: disabled)."), #endif }; static const struct ruby_opt_message warn_categories[] = { M("deprecated", "", "Deprecated features."), M("experimental", "", "Experimental features."), M("performance", "", "Performance issues."), + M("strict_unused_block", "", "Warning unused block strictly"), }; -#if USE_RJIT - extern const struct ruby_opt_message rb_rjit_option_messages[]; -#endif int i; const char *sb = highlight ? esc_standout+1 : esc_none; const char *se = highlight ? esc_reset : esc_none; @@ -429,10 +432,10 @@ usage(const char *name, int help, int highlight, int columns) printf("%s""YJIT options:%s\n", sb, se); rb_yjit_show_usage(help, highlight, w, columns); #endif -#if USE_RJIT - printf("%s""RJIT options (experimental):%s\n", sb, se); - for (i = 0; rb_rjit_option_messages[i].str; ++i) - SHOW(rb_rjit_option_messages[i]); +#if USE_ZJIT + printf("%s""ZJIT options:%s\n", sb, se); + extern void rb_zjit_show_usage(int help, int highlight, unsigned int width, int columns); + rb_zjit_show_usage(help, highlight, w, columns); #endif } @@ -443,7 +446,7 @@ ruby_push_include(const char *path, VALUE (*filter)(VALUE)) { const char sep = PATH_SEP_CHAR; const char *p, *s; - VALUE load_path = GET_VM()->load_path; + VALUE load_path = rb_root_box()->load_path; #ifdef __CYGWIN__ char rubylib[FILENAME_MAX]; VALUE buf = 0; @@ -556,6 +559,8 @@ translit_char_bin(char *p, int from, int to) #endif #ifdef _WIN32 +# undef chdir +# define chdir rb_w32_uchdir # define UTF8_PATH 1 #endif @@ -746,7 +751,7 @@ ruby_init_loadpath(void) rb_gc_register_address(&ruby_archlibdir_path); ruby_archlibdir_path = archlibdir; - load_path = GET_VM()->load_path; + load_path = rb_root_box()->load_path; ruby_push_include(getenv("RUBYLIB"), identical_path); @@ -758,8 +763,6 @@ ruby_init_loadpath(void) rb_ary_push(load_path, path); paths += len + 1; } - - rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), ruby_prefix_path); } @@ -910,7 +913,9 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt) argc = RSTRING_LEN(argary) / sizeof(ap); ap = 0; rb_str_cat(argary, (char *)&ap, sizeof(ap)); - argv = ptr = ALLOC_N(char *, argc); + + VALUE ptr_obj; + argv = ptr = RB_ALLOCV_N(char *, ptr_obj, argc); MEMMOVE(argv, RSTRING_PTR(argary), char *, argc); while ((i = proc_options(argc, argv, opt, envopt)) > 1 && envopt && (argc -= i) > 0) { @@ -942,7 +947,8 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt) opt->crash_report = crash_report; } - ruby_xfree(ptr); + RB_ALLOCV_END(ptr_obj); + /* get rid of GC */ rb_str_resize(argary, 0); rb_str_resize(argstr, 0); @@ -1005,7 +1011,7 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable) goto found; } if (NAME_MATCH_P("all", str, len)) { - // YJIT and RJIT cannot be enabled at the same time. We enable only one for --enable=all. + // We enable only one JIT for --enable=all. mask &= ~feature_jit_mask | FEATURE_BIT(jit); goto found; } @@ -1033,6 +1039,9 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable) found: FEATURE_SET_TO(*argp, mask, (mask & enable)); + if (NAME_MATCH_P("frozen_string_literal", str, len)) { + FEATURE_SET_TO(*argp, FEATURE_BIT(frozen_string_literal_set), FEATURE_BIT(frozen_string_literal_set)); + } return; } @@ -1194,6 +1203,19 @@ setup_yjit_options(const char *s) } #endif +#if USE_ZJIT +static void +setup_zjit_options(const char *s) +{ + // The option parsing is done in zjit/src/options.rs + extern bool rb_zjit_parse_option(const char *s); + + if (!rb_zjit_parse_option(s)) { + rb_raise(rb_eRuntimeError, "invalid ZJIT option '%s' (--help will show valid zjit options)", s); + } +} +#endif + /* * Following proc_*_option functions are tree kinds: * @@ -1225,6 +1247,9 @@ proc_W_option(ruby_cmdline_options_t *opt, const char *s, int *warning) else if (NAME_MATCH_P("performance", s, len)) { bits = 1U << RB_WARN_CATEGORY_PERFORMANCE; } + else if (NAME_MATCH_P("strict_unused_block", s, len)) { + bits = 1U << RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK; + } else { rb_warn("unknown warning category: '%s'", s); } @@ -1335,11 +1360,11 @@ proc_0_option(ruby_cmdline_options_t *opt, const char *s) if (v > 0377) rb_rs = Qnil; else if (v == 0 && numlen >= 2) { - rb_rs = rb_str_new2(""); + rb_rs = rb_fstring_lit(""); } else { c = v & 0xff; - rb_rs = rb_str_new(&c, 1); + rb_rs = rb_str_freeze(rb_str_new(&c, 1)); } return s; } @@ -1422,10 +1447,10 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char ** } else if (is_option_with_arg("parser", Qfalse, Qtrue)) { if (strcmp("prism", s) == 0) { - (*rb_ruby_prism_ptr()) = true; + rb_ruby_default_parser_set(RB_DEFAULT_PARSER_PRISM); } else if (strcmp("parse.y", s) == 0) { - // default behavior + rb_ruby_default_parser_set(RB_DEFAULT_PARSER_PARSE_Y); } else { rb_raise(rb_eRuntimeError, "unknown parser %s", s); @@ -1445,21 +1470,12 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char ** ruby_verbose = Qtrue; } else if (strcmp("jit", s) == 0) { -#if USE_YJIT || USE_RJIT +#if USE_YJIT || USE_ZJIT FEATURE_SET(opt->features, FEATURE_BIT(jit)); #else rb_warn("Ruby was built without JIT support"); #endif } - else if (is_option_with_optarg("rjit", '-', true, false, false)) { -#if USE_RJIT - extern void rb_rjit_setup_options(const char *s, struct rb_rjit_options *rjit_opt); - FEATURE_SET(opt->features, FEATURE_BIT(rjit)); - rb_rjit_setup_options(s, &opt->rjit); -#else - rb_warn("RJIT support is disabled."); -#endif - } else if (is_option_with_optarg("yjit", '-', true, false, false)) { #if USE_YJIT FEATURE_SET(opt->features, FEATURE_BIT(yjit)); @@ -1469,6 +1485,15 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char ** " You may need to install rustc to build Ruby with YJIT."); #endif } + else if (is_option_with_optarg("zjit", '-', true, false, false)) { +#if USE_ZJIT + FEATURE_SET(opt->features, FEATURE_BIT(zjit)); + setup_zjit_options(s); +#else + rb_warn("Ruby was built without ZJIT support." + " You may need to install rustc to build Ruby with ZJIT."); +#endif + } else if (strcmp("yydebug", s) == 0) { if (envopt) goto noenvopt_long; opt->dump |= DUMP_BIT(yydebug); @@ -1709,11 +1734,27 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt) if (!s[1]) break; - default: + default: { + rb_encoding *enc = IF_UTF8_PATH(rb_utf8_encoding(), rb_locale_encoding()); + const char *e = s + strlen(s); + int r = rb_enc_precise_mbclen(s, e, enc); + unsigned int c = (unsigned char)*s; + if (r > 0) { + c = rb_enc_mbc_to_codepoint(s, e, enc); + if (ONIGENC_IS_CODE_GRAPH(enc, c) || + ((s = ruby_escaped_char(c)) != 0 && + (r = (int)strlen(s), /* 3 at most */ 1))) { + rb_enc_raise(enc, rb_eRuntimeError, + "invalid option -%.*s (-h will show valid options)", + r, s); + } + } rb_raise(rb_eRuntimeError, - "invalid option -%c (-h will show valid options)", - (int)(unsigned char)*s); + "invalid option -\\x%.2x (-h will show valid options)", + c); + goto switch_end; + } noenvopt: /* "EIdvwWrKU" only */ @@ -1736,7 +1777,6 @@ static void ruby_init_prelude(void) { Init_builtin_features(); - rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX")); } void rb_call_builtin_inits(void); @@ -1771,28 +1811,6 @@ ruby_opt_init(ruby_cmdline_options_t *opt) } } - /* [Feature #19785] Warning for removed GC environment variable. - * Remove this in Ruby 3.4. */ - if (getenv("RUBY_GC_HEAP_INIT_SLOTS")) { - rb_warn_deprecated("The environment variable RUBY_GC_HEAP_INIT_SLOTS", - "environment variables RUBY_GC_HEAP_%d_INIT_SLOTS"); - } - - if (getenv("RUBY_FREE_AT_EXIT")) { - rb_warn("Free at exit is experimental and may be unstable"); - rb_free_at_exit = true; - } - -#if USE_RJIT - // rb_call_builtin_inits depends on RubyVM::RJIT.enabled? - if (opt->rjit.on) - rb_rjit_enabled = true; - if (opt->rjit.stats) - rb_rjit_stats_enabled = true; - if (opt->rjit.trace_exits) - rb_rjit_trace_exits_enabled = true; -#endif - Init_ext(); /* load statically linked extensions before rubygems */ Init_extra_exts(); @@ -1803,15 +1821,20 @@ ruby_opt_init(ruby_cmdline_options_t *opt) ruby_init_prelude(); - // Initialize JITs after prelude because JITing prelude is typically not optimal. -#if USE_RJIT - // Also, rb_rjit_init is safe only after rb_call_builtin_inits() defines RubyVM::RJIT::Compiler. - if (opt->rjit.on) - rb_rjit_init(&opt->rjit); -#endif + /* Initialize the main box after loading libraries (including rubygems) + * to enable those in both root and main */ + if (rb_box_available()) + rb_initialize_main_box(); + rb_box_init_done(); + + // Initialize JITs after ruby_init_prelude() because JITing prelude is typically not optimal. #if USE_YJIT rb_yjit_init(opt->yjit); #endif +#if USE_ZJIT + extern void rb_zjit_init(bool); + rb_zjit_init(opt->zjit); +#endif ruby_set_script_name(opt->script_name); require_libraries(&opt->req_list); @@ -1977,7 +2000,7 @@ copy_str(VALUE str, rb_encoding *enc, bool intern) return rb_enc_interned_str(RSTRING_PTR(str), RSTRING_LEN(str), enc); } -#if USE_YJIT +#if USE_YJIT || USE_ZJIT // Check that an environment variable is set to a truthy value static bool env_var_truthy(const char *name) @@ -2098,6 +2121,49 @@ process_script(ruby_cmdline_options_t *opt) return ast_value; } +static uint8_t +prism_script_command_line(ruby_cmdline_options_t *opt) +{ + uint8_t command_line = 0; + if (opt->do_split) command_line |= PM_OPTIONS_COMMAND_LINE_A; + if (opt->do_line) command_line |= PM_OPTIONS_COMMAND_LINE_L; + if (opt->do_loop) command_line |= PM_OPTIONS_COMMAND_LINE_N; + if (opt->do_print) command_line |= PM_OPTIONS_COMMAND_LINE_P; + if (opt->xflag) command_line |= PM_OPTIONS_COMMAND_LINE_X; + return command_line; +} + +static void +prism_script_shebang_callback(pm_options_t *options, const uint8_t *source, size_t length, void *data) +{ + ruby_cmdline_options_t *opt = (ruby_cmdline_options_t *) data; + opt->warning = 0; + + char *switches = malloc(length + 1); + memcpy(switches, source, length); + switches[length] = '\0'; + + int no_src_enc = !opt->src.enc.name; + int no_ext_enc = !opt->ext.enc.name; + int no_int_enc = !opt->intern.enc.name; + + moreswitches(switches, opt, 0); + free(switches); + + pm_options_command_line_set(options, prism_script_command_line(opt)); + + if (no_src_enc && opt->src.enc.name) { + opt->src.enc.index = opt_enc_index(opt->src.enc.name); + pm_options_encoding_set(options, StringValueCStr(opt->ext.enc.name)); + } + if (no_ext_enc && opt->ext.enc.name) { + opt->ext.enc.index = opt_enc_index(opt->ext.enc.name); + } + if (no_int_enc && opt->intern.enc.name) { + opt->intern.enc.index = opt_enc_index(opt->intern.enc.name); + } +} + /** * Process the command line options and parse the script into the given result. * Raise an error if the script cannot be parsed. @@ -2109,44 +2175,63 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result) pm_options_t *options = &result->options; pm_options_line_set(options, 1); + pm_options_main_script_set(options, true); - if (opt->ext.enc.name != 0) { - pm_options_encoding_set(options, StringValueCStr(opt->ext.enc.name)); - } + const bool read_stdin = (strcmp(opt->script, "-") == 0); - uint8_t command_line = 0; - if (opt->do_split) command_line |= PM_OPTIONS_COMMAND_LINE_A; - if (opt->do_line) command_line |= PM_OPTIONS_COMMAND_LINE_L; - if (opt->do_loop) command_line |= PM_OPTIONS_COMMAND_LINE_N; - if (opt->do_print) command_line |= PM_OPTIONS_COMMAND_LINE_P; - if (opt->xflag) command_line |= PM_OPTIONS_COMMAND_LINE_X; + if (read_stdin) { + pm_options_encoding_set(options, rb_enc_name(rb_locale_encoding())); + } + if (opt->src.enc.name != 0) { + pm_options_encoding_set(options, StringValueCStr(opt->src.enc.name)); + } + uint8_t command_line = prism_script_command_line(opt); VALUE error; - if (strcmp(opt->script, "-") == 0) { + + if (read_stdin) { pm_options_command_line_set(options, command_line); pm_options_filepath_set(options, "-"); + pm_options_shebang_callback_set(options, prism_script_shebang_callback, (void *) opt); ruby_opt_init(opt); error = pm_parse_stdin(result); + + // If we found an __END__ marker, then we're going to define a global + // DATA constant that is a file object that can be read to read the + // contents after the marker. + if (NIL_P(error) && result->parser.data_loc.start != NULL) { + rb_define_global_const("DATA", rb_stdin); + } } else if (opt->e_script) { - command_line |= PM_OPTIONS_COMMAND_LINE_E; + command_line = (uint8_t) ((command_line | PM_OPTIONS_COMMAND_LINE_E) & ~PM_OPTIONS_COMMAND_LINE_X); pm_options_command_line_set(options, command_line); ruby_opt_init(opt); result->node.coverage_enabled = 0; - error = pm_parse_string(result, opt->e_script, rb_str_new2("-e")); + error = pm_parse_string(result, opt->e_script, rb_str_new2("-e"), NULL); } else { + VALUE script_name = rb_str_encode_ospath(opt->script_name); + pm_options_command_line_set(options, command_line); - error = pm_load_file(result, opt->script_name, true); + pm_options_shebang_callback_set(options, prism_script_shebang_callback, (void *) opt); + + error = pm_load_file(result, script_name, true); // If reading the file did not error, at that point we load the command // line options. We do it in this order so that if the main script fails // to load, it doesn't require files required by -r. if (NIL_P(error)) { ruby_opt_init(opt); - error = pm_parse_file(result, opt->script_name); + error = pm_parse_file(result, opt->script_name, NULL); + } + + // Check if (after requiring all of the files through -r flags) we have + // coverage enabled and need to enable coverage on the main script. + if (RTEST(rb_get_coverages())) { + result->node.coverage_enabled = 1; } // If we found an __END__ marker, then we're going to define a global @@ -2154,7 +2239,7 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result) // contents after the marker. if (NIL_P(error) && result->parser.data_loc.start != NULL) { int xflag = opt->xflag; - VALUE file = open_load_file(opt->script_name, &xflag); + VALUE file = open_load_file(script_name, &xflag); const pm_parser_t *parser = &result->parser; size_t offset = parser->data_loc.start - parser->start + 7; @@ -2237,8 +2322,8 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) char fbuf[MAXPATHLEN]; int i = (int)proc_options(argc, argv, opt, 0); unsigned int dump = opt->dump & dump_exit_bits; - rb_vm_t *vm = GET_VM(); - const long loaded_before_enc = RARRAY_LEN(vm->loaded_features); + const rb_box_t *box = rb_root_box(); + const long loaded_before_enc = RARRAY_LEN(box->loaded_features); if (opt->dump & (DUMP_BIT(usage)|DUMP_BIT(help))) { const char *const progname = @@ -2268,23 +2353,35 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) FEATURE_SET(opt->features, FEATURE_BIT(yjit)); } #endif +#if USE_ZJIT + if (!FEATURE_USED_P(opt->features, zjit) && env_var_truthy("RUBY_ZJIT_ENABLE")) { + FEATURE_SET(opt->features, FEATURE_BIT(zjit)); + + // When the --zjit flag is specified, we would have call setup_zjit_options(""), + // which would have called rb_zjit_prepare_options() internally. This ensures we + // go through the same set up but with less overhead than setup_zjit_options(""). + extern void rb_zjit_prepare_options(); + rb_zjit_prepare_options(); + } +#endif } if (MULTI_BITS_P(FEATURE_SET_BITS(opt->features) & feature_jit_mask)) { - rb_warn("RJIT and YJIT cannot both be enabled at the same time. Exiting"); + rb_warn("Only one JIT can be enabled at the same time. Exiting"); return Qfalse; } -#if USE_RJIT - if (FEATURE_SET_P(opt->features, rjit)) { - opt->rjit.on = true; // set opt->rjit.on for Init_ruby_description() and calling rb_rjit_init() - } -#endif #if USE_YJIT if (FEATURE_SET_P(opt->features, yjit)) { bool rb_yjit_option_disable(void); opt->yjit = !rb_yjit_option_disable(); // set opt->yjit for Init_ruby_description() and calling rb_yjit_init() } #endif +#if USE_ZJIT + if (FEATURE_SET_P(opt->features, zjit)) { + bool rb_zjit_option_enable(void); + opt->zjit = rb_zjit_option_enable(); // set opt->zjit for Init_ruby_description() and calling rb_zjit_init() + } +#endif ruby_mn_threads_params(); Init_ruby_description(opt); @@ -2379,7 +2476,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) rb_obj_freeze(opt->script_name); if (IF_UTF8_PATH(uenc != lenc, 1)) { long i; - VALUE load_path = vm->load_path; + VALUE load_path = box->load_path; const ID id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK; int modifiable = FALSE; @@ -2402,11 +2499,11 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) RARRAY_ASET(load_path, i, path); } if (modifiable) { - rb_ary_replace(vm->load_path_snapshot, load_path); + rb_ary_replace(box->load_path_snapshot, load_path); } } { - VALUE loaded_features = vm->loaded_features; + VALUE loaded_features = box->loaded_features; bool modified = false; for (long i = loaded_before_enc; i < RARRAY_LEN(loaded_features); ++i) { VALUE path = RARRAY_AREF(loaded_features, i); @@ -2418,7 +2515,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) RARRAY_ASET(loaded_features, i, path); } if (modified) { - rb_ary_replace(vm->loaded_features_snapshot, loaded_features); + rb_ary_replace(box->loaded_features_snapshot, loaded_features); } } @@ -2427,7 +2524,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) #define SET_COMPILE_OPTION(h, o, name) \ rb_hash_aset((h), ID2SYM(rb_intern_const(#name)), \ RBOOL(FEATURE_SET_P(o->features, name))) - SET_COMPILE_OPTION(option, opt, frozen_string_literal); + + if (FEATURE_SET_P(opt->features, frozen_string_literal_set)) { + SET_COMPILE_OPTION(option, opt, frozen_string_literal); + } SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal); rb_funcallv(rb_cISeq, rb_intern_const("compile_option="), 1, &option); #undef SET_COMPILE_OPTION @@ -2454,7 +2554,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) rb_enc_associate(opt->e_script, eenc); } - if (!(*rb_ruby_prism_ptr())) { + if (!rb_ruby_prism_p()) { ast_value = process_script(opt); if (!(result.ast = rb_ruby_ast_data_get(ast_value))) return Qfalse; } @@ -2490,7 +2590,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) if (dump & DUMP_BIT(syntax)) { printf("Syntax OK\n"); dump &= ~DUMP_BIT(syntax); - if (!dump) return Qtrue; + if (!dump) { + dispose_result(); + return Qtrue; + } } if (dump & DUMP_BIT(parsetree)) { @@ -2533,8 +2636,15 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) if (!result.ast) { pm_parse_result_t *pm = &result.prism; - iseq = pm_iseq_new_main(&pm->node, opt->script_name, path, parent, optimize); + int error_state; + iseq = pm_iseq_new_main(&pm->node, opt->script_name, path, parent, optimize, &error_state); + pm_parse_result_free(pm); + + if (error_state) { + RUBY_ASSERT(iseq == NULL); + rb_jump_tag(error_state); + } } else { rb_ast_t *ast = result.ast; @@ -3068,8 +3178,6 @@ ruby_process_options(int argc, char **argv) VALUE iseq; const char *script_name = (argc > 0 && argv[0]) ? argv[0] : ruby_engine; - (*rb_ruby_prism_ptr()) = false; - if (!origarg.argv || origarg.argc <= 0) { origarg.argc = argc; origarg.argv = argv; @@ -3082,12 +3190,18 @@ ruby_process_options(int argc, char **argv) ruby_init_setproctitle(argc, argv); #endif + if (getenv("RUBY_FREE_AT_EXIT")) { + rb_free_at_exit = true; + rb_category_warn(RB_WARN_CATEGORY_EXPERIMENTAL, "Free at exit is experimental and may be unstable"); + } + iseq = process_options(argc, argv, cmdline_options_init(&opt)); if (opt.crash_report && *opt.crash_report) { void ruby_set_crash_report(const char *template); ruby_set_crash_report(opt.crash_report); } + return (void*)(struct RData*)iseq; } @@ -3133,3 +3247,9 @@ ruby_sysinit(int *argc, char ***argv) } fill_standard_fds(); } + +#ifdef RUBY_ASAN_ENABLED +RUBY_SYMBOL_EXPORT_BEGIN +const char ruby_asan_default_options[] = "use_sigaltstack=0:detect_leaks=0"; +RUBY_SYMBOL_EXPORT_END +#endif |
