ZJIT: Handle ZJIT options properly (#13197)

This commit is contained in:
Takashi Kokubun 2025-04-29 09:50:05 -07:00 committed by GitHub
parent 10fd5a6357
commit 608fe6ee53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2025-04-29 16:50:20 +00:00
Merged-By: k0kubun <takashikkbn@gmail.com>
2 changed files with 57 additions and 18 deletions

26
ruby.c
View File

@ -307,7 +307,9 @@ 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"
# define DEFAULT_JIT_OPTION "--yjit"
#elif USE_ZJIT
# define DEFAULT_JIT_OPTION "--zjit"
#endif
/* This message really ought to be max 23 lines.
@ -338,13 +340,15 @@ 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."),
#if USE_YJIT
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
M("--zjit", "", "Enable in-process JIT compiler."),
#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) < 26);
@ -381,6 +385,9 @@ usage(const char *name, int help, int highlight, int columns)
M("frozen-string-literal", "", "Freeze all string literals (default: disabled)."),
#if USE_YJIT
M("yjit", "", "In-process JIT compiler (default: disabled)."),
#endif
#if USE_ZJIT
M("zjit", "", "Method-based JIT compiler (default: disabled)."),
#endif
};
static const struct ruby_opt_message warn_categories[] = {
@ -419,6 +426,11 @@ 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_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
}
#define rubylib_path_new rb_str_new
@ -1993,7 +2005,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)
@ -2345,6 +2357,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
if (!FEATURE_USED_P(opt->features, yjit) && env_var_truthy("RUBY_YJIT_ENABLE")) {
FEATURE_SET(opt->features, FEATURE_BIT(yjit));
}
#elif USE_ZJIT
if (!FEATURE_USED_P(opt->features, zjit) && env_var_truthy("RUBY_ZJIT_ENABLE")) {
FEATURE_SET(opt->features, FEATURE_BIT(zjit));
}
#endif
}
if (MULTI_BITS_P(FEATURE_SET_BITS(opt->features) & feature_jit_mask)) {

View File

@ -1,4 +1,5 @@
use std::{ffi::CStr, os::raw::c_char};
use std::{ffi::{CStr, CString}, ptr::null};
use std::os::raw::{c_char, c_int, c_uint};
/// Number of calls to start profiling YARV instructions.
/// They are profiled `rb_zjit_call_threshold - rb_zjit_profile_threshold` times,
@ -34,6 +35,25 @@ pub struct Options {
pub dump_disasm: bool,
}
/// Return an Options with default values
pub fn init_options() -> Options {
Options {
num_profiles: 1,
debug: false,
dump_hir_init: None,
dump_hir_opt: None,
dump_lir: false,
dump_disasm: false,
}
}
/// `ruby --help` descriptions for user-facing options. Do not add options for ZJIT developers.
/// Note that --help allows only 80 chars per line, including indentation. 80-char limit --> |
pub const ZJIT_OPTIONS: &'static [(&str, &str)] = &[
("--zjit-call-threshold=num", "Number of calls to trigger JIT (default: 2)."),
("--zjit-num-profiles=num", "Number of profiled calls before JIT (default: 1)."),
];
#[derive(Clone, Copy, Debug)]
pub enum DumpHIR {
// Dump High-level IR without Snapshot
@ -66,18 +86,6 @@ pub extern "C" fn rb_zjit_init_options() -> *const u8 {
Box::into_raw(Box::new(options)) as *const u8
}
/// Return an Options with default values
pub fn init_options() -> Options {
Options {
num_profiles: 1,
debug: false,
dump_hir_init: None,
dump_hir_opt: None,
dump_lir: false,
dump_disasm: false,
}
}
/// Parse a --zjit* command-line flag
#[unsafe(no_mangle)]
pub extern "C" fn rb_zjit_parse_option(options: *const u8, str_ptr: *const c_char) -> bool {
@ -155,6 +163,21 @@ fn update_profile_threshold(options: &Options) {
}
}
/// Print YJIT options for `ruby --help`. `width` is width of option parts, and
/// `columns` is indent width of descriptions.
#[unsafe(no_mangle)]
pub extern "C" fn rb_zjit_show_usage(help: c_int, highlight: c_int, width: c_uint, columns: c_int) {
for &(name, description) in ZJIT_OPTIONS.iter() {
unsafe extern "C" {
fn ruby_show_usage_line(name: *const c_char, secondary: *const c_char, description: *const c_char,
help: c_int, highlight: c_int, width: c_uint, columns: c_int);
}
let name = CString::new(name).unwrap();
let description = CString::new(description).unwrap();
unsafe { ruby_show_usage_line(name.as_ptr(), null(), description.as_ptr(), help, highlight, width, columns) }
}
}
/// Macro to print a message only when --zjit-debug is given
macro_rules! debug {
($($msg:tt)*) => {