Rename --jit to --mjit (#5248)

* Rename --jit to --mjit

[Feature #18349]

* Fix a few more --jit references

* Fix MJIT Actions

* More s/jit/mjit/ and re-introduce --disable-jit

* Update NEWS.md

* Fix test_bug_reporter_add
This commit is contained in:
Takashi Kokubun 2021-12-13 16:08:01 -08:00 committed by GitHub
parent 94494a565d
commit 11b8aaa26a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
Notes: git 2021-12-14 09:08:31 +09:00
Merged-By: k0kubun <takashikkbn@gmail.com>
16 changed files with 111 additions and 64 deletions

View File

@ -20,12 +20,12 @@ jobs:
strategy:
matrix:
test_task: [ "check" ] # to make job names consistent
jit_opts: [ "--jit", "--jit-wait" ]
jit_opts: [ "--mjit", "--mjit-wait" ]
fail-fast: false
runs-on: ubuntu-latest
env:
TESTOPTS: '-q --tty=no'
RUN_OPTS: '--disable-gems ${{ matrix.jit_opts }} --jit-debug=-ggdb3'
RUN_OPTS: '--disable-gems ${{ matrix.jit_opts }} --mjit-debug=-ggdb3'
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
steps:
- run: mkdir build

11
NEWS.md
View File

@ -419,9 +419,14 @@ Excluding feature bug fixes.
This feature is turned off by default and can be enabled by compiling Ruby
with flag `USE_RVARGC=1` set. [[Feature #18045]] [[Feature #18239]]
### JIT
## JIT
* The default `--jit-max-cache` is changed from 100 to 10000.
* Rename Ruby 3.0's `--jit` to `--mjit`, and alias `--jit` to `--yjit`
on non-Windows x86-64 platforms and to `--mjit` on others.
### MJIT
* The default `--mjit-max-cache` is changed from 100 to 10000.
* JIT-ed code is no longer cancelled when a TracePoint for class events
is enabled.
@ -429,7 +434,7 @@ Excluding feature bug fixes.
* The JIT compiler no longer skips compilation of methods longer than
1000 instructions.
* `--jit-verbose` and `--jit-warning` output "JIT cancel" when JIT-ed
* `--mjit-verbose` and `--mjit-warning` output "JIT cancel" when JIT-ed
code is disabled because TracePoint or GC.compact is used.
* `RubyVM::MJIT` is renamed to `RubyVM::JIT`. [[Feature #17490]]

View File

@ -249,7 +249,7 @@ static char *tmp_dir;
static const char *cc_path;
// Used C compiler flags.
static const char **cc_common_args;
// Used C compiler flags added by --jit-debug=...
// Used C compiler flags added by --mjit-debug=...
static char **cc_added_args;
// Name of the precompiled header file.
static char *pch_file;
@ -686,7 +686,7 @@ remove_so_file(const char *so_file, struct rb_mjit_unit *unit)
#endif
}
// Print _mjitX, but make a human-readable funcname when --jit-debug is used
// Print _mjitX, but make a human-readable funcname when --mjit-debug is used
static void
sprint_funcname(char *funcname, const struct rb_mjit_unit *unit)
{

62
ruby.c
View File

@ -103,7 +103,7 @@ void rb_warning_category_update(unsigned int mask, unsigned int bits);
SEP \
X(frozen_string_literal) \
SEP \
X(jit) \
X(mjit) \
SEP \
X(yjit)
/* END OF FEATURES */
@ -220,7 +220,7 @@ enum {
& ~FEATURE_BIT(gems)
#endif
& ~FEATURE_BIT(frozen_string_literal)
& ~FEATURE_BIT(jit)
& ~FEATURE_BIT(mjit)
& ~FEATURE_BIT(yjit)
)
};
@ -235,7 +235,7 @@ cmdline_options_init(ruby_cmdline_options_t *opt)
opt->intern.enc.index = -1;
opt->features.set = DEFAULT_FEATURES;
#ifdef MJIT_FORCE_ENABLE /* to use with: ./configure cppflags="-DMJIT_FORCE_ENABLE" */
opt->features.set |= FEATURE_BIT(jit);
opt->features.set |= FEATURE_BIT(mjit);
#elif defined(YJIT_FORCE_ENABLE)
opt->features.set |= FEATURE_BIT(yjit);
#endif
@ -291,6 +291,11 @@ usage(const char *name, int help, int highlight, int columns)
(unsigned short)sizeof(shortopt), \
(unsigned short)sizeof(longopt), \
}
#if YJIT_SUPPORTED_P
# define PLATFORM_JIT_OPTION "--yjit"
#else
# define PLATFORM_JIT_OPTION "--mjit"
#endif
static const struct message usage_msg[] = {
M("-0[octal]", "", "specify record separator (\\0, if no argument)"),
M("-a", "", "autosplit mode with -n or -p (splits $_ into $F)"),
@ -312,8 +317,8 @@ usage(const char *name, int help, int highlight, int columns)
M("-w", "", "turn warnings on for your script"),
M("-W[level=2|:category]", "", "set warning level; 0=silence, 1=medium, 2=verbose"),
M("-x[directory]", "", "strip off text before #!ruby line and perhaps cd to directory"),
M("--jit", "", "enable JIT with default options (experimental)"),
M("--jit-[option]","", "enable JIT with an option (experimental)"),
M("--jit", "", "enable JIT for the platform, same as " PLATFORM_JIT_OPTION " (experimental)"),
M("--mjit", "", "enable C compiler-based JIT compiler (experimental)"),
M("--yjit", "", "enable in-process JIT compiler (experimental)"),
M("-h", "", "show this message, --help for more info"),
};
@ -321,7 +326,7 @@ usage(const char *name, int help, int highlight, int columns)
M("--copyright", "", "print the copyright"),
M("--dump={insns|parsetree|...}[,...]", "",
"dump debug information. see below for available dump list"),
M("--enable={jit|rubyopt|...}[,...]", ", --disable={jit|rubyopt|...}[,...]",
M("--enable={mjit|rubyopt|...}[,...]", ", --disable={mjit|rubyopt|...}[,...]",
"enable or disable features. see below for available features"),
M("--external-encoding=encoding", ", --internal-encoding=encoding",
"specify the default external or internal character encoding"),
@ -343,7 +348,7 @@ usage(const char *name, int help, int highlight, int columns)
M("did_you_mean", "", "did_you_mean (default: "DEFAULT_RUBYGEMS_ENABLED")"),
M("rubyopt", "", "RUBYOPT environment variable (default: enabled)"),
M("frozen-string-literal", "", "freeze all string literals (default: disabled)"),
M("jit", "", "JIT compiler (default: disabled)"),
M("mjit", "", "C compiler-based JIT compiler (default: disabled)"),
M("yjit", "", "in-process JIT compiler (default: disabled)"),
};
static const struct message warn_categories[] = {
@ -351,13 +356,13 @@ usage(const char *name, int help, int highlight, int columns)
M("experimental", "", "experimental features"),
};
static const struct message mjit_options[] = {
M("--jit-warnings", "", "Enable printing JIT warnings"),
M("--jit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"),
M("--jit-wait", "", "Wait until JIT compilation finishes every time (for testing)"),
M("--jit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"),
M("--jit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"),
M("--jit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 100)"),
M("--jit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"),
M("--mjit-warnings", "", "Enable printing JIT warnings"),
M("--mjit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"),
M("--mjit-wait", "", "Wait until JIT compilation finishes every time (for testing)"),
M("--mjit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"),
M("--mjit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"),
M("--mjit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 100)"),
M("--mjit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"),
};
static const struct message yjit_options[] = {
#if YJIT_STATS
@ -952,12 +957,20 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable)
#define SET_FEATURE(bit) \
if (NAME_MATCH_P(#bit, str, len)) {set |= mask = FEATURE_BIT(bit); FEATURE_FOUND;}
EACH_FEATURES(SET_FEATURE, ;);
if (NAME_MATCH_P("jit", str, len)) { // This allows you to cancel --jit
#if defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P
set |= mask = FEATURE_BIT(mjit);
#else
set |= mask = FEATURE_BIT(yjit);
#endif
goto found;
}
if (NAME_MATCH_P("all", str, len)) {
// YJIT and MJIT cannot be enabled at the same time. We enable only YJIT for --enable=all.
#ifdef MJIT_FORCE_ENABLE
#if defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P
mask &= ~(FEATURE_BIT(yjit));
#else
mask &= ~(FEATURE_BIT(jit));
mask &= ~(FEATURE_BIT(mjit));
#endif
goto found;
}
@ -1512,10 +1525,19 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
opt->verbose = 1;
ruby_verbose = Qtrue;
}
else if (strncmp("jit", s, 3) == 0) {
else if (strcmp("jit", s) == 0) {
#if !USE_MJIT
rb_warn("Ruby was built without JIT support");
#elif defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P
FEATURE_SET(opt->features, FEATURE_BIT(mjit));
#else
FEATURE_SET(opt->features, FEATURE_BIT(yjit));
#endif
}
else if (strncmp("mjit", s, 4) == 0) {
#if USE_MJIT
FEATURE_SET(opt->features, FEATURE_BIT(jit));
setup_mjit_options(s + 3, &opt->mjit);
FEATURE_SET(opt->features, FEATURE_BIT(mjit));
setup_mjit_options(s + 4, &opt->mjit);
#else
rb_warn("MJIT support is disabled.");
#endif
@ -1888,7 +1910,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
#if USE_MJIT
if (opt->features.set & FEATURE_BIT(jit)) {
if (opt->features.set & FEATURE_BIT(mjit)) {
opt->mjit.on = TRUE; /* set mjit.on for ruby_show_version() API and check to call mjit_init() */
}
#endif

View File

@ -15,7 +15,7 @@ if inc = arg['i']
scan(/rb_define_global_const\("(RUBY_\w+)",[^;]*?\bMK(?:INT|STR)\(([^()]*)\)/m) do |n, v|
version[n] = src.value(v)
end
arg['RUBY_DESCRIPTION_WITH_JIT'] = src.value('description_with_jit')
arg['RUBY_DESCRIPTION_WITH_MJIT'] = src.value('description_with_mjit')
end
%>baseruby="<%=arg['BASERUBY']%>"
_\

View File

@ -7,7 +7,7 @@ class TestBugReporter < Test::Unit::TestCase
skip if ENV['RUBY_ON_BUG']
description = RUBY_DESCRIPTION
description = description.sub(/\+JIT /, '') if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
description = description.sub(/\+MJIT /, '') if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
description = description.sub(/\+YJIT /, '') if defined?(RubyVM::YJIT.enabled?) && RubyVM::YJIT.enabled?
expected_stderr = [
:*,

View File

@ -21,7 +21,7 @@ module JITSupport
]
module_function
# Run Ruby script with --jit-wait (Synchronous JIT compilation).
# Run Ruby script with --mjit-wait (Synchronous JIT compilation).
# Returns [stdout, stderr]
def eval_with_jit(env = nil, script, **opts)
stdout, stderr = nil, nil
@ -36,13 +36,13 @@ module JITSupport
def eval_with_jit_without_retry(env = nil, script, verbose: 0, min_calls: 5, save_temps: false, max_cache: 1000, wait: true, timeout: JIT_TIMEOUT)
args = [
'--disable-gems', "--jit-verbose=#{verbose}",
"--jit-min-calls=#{min_calls}", "--jit-max-cache=#{max_cache}",
'--disable-gems', "--mjit-verbose=#{verbose}",
"--mjit-min-calls=#{min_calls}", "--mjit-max-cache=#{max_cache}",
]
args << '--disable-yjit'
args << '--jit-wait' if wait
args << '--jit-save-temps' if save_temps
args << '--jit-debug' if defined?(@jit_debug) && @jit_debug
args << '--mjit-wait' if wait
args << '--mjit-save-temps' if save_temps
args << '--mjit-debug' if defined?(@mjit_debug) && @mjit_debug
args << '-e' << script
base_env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' } # workaround to skip requiring `make install` for `make test-all`
if preloadenv = RbConfig::CONFIG['PRELOADENV'] and !preloadenv.empty?

View File

@ -1194,8 +1194,8 @@ class TestJIT < Test::Unit::TestCase
out, err = eval_with_jit(script, verbose: 1, min_calls: min_calls, max_cache: max_cache)
success_actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
recompile_actual = err.scan(/^#{JIT_RECOMPILE_PREFIX}:/).size
# Add --jit-verbose=2 logs for cl.exe because compiler's error message is suppressed
# for cl.exe with --jit-verbose=1. See `start_process` in mjit_worker.c.
# Add --mjit-verbose=2 logs for cl.exe because compiler's error message is suppressed
# for cl.exe with --mjit-verbose=1. See `start_process` in mjit_worker.c.
if RUBY_PLATFORM.match?(/mswin/) && success_count != success_actual
out2, err2 = eval_with_jit(script, verbose: 2, min_calls: min_calls, max_cache: max_cache)
end

View File

@ -11,7 +11,7 @@ class TestJITDebug < TestJIT
def setup
super
# let `#eval_with_jit` use --jit-debug
@jit_debug = true
# let `#eval_with_jit` use --mjit-debug
@mjit_debug = true
end
end

View File

@ -11,7 +11,7 @@ class TestRubyOptions < Test::Unit::TestCase
NO_JIT_DESCRIPTION =
if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # checking -DMJIT_FORCE_ENABLE
RUBY_DESCRIPTION.sub(/\+JIT /, '')
RUBY_DESCRIPTION.sub(/\+MJIT /, '')
elsif yjit_enabled? # checking -DYJIT_FORCE_ENABLE
RUBY_DESCRIPTION.sub(/\+YJIT /, '')
else
@ -137,7 +137,7 @@ class TestRubyOptions < Test::Unit::TestCase
VERSION_PATTERN_WITH_JIT =
case RUBY_ENGINE
when 'ruby'
/^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+JIT \[#{q[RUBY_PLATFORM]}\]$/
/^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+MJIT \[#{q[RUBY_PLATFORM]}\]$/
else
VERSION_PATTERN
end
@ -226,9 +226,14 @@ class TestRubyOptions < Test::Unit::TestCase
return if yjit_force_enabled?
[
%w(--version --jit --disable=jit),
%w(--version --enable=jit --disable=jit),
%w(--version --enable-jit --disable-jit),
%w(--version --mjit --disable=mjit),
%w(--version --enable=mjit --disable=mjit),
%w(--version --enable-mjit --disable-mjit),
*([
%w(--version --jit --disable=jit),
%w(--version --enable=jit --disable=jit),
%w(--version --enable-jit --disable-jit),
] unless RUBY_PLATFORM.start_with?('x86_64-') && RUBY_PLATFORM !~ /mswin|mingw|msys/),
].each do |args|
assert_in_out_err([env] + args) do |r, e|
assert_match(VERSION_PATTERN, r[0])
@ -239,16 +244,21 @@ class TestRubyOptions < Test::Unit::TestCase
if JITSupport.supported?
[
%w(--version --jit),
%w(--version --enable=jit),
%w(--version --enable-jit),
%w(--version --mjit),
%w(--version --enable=mjit),
%w(--version --enable-mjit),
*([
%w(--version --jit),
%w(--version --enable=jit),
%w(--version --enable-jit),
] unless RUBY_PLATFORM.start_with?('x86_64-') && RUBY_PLATFORM !~ /mswin|mingw|msys/),
].each do |args|
assert_in_out_err([env] + args) do |r, e|
assert_match(VERSION_PATTERN_WITH_JIT, r[0])
if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # checking -DMJIT_FORCE_ENABLE
assert_equal(RUBY_DESCRIPTION, r[0])
else
assert_equal(EnvUtil.invoke_ruby([env, '--jit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
assert_equal(EnvUtil.invoke_ruby([env, '--mjit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
end
assert_equal([], e)
end
@ -1113,7 +1123,7 @@ class TestRubyOptions < Test::Unit::TestCase
# mswin uses prebuilt precompiled header. Thus it does not show a pch compilation log to check "-O0 -O1".
if JITSupport.supported? && !RUBY_PLATFORM.match?(/mswin/)
env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' }
assert_in_out_err([env, "--disable-yjit", "--jit-debug=-O0 -O1", "--jit-verbose=2", "" ], "", [], /-O0 -O1/)
assert_in_out_err([env, "--disable-yjit", "--mjit-debug=-O0 -O1", "--mjit-verbose=2", "" ], "", [], /-O0 -O1/)
end
end

View File

@ -21,6 +21,15 @@ class TestYJIT < Test::Unit::TestCase
%w(--version --disable=yjit --yjit),
%w(--version --disable=yjit --enable-yjit),
%w(--version --disable=yjit --enable=yjit),
*([
%w(--version --jit),
%w(--version --disable-jit --jit),
%w(--version --disable-jit --enable-jit),
%w(--version --disable-jit --enable=jit),
%w(--version --disable=jit --yjit),
%w(--version --disable=jit --enable-jit),
%w(--version --disable=jit --enable=jit),
] if RUBY_PLATFORM.start_with?('x86_64-') && RUBY_PLATFORM !~ /mswin|mingw|msys/),
].each do |version_args|
assert_in_out_err(version_args) do |stdout, stderr|
assert_equal(RUBY_DESCRIPTION, stdout.first)

View File

@ -42,7 +42,7 @@ const char ruby_release_date[] = RUBY_RELEASE_DATE;
const char ruby_platform[] = RUBY_PLATFORM;
const int ruby_patchlevel = RUBY_PATCHLEVEL;
const char ruby_description[] = RUBY_DESCRIPTION_WITH("");
static const char ruby_description_with_jit[] = RUBY_DESCRIPTION_WITH(" +JIT");
static const char ruby_description_with_mjit[] = RUBY_DESCRIPTION_WITH(" +MJIT");
static const char ruby_description_with_yjit[] = RUBY_DESCRIPTION_WITH(" +YJIT");
const char ruby_copyright[] = RUBY_COPYRIGHT;
const char ruby_engine[] = "ruby";
@ -104,7 +104,7 @@ Init_ruby_description(void)
VALUE description;
if (MJIT_OPTS_ON) {
description = MKSTR(description_with_jit);
description = MKSTR(description_with_mjit);
}
else if (rb_yjit_enabled_p()) {
description = MKSTR(description_with_yjit);
@ -123,7 +123,7 @@ void
ruby_show_version(void)
{
if (MJIT_OPTS_ON) {
PRINT(description_with_jit);
PRINT(description_with_mjit);
}
else if (rb_yjit_enabled_p()) {
PRINT(description_with_yjit);

View File

@ -1322,14 +1322,14 @@ clean-local::
$(Q)$(RM) $(arch_hdrdir)/rb_mjit_header-*.$(OBJEXT)
# Non-mswin environment is not using prebuilt precompiled header because upgrading compiler
# or changing compiler options may break MJIT so build (currently only by --jit-debug though).
# or changing compiler options may break MJIT so build (currently only by --mjit-debug though).
#
# But mswin is building precompiled header because cl.exe cannot leave macro after preprocess.
# As a workaround to use macro without installing many source files, it uses precompiled header
# without sufficient guard for a broken build.
#
# TODO: Fix the above issue by including VC version in header name, and create another header
# for --jit-debug as well.
# for --mjit-debug as well.
$(TIMESTAMPDIR)/$(MJIT_PRECOMPILED_HEADER_NAME:.pch=).time: probes.h vm.$(OBJEXT)
$(ECHO) building $(@F:.time=.pch)
$(Q) $(CC) -DMJIT_HEADER $(CFLAGS: -Zi = -Z7 ) $(XCFLAGS:-DRUBY_EXPORT =) -URUBY_EXPORT $(CPPFLAGS) $(srcdir)/vm.c -c -Yc \

12
yjit.c
View File

@ -20,17 +20,11 @@
# define YJIT_DUMP_MODE 0
#endif
#if defined(__x86_64__) && !defined(_WIN32)
# define PLATFORM_SUPPORTED_P 1
#else
# define PLATFORM_SUPPORTED_P 0
#endif
// USE_MJIT comes from configure options
#define JIT_ENABLED USE_MJIT
// Check if we need to include YJIT in the build
#if JIT_ENABLED && PLATFORM_SUPPORTED_P
#if JIT_ENABLED && YJIT_SUPPORTED_P
#include "yjit_asm.c"
@ -165,7 +159,7 @@ static uint32_t yjit_codepage_frozen_bytes = 0;
#include "yjit_codegen.c"
#else
// !JIT_ENABLED || !PLATFORM_SUPPORTED_P
// !JIT_ENABLED || !YJIT_SUPPORTED_P
// In these builds, YJIT could never be turned on. Provide dummy
// implementations for YJIT functions exposed to the rest of the code base.
// See yjit.h.
@ -190,4 +184,4 @@ void rb_yjit_before_ractor_spawn(void) {}
void rb_yjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic) {}
void rb_yjit_tracing_invalidate_all(void) {}
#endif // if JIT_ENABLED && PLATFORM_SUPPORTED_P
#endif // if JIT_ENABLED && YJIT_SUPPORTED_P

7
yjit.h
View File

@ -15,6 +15,13 @@
# define YJIT_STATS RUBY_DEBUG
#endif
// We generate x86 assembly and rely on mmap(2).
#if defined(__x86_64__) && !defined(_WIN32)
# define YJIT_SUPPORTED_P 1
#else
# define YJIT_SUPPORTED_P 0
#endif
struct rb_yjit_options {
// Enable compilation with YJIT
bool yjit_enabled;

View File

@ -1233,7 +1233,7 @@ outgoing_ids(VALUE self)
void
rb_yjit_init(struct rb_yjit_options *options)
{
if (!PLATFORM_SUPPORTED_P || !JIT_ENABLED) {
if (!YJIT_SUPPORTED_P || !JIT_ENABLED) {
return;
}