Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

YJIT: Move help descriptions to options.rs #8583

Merged
merged 5 commits into from Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
79 changes: 45 additions & 34 deletions ruby.c
Expand Up @@ -241,45 +241,69 @@ static const char esc_standout[] = "\n\033[1;7m";
static const char esc_bold[] = "\033[1m";
static const char esc_reset[] = "\033[0m";
static const char esc_none[] = "";
#define USAGE_INDENT " " /* macro for concatenation */

static void
show_usage_line(const struct ruby_opt_message *m,
show_usage_part(const char *str, const unsigned int namelen,
const char *str2, const unsigned int secondlen,
const char *desc,
int help, int highlight, unsigned int w, int columns)
{
const char *str = m->str;
const unsigned int namelen = m->namelen, secondlen = m->secondlen;
static const int indent_width = (int)rb_strlen_lit(USAGE_INDENT);
const char *sb = highlight ? esc_bold : esc_none;
const char *se = highlight ? esc_reset : esc_none;
const char *desc = str + namelen + secondlen;
unsigned int desclen = (unsigned int)strcspn(desc, "\n");
if (help && (namelen > w) && (int)(namelen + secondlen) >= columns) {
printf(" %s" "%.*s" "%s\n", sb, namelen-1, str, se);
if (secondlen > 1) {
const int second_end = namelen+secondlen-1;
int n = namelen;
if (str[n] == ',') n++;
if (str[n] == ' ') n++;
printf(" %s" "%.*s" "%s\n", sb, second_end-n, str+n, se);
if (help && (namelen + 1 > w) && /* a padding space */
(int)(namelen + secondlen + indent_width) >= columns) {
printf(USAGE_INDENT "%s" "%.*s" "%s\n", sb, namelen, str, se);
if (secondlen > 0) {
const int second_end = secondlen;
int n = 0;
if (str2[n] == ',') n++;
if (str2[n] == ' ') n++;
printf(USAGE_INDENT "%s" "%.*s" "%s\n", sb, second_end-n, str2+n, se);
}
printf("%-*s%.*s\n", w + 2, "", desclen, desc);
printf("%-*s%.*s\n", w + indent_width, USAGE_INDENT, desclen, desc);
}
else {
const int wrap = help && namelen + secondlen - 1 > w;
printf(" %s%.*s%-*.*s%s%-*s%.*s\n", sb, namelen-1, str,
(wrap ? 0 : w - namelen + 1),
(help ? secondlen-1 : 0), str + namelen, se,
(wrap ? w + 3 : 0), (wrap ? "\n" : ""),
const int wrap = help && namelen + secondlen >= w;
printf(USAGE_INDENT "%s%.*s%-*.*s%s%-*s%.*s\n", sb, namelen, str,
(wrap ? 0 : w - namelen),
(help ? secondlen : 0), str2, se,
(wrap ? (int)(w + rb_strlen_lit("\n" USAGE_INDENT)) : 0),
(wrap ? "\n" USAGE_INDENT : ""),
desclen, desc);
}
if (help) {
while (desc[desclen]) {
desc += desclen + 1;
desc += desclen + rb_strlen_lit("\n");
desclen = (unsigned int)strcspn(desc, "\n");
printf("%-*s%.*s\n", w + 2, "", desclen, desc);
printf("%-*s%.*s\n", w + indent_width, USAGE_INDENT, desclen, desc);
}
}
}

static void
show_usage_line(const struct ruby_opt_message *m,
int help, int highlight, unsigned int w, int columns)
{
const char *str = m->str;
const unsigned int namelen = m->namelen, secondlen = m->secondlen;
const char *desc = str + namelen + secondlen;
show_usage_part(str, namelen - 1, str + namelen, secondlen - 1, desc,
help, highlight, w, columns);
}

void
ruby_show_usage_line(const char *name, const char *secondary, const char *description,
int help, int highlight, unsigned int width, int columns)
{
unsigned int namelen = (unsigned int)strlen(name);
unsigned int secondlen = (secondary ? (unsigned int)strlen(secondary) : 0);
show_usage_part(name, namelen, secondary, secondlen,
description, help, highlight, width, columns);
}

static void
usage(const char *name, int help, int highlight, int columns)
{
Expand Down Expand Up @@ -367,18 +391,6 @@ usage(const char *name, int help, int highlight, int columns)
M("experimental", "", "experimental features"),
M("performance", "", "performance issues"),
};
#if USE_YJIT
static const struct ruby_opt_message yjit_options[] = {
M("--yjit-stats", "", "Enable collecting YJIT statistics"),
M("--yjit-trace-exits", "", "Record Ruby source location when exiting from generated code"),
M("--yjit-trace-exits-sample-rate", "", "Trace exit locations only every Nth occurrence"),
M("--yjit-exec-mem-size=num", "", "Size of executable memory block in MiB (default: 128)"),
M("--yjit-call-threshold=num", "", "Number of calls to trigger JIT (default: 30)"),
M("--yjit-cold-threshold=num", "", "Global call after which ISEQs not compiled (default: 200K)"),
M("--yjit-max-versions=num", "", "Maximum number of versions per basic block (default: 4)"),
M("--yjit-greedy-versioning", "", "Greedy versioning mode (default: disabled)"),
};
#endif
#if USE_RJIT
extern const struct ruby_opt_message rb_rjit_option_messages[];
#endif
Expand Down Expand Up @@ -410,8 +422,7 @@ usage(const char *name, int help, int highlight, int columns)
SHOW(warn_categories[i]);
#if USE_YJIT
printf("%s""YJIT options:%s\n", sb, se);
for (i = 0; i < numberof(yjit_options); ++i)
SHOW(yjit_options[i]);
rb_yjit_show_usage(help, highlight, w, columns);
#endif
#if USE_RJIT
printf("%s""RJIT options (experimental):%s\n", sb, se);
Expand Down
1 change: 1 addition & 0 deletions yjit.h
Expand Up @@ -43,6 +43,7 @@ void rb_yjit_iseq_free(void *payload);
void rb_yjit_before_ractor_spawn(void);
void rb_yjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx);
void rb_yjit_tracing_invalidate_all(void);
void rb_yjit_show_usage(int help, int highlight, unsigned int width, int columns);

#else
// !USE_YJIT
Expand Down
29 changes: 28 additions & 1 deletion yjit/src/options.rs
@@ -1,5 +1,6 @@
use std::ffi::CStr;
use std::{ffi::{CStr, CString}, ptr::null};
use crate::backend::current::TEMP_REGS;
use std::os::raw::{c_char, c_int, c_uint};

// Command-line options
#[derive(Clone, PartialEq, Eq, Debug)]
Expand Down Expand Up @@ -79,6 +80,17 @@ pub static mut OPTIONS: Options = Options {
dump_iseq_disasm: None,
};

static YJIT_OPTIONS: [(&str, &str); 8] = [
("--yjit-stats", "Enable collecting YJIT statistics"),
("--yjit-trace-exits", "Record Ruby source location when exiting from generated code"),
("--yjit-trace-exits-sample-rate", "Trace exit locations only every Nth occurrence"),
("--yjit-exec-mem-size=num", "Size of executable memory block in MiB (default: 128)"),
("--yjit-call-threshold=num", "Number of calls to trigger JIT (default: 30)"),
("--yjit-cold-threshold=num", "Global call after which ISEQs not compiled (default: 200K)"),
("--yjit-max-versions=num", "Maximum number of versions per basic block (default: 4)"),
("--yjit-greedy-versioning", "Greedy versioning mode (default: disabled)"),
];

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum DumpDisasm {
// Dump to stdout
Expand Down Expand Up @@ -231,3 +243,18 @@ pub fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> {
// Option successfully parsed
return Some(());
}

/// Print YJIT options for `ruby --help`. `width` is width of option parts, and
/// `columns` is indent width of descriptions.
#[no_mangle]
pub extern "C" fn rb_yjit_show_usage(help: c_int, highlight: c_int, width: c_uint, columns: c_int) {
for &(name, description) in YJIT_OPTIONS.iter() {
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) }
}
}