Rename --mjit-min-calls to --mjit-call-threshold (#6731)
for consistency with YJIT
This commit is contained in:
parent
c75de1e330
commit
d15d1c01c2
Notes:
git
2022-11-15 07:39:11 +00:00
Merged-By: k0kubun <takashikkbn@gmail.com>
1
NEWS.md
1
NEWS.md
@ -356,6 +356,7 @@ The following deprecated APIs are removed.
|
|||||||
doing it in a native thread called MJIT worker. [[Feature #18968]]
|
doing it in a native thread called MJIT worker. [[Feature #18968]]
|
||||||
* As a result, Microsoft Visual Studio (MSWIN) is no longer supported.
|
* As a result, Microsoft Visual Studio (MSWIN) is no longer supported.
|
||||||
* MinGW is no longer supported. [[Feature #18824]]
|
* MinGW is no longer supported. [[Feature #18824]]
|
||||||
|
* Rename `--mjit-min-calls` to `--mjit-call-threshold`.
|
||||||
|
|
||||||
## Static analysis
|
## Static analysis
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ class BenchmarkDriver::Runner::Mjit < BenchmarkDriver::Runner::Ips
|
|||||||
job.prelude = "#{job.prelude}\n#{<<~EOS}"
|
job.prelude = "#{job.prelude}\n#{<<~EOS}"
|
||||||
if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
|
if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
|
||||||
__bmdv_ruby_i = 0
|
__bmdv_ruby_i = 0
|
||||||
while __bmdv_ruby_i < 10000 # jit_min_calls
|
while __bmdv_ruby_i < 10000 # MJIT call threshold
|
||||||
#{job.script}
|
#{job.script}
|
||||||
__bmdv_ruby_i += 1
|
__bmdv_ruby_i += 1
|
||||||
end
|
end
|
||||||
|
@ -283,7 +283,7 @@ assert_equal 30.times.map { 'ok' }.to_s, %q{
|
|||||||
30.times.map{|i|
|
30.times.map{|i|
|
||||||
test i
|
test i
|
||||||
}
|
}
|
||||||
} unless ENV['RUN_OPTS'] =~ /--jit-min-calls=5/ || # This always fails with --jit-wait --jit-min-calls=5
|
} unless ENV['RUN_OPTS'] =~ /--mjit-call-threshold=5/ || # This always fails with --mjit-wait --mjit-call-threshold=5
|
||||||
(ENV.key?('TRAVIS') && ENV['TRAVIS_CPU_ARCH'] == 'arm64') # https://bugs.ruby-lang.org/issues/17878
|
(ENV.key?('TRAVIS') && ENV['TRAVIS_CPU_ARCH'] == 'arm64') # https://bugs.ruby-lang.org/issues/17878
|
||||||
|
|
||||||
# Exception for empty select
|
# Exception for empty select
|
||||||
|
26
mjit.c
26
mjit.c
@ -1628,7 +1628,7 @@ system_tmpdir(void)
|
|||||||
// Default permitted number of units with a JIT code kept in memory.
|
// Default permitted number of units with a JIT code kept in memory.
|
||||||
#define DEFAULT_MAX_CACHE_SIZE 10000
|
#define DEFAULT_MAX_CACHE_SIZE 10000
|
||||||
// A default threshold used to add iseq to JIT.
|
// A default threshold used to add iseq to JIT.
|
||||||
#define DEFAULT_MIN_CALLS_TO_ADD 10000
|
#define DEFAULT_CALL_THRESHOLD 10000
|
||||||
|
|
||||||
// Start MJIT worker. Return TRUE if worker is successfully started.
|
// Start MJIT worker. Return TRUE if worker is successfully started.
|
||||||
static bool
|
static bool
|
||||||
@ -1709,8 +1709,8 @@ mjit_setup_options(const char *s, struct mjit_options *mjit_opt)
|
|||||||
else if (opt_match_arg(s, l, "max-cache")) {
|
else if (opt_match_arg(s, l, "max-cache")) {
|
||||||
mjit_opt->max_cache_size = atoi(s + 1);
|
mjit_opt->max_cache_size = atoi(s + 1);
|
||||||
}
|
}
|
||||||
else if (opt_match_arg(s, l, "min-calls")) {
|
else if (opt_match_arg(s, l, "call-threshold")) {
|
||||||
mjit_opt->min_calls = atoi(s + 1);
|
mjit_opt->call_threshold = atoi(s + 1);
|
||||||
}
|
}
|
||||||
// --mjit=pause is an undocumented feature for experiments
|
// --mjit=pause is an undocumented feature for experiments
|
||||||
else if (opt_match_noarg(s, l, "pause")) {
|
else if (opt_match_noarg(s, l, "pause")) {
|
||||||
@ -1724,15 +1724,15 @@ mjit_setup_options(const char *s, struct mjit_options *mjit_opt)
|
|||||||
|
|
||||||
#define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
|
#define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
|
||||||
const struct ruby_opt_message mjit_option_messages[] = {
|
const struct ruby_opt_message mjit_option_messages[] = {
|
||||||
M("--mjit-warnings", "", "Enable printing JIT warnings"),
|
M("--mjit-warnings", "", "Enable printing JIT warnings"),
|
||||||
M("--mjit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"),
|
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-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-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-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: "
|
M("--mjit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: "
|
||||||
STRINGIZE(DEFAULT_MAX_CACHE_SIZE) ")"),
|
STRINGIZE(DEFAULT_MAX_CACHE_SIZE) ")"),
|
||||||
M("--mjit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: "
|
M("--mjit-call-threshold=num", "", "Number of calls to trigger JIT (for testing, default: "
|
||||||
STRINGIZE(DEFAULT_MIN_CALLS_TO_ADD) ")"),
|
STRINGIZE(DEFAULT_CALL_THRESHOLD) ")"),
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
#undef M
|
#undef M
|
||||||
@ -1760,8 +1760,8 @@ mjit_init(const struct mjit_options *opts)
|
|||||||
mjit_pid = getpid();
|
mjit_pid = getpid();
|
||||||
|
|
||||||
// Normalize options
|
// Normalize options
|
||||||
if (mjit_opts.min_calls == 0)
|
if (mjit_opts.call_threshold == 0)
|
||||||
mjit_opts.min_calls = DEFAULT_MIN_CALLS_TO_ADD;
|
mjit_opts.call_threshold = DEFAULT_CALL_THRESHOLD;
|
||||||
if (mjit_opts.max_cache_size <= 0)
|
if (mjit_opts.max_cache_size <= 0)
|
||||||
mjit_opts.max_cache_size = DEFAULT_MAX_CACHE_SIZE;
|
mjit_opts.max_cache_size = DEFAULT_MAX_CACHE_SIZE;
|
||||||
if (mjit_opts.max_cache_size < MIN_CACHE_SIZE)
|
if (mjit_opts.max_cache_size < MIN_CACHE_SIZE)
|
||||||
|
2
mjit.h
2
mjit.h
@ -52,7 +52,7 @@ struct mjit_options {
|
|||||||
// If true, all ISeqs are synchronously compiled. For testing.
|
// If true, all ISeqs are synchronously compiled. For testing.
|
||||||
bool wait;
|
bool wait;
|
||||||
// Number of calls to trigger JIT compilation. For testing.
|
// Number of calls to trigger JIT compilation. For testing.
|
||||||
unsigned int min_calls;
|
unsigned int call_threshold;
|
||||||
// Force printing info about MJIT work of level VERBOSE or
|
// Force printing info about MJIT work of level VERBOSE or
|
||||||
// less. 0=silence, 1=medium, 2=verbose.
|
// less. 0=silence, 1=medium, 2=verbose.
|
||||||
int verbose;
|
int verbose;
|
||||||
|
@ -330,7 +330,7 @@ module RubyVM::MJIT
|
|||||||
debug: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), debug)")],
|
debug: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), debug)")],
|
||||||
debug_flags: [CType::Pointer.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), debug_flags)")],
|
debug_flags: [CType::Pointer.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), debug_flags)")],
|
||||||
wait: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), wait)")],
|
wait: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), wait)")],
|
||||||
min_calls: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), min_calls)")],
|
call_threshold: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), call_threshold)")],
|
||||||
verbose: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), verbose)")],
|
verbose: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), verbose)")],
|
||||||
max_cache_size: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), max_cache_size)")],
|
max_cache_size: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), max_cache_size)")],
|
||||||
pause: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), pause)")],
|
pause: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), pause)")],
|
||||||
|
@ -38,10 +38,10 @@ module JITSupport
|
|||||||
[stdout, stderr]
|
[stdout, stderr]
|
||||||
end
|
end
|
||||||
|
|
||||||
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)
|
def eval_with_jit_without_retry(env = nil, script, verbose: 0, call_threshold: 5, save_temps: false, max_cache: 1000, wait: true, timeout: JIT_TIMEOUT)
|
||||||
args = [
|
args = [
|
||||||
'--disable-gems', "--mjit-verbose=#{verbose}",
|
'--disable-gems', "--mjit-verbose=#{verbose}",
|
||||||
"--mjit-min-calls=#{min_calls}", "--mjit-max-cache=#{max_cache}",
|
"--mjit-call-threshold=#{call_threshold}", "--mjit-max-cache=#{max_cache}",
|
||||||
]
|
]
|
||||||
args << '--disable-yjit'
|
args << '--disable-yjit'
|
||||||
args << '--mjit-wait' if wait
|
args << '--mjit-wait' if wait
|
||||||
|
@ -142,7 +142,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
# optimized getinstancevariable call
|
# optimized getinstancevariable call
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 1, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 1, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
class A
|
class A
|
||||||
def initialize
|
def initialize
|
||||||
@ -533,7 +533,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
|
|
||||||
def test_compile_insn_opt_aref
|
def test_compile_insn_opt_aref
|
||||||
# optimized call (optimized JIT) -> send call
|
# optimized call (optimized JIT) -> send call
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '21', success_count: 2, min_calls: 1, insns: %i[opt_aref])
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '21', success_count: 2, call_threshold: 1, insns: %i[opt_aref])
|
||||||
begin;
|
begin;
|
||||||
obj = Object.new
|
obj = Object.new
|
||||||
def obj.[](h)
|
def obj.[](h)
|
||||||
@ -546,7 +546,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
# send call -> optimized call (send JIT) -> optimized call
|
# send call -> optimized call (send JIT) -> optimized call
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '122', success_count: 2, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '122', success_count: 2, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
obj = Object.new
|
obj = Object.new
|
||||||
def obj.[](h)
|
def obj.[](h)
|
||||||
@ -637,7 +637,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_mjit_output
|
def test_mjit_output
|
||||||
out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, min_calls: 5)
|
out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, call_threshold: 5)
|
||||||
assert_equal("MJIT\n" * 5, out)
|
assert_equal("MJIT\n" * 5, out)
|
||||||
assert_match(/^#{JIT_SUCCESS_PREFIX}: block in <main>@-e:1 -> .+_ruby_mjit_p\d+u\d+\.c$/, err)
|
assert_match(/^#{JIT_SUCCESS_PREFIX}: block in <main>@-e:1 -> .+_ruby_mjit_p\d+u\d+\.c$/, err)
|
||||||
assert_match(/^Successful MJIT finish$/, err)
|
assert_match(/^Successful MJIT finish$/, err)
|
||||||
@ -686,7 +686,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
def test_unload_units_and_compaction
|
def test_unload_units_and_compaction
|
||||||
Dir.mktmpdir("jit_test_unload_units_") do |dir|
|
Dir.mktmpdir("jit_test_unload_units_") do |dir|
|
||||||
# MIN_CACHE_SIZE is 10
|
# MIN_CACHE_SIZE is 10
|
||||||
out, err = eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~'end;'}", verbose: 1, min_calls: 1, max_cache: 10)
|
out, err = eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~'end;'}", verbose: 1, call_threshold: 1, max_cache: 10)
|
||||||
begin;
|
begin;
|
||||||
i = 0
|
i = 0
|
||||||
while i < 11
|
while i < 11
|
||||||
@ -805,7 +805,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_inlined_builtin_methods
|
def test_inlined_builtin_methods
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 1, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 1, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
def test
|
def test
|
||||||
float = 0.0
|
float = 0.0
|
||||||
@ -819,7 +819,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_inlined_c_method
|
def test_inlined_c_method
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 2, recompile_count: 1, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 2, recompile_count: 1, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
def test(obj, recursive: nil)
|
def test(obj, recursive: nil)
|
||||||
if recursive
|
if recursive
|
||||||
@ -837,7 +837,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_inlined_exivar
|
def test_inlined_exivar
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 4, recompile_count: 2, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 4, recompile_count: 2, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
class Foo < Hash
|
class Foo < Hash
|
||||||
def initialize
|
def initialize
|
||||||
@ -856,7 +856,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_inlined_undefined_ivar
|
def test_inlined_undefined_ivar
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 2, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 2, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
class Foo
|
class Foo
|
||||||
def initialize
|
def initialize
|
||||||
@ -877,7 +877,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_inlined_setivar_frozen
|
def test_inlined_setivar_frozen
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "FrozenError\n", success_count: 2, min_calls: 3)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "FrozenError\n", success_count: 2, call_threshold: 3)
|
||||||
begin;
|
begin;
|
||||||
class A
|
class A
|
||||||
def a
|
def a
|
||||||
@ -899,7 +899,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_inlined_getconstant
|
def test_inlined_getconstant
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 1, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 1, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
FOO = 1
|
FOO = 1
|
||||||
def const
|
def const
|
||||||
@ -911,7 +911,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_attr_reader
|
def test_attr_reader
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
class A
|
class A
|
||||||
attr_reader :a, :b
|
attr_reader :a, :b
|
||||||
@ -942,7 +942,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
print(2 * a.test)
|
print(2 * a.test)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true", success_count: 1, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true", success_count: 1, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
class Hoge
|
class Hoge
|
||||||
attr_reader :foo
|
attr_reader :foo
|
||||||
@ -977,7 +977,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
def test_heap_promotion_of_ivar_in_the_middle_of_jit
|
def test_heap_promotion_of_ivar_in_the_middle_of_jit
|
||||||
omit if GC.using_rvargc?
|
omit if GC.using_rvargc?
|
||||||
|
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\n", success_count: 2, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\n", success_count: 2, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
class A
|
class A
|
||||||
def initialize
|
def initialize
|
||||||
@ -1004,7 +1004,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_jump_to_precompiled_branch
|
def test_jump_to_precompiled_branch
|
||||||
assert_eval_with_jit("#{<<~'begin;'}\n#{<<~'end;'}", stdout: ".0", success_count: 1, min_calls: 1)
|
assert_eval_with_jit("#{<<~'begin;'}\n#{<<~'end;'}", stdout: ".0", success_count: 1, call_threshold: 1)
|
||||||
begin;
|
begin;
|
||||||
def test(foo)
|
def test(foo)
|
||||||
".#{foo unless foo == 1}" if true
|
".#{foo unless foo == 1}" if true
|
||||||
@ -1038,7 +1038,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
omit '.bundle.dSYM directory is left but removing it is not supported for now'
|
omit '.bundle.dSYM directory is left but removing it is not supported for now'
|
||||||
end
|
end
|
||||||
Dir.mktmpdir("jit_test_clean_objects_on_exec_") do |dir|
|
Dir.mktmpdir("jit_test_clean_objects_on_exec_") do |dir|
|
||||||
eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1)
|
eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 1)
|
||||||
begin;
|
begin;
|
||||||
def a; end; a
|
def a; end; a
|
||||||
exec "true"
|
exec "true"
|
||||||
@ -1070,7 +1070,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_frame_omitted_inlining
|
def test_frame_omitted_inlining
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\ntrue\n", success_count: 1, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
class Integer
|
class Integer
|
||||||
remove_method :zero?
|
remove_method :zero?
|
||||||
@ -1086,7 +1086,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_block_handler_with_possible_frame_omitted_inlining
|
def test_block_handler_with_possible_frame_omitted_inlining
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "70.0\n70.0\n70.0\n", success_count: 2, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "70.0\n70.0\n70.0\n", success_count: 2, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
def multiply(a, b)
|
def multiply(a, b)
|
||||||
a *= b
|
a *= b
|
||||||
@ -1099,7 +1099,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_builtin_frame_omitted_inlining
|
def test_builtin_frame_omitted_inlining
|
||||||
assert_eval_with_jit('0.zero?; 0.zero?; 3.times { p 0.zero? }', stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2)
|
assert_eval_with_jit('0.zero?; 0.zero?; 3.times { p 0.zero? }', stdout: "true\ntrue\ntrue\n", success_count: 1, call_threshold: 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_program_counter_with_regexpmatch
|
def test_program_counter_with_regexpmatch
|
||||||
@ -1131,7 +1131,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_mjit_pause_wait
|
def test_mjit_pause_wait
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 0, min_calls: 1)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 0, call_threshold: 1)
|
||||||
begin;
|
begin;
|
||||||
RubyVM::MJIT.pause
|
RubyVM::MJIT.pause
|
||||||
proc {}.call
|
proc {}.call
|
||||||
@ -1139,7 +1139,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_not_cancel_by_tracepoint_class
|
def test_not_cancel_by_tracepoint_class
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 1, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 1, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
TracePoint.new(:class) {}.enable
|
TracePoint.new(:class) {}.enable
|
||||||
2.times {}
|
2.times {}
|
||||||
@ -1147,7 +1147,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_cancel_by_tracepoint
|
def test_cancel_by_tracepoint
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 0, min_calls: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 0, call_threshold: 2)
|
||||||
begin;
|
begin;
|
||||||
TracePoint.new(:line) {}.enable
|
TracePoint.new(:line) {}.enable
|
||||||
2.times {}
|
2.times {}
|
||||||
@ -1155,7 +1155,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_caller_locations_without_catch_table
|
def test_caller_locations_without_catch_table
|
||||||
out, _ = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1)
|
out, _ = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 1)
|
||||||
begin;
|
begin;
|
||||||
def b # 2
|
def b # 2
|
||||||
caller_locations.first # 3
|
caller_locations.first # 3
|
||||||
@ -1175,8 +1175,8 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
|
|
||||||
def test_fork_with_mjit_worker_thread
|
def test_fork_with_mjit_worker_thread
|
||||||
Dir.mktmpdir("jit_test_fork_with_mjit_worker_thread_") do |dir|
|
Dir.mktmpdir("jit_test_fork_with_mjit_worker_thread_") do |dir|
|
||||||
# min_calls: 2 to skip fork block
|
# call_threshold: 2 to skip fork block
|
||||||
out, err = eval_with_jit({ "TMPDIR" => dir }, "#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 2, verbose: 1)
|
out, err = eval_with_jit({ "TMPDIR" => dir }, "#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 2, verbose: 1)
|
||||||
begin;
|
begin;
|
||||||
def before_fork; end
|
def before_fork; end
|
||||||
def after_fork; end
|
def after_fork; end
|
||||||
@ -1206,7 +1206,7 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end if defined?(fork)
|
end if defined?(fork)
|
||||||
|
|
||||||
def test_jit_failure
|
def test_jit_failure
|
||||||
_, err = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1, verbose: 1)
|
_, err = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 1, verbose: 1)
|
||||||
begin;
|
begin;
|
||||||
1.times do
|
1.times do
|
||||||
class A
|
class A
|
||||||
@ -1230,14 +1230,14 @@ class TestMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Shorthand for normal test cases
|
# Shorthand for normal test cases
|
||||||
def assert_eval_with_jit(script, stdout: nil, success_count:, recompile_count: nil, min_calls: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: [])
|
def assert_eval_with_jit(script, stdout: nil, success_count:, recompile_count: nil, call_threshold: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: [])
|
||||||
out, err = eval_with_jit(script, verbose: 1, min_calls: min_calls, max_cache: max_cache)
|
out, err = eval_with_jit(script, verbose: 1, call_threshold: call_threshold, max_cache: max_cache)
|
||||||
success_actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
|
success_actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
|
||||||
recompile_actual = err.scan(/^#{JIT_RECOMPILE_PREFIX}:/).size
|
recompile_actual = err.scan(/^#{JIT_RECOMPILE_PREFIX}:/).size
|
||||||
# Add --mjit-verbose=2 logs for cl.exe because compiler's error message is suppressed
|
# 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.c.
|
# for cl.exe with --mjit-verbose=1. See `start_process` in mjit.c.
|
||||||
if RUBY_PLATFORM.match?(/mswin/) && success_count != success_actual
|
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)
|
out2, err2 = eval_with_jit(script, verbose: 2, call_threshold: call_threshold, max_cache: max_cache)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Make sure that the script has insns expected to be tested
|
# Make sure that the script has insns expected to be tested
|
||||||
|
@ -14,7 +14,7 @@ class TestRubyVMMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_pause
|
def test_pause
|
||||||
out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false)
|
out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
|
||||||
i = 0
|
i = 0
|
||||||
while i < 5
|
while i < 5
|
||||||
eval("def mjit#{i}; end; mjit#{i}")
|
eval("def mjit#{i}; end; mjit#{i}")
|
||||||
@ -36,7 +36,7 @@ class TestRubyVMMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_pause_waits_until_compaction
|
def test_pause_waits_until_compaction
|
||||||
out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false)
|
out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
|
||||||
def a() end; a
|
def a() end; a
|
||||||
def b() end; b
|
def b() end; b
|
||||||
RubyVM::MJIT.pause
|
RubyVM::MJIT.pause
|
||||||
@ -52,7 +52,7 @@ class TestRubyVMMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_pause_after_waitall
|
def test_pause_after_waitall
|
||||||
out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false)
|
out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
|
||||||
def test() = nil
|
def test() = nil
|
||||||
test
|
test
|
||||||
Process.waitall
|
Process.waitall
|
||||||
@ -65,7 +65,7 @@ class TestRubyVMMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_pause_does_not_hang_on_full_units
|
def test_pause_does_not_hang_on_full_units
|
||||||
out, _ = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, max_cache: 10, wait: false)
|
out, _ = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, max_cache: 10, wait: false)
|
||||||
i = 0
|
i = 0
|
||||||
while i < 11
|
while i < 11
|
||||||
eval("def mjit#{i}; end; mjit#{i}")
|
eval("def mjit#{i}; end; mjit#{i}")
|
||||||
@ -77,7 +77,7 @@ class TestRubyVMMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_pause_wait_false
|
def test_pause_wait_false
|
||||||
out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false)
|
out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
|
||||||
i = 0
|
i = 0
|
||||||
while i < 10
|
while i < 10
|
||||||
eval("def mjit#{i}; end; mjit#{i}")
|
eval("def mjit#{i}; end; mjit#{i}")
|
||||||
@ -95,7 +95,7 @@ class TestRubyVMMJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_resume
|
def test_resume
|
||||||
out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false)
|
out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
|
||||||
print RubyVM::MJIT.resume
|
print RubyVM::MJIT.resume
|
||||||
print RubyVM::MJIT.pause
|
print RubyVM::MJIT.pause
|
||||||
print RubyVM::MJIT.resume
|
print RubyVM::MJIT.resume
|
||||||
|
2
vm.c
2
vm.c
@ -391,7 +391,7 @@ mjit_check_iseq(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_ise
|
|||||||
ASSUME(func_i <= LAST_JIT_ISEQ_FUNC);
|
ASSUME(func_i <= LAST_JIT_ISEQ_FUNC);
|
||||||
switch ((enum rb_mjit_iseq_func)func_i) {
|
switch ((enum rb_mjit_iseq_func)func_i) {
|
||||||
case NOT_ADDED_JIT_ISEQ_FUNC:
|
case NOT_ADDED_JIT_ISEQ_FUNC:
|
||||||
if (body->total_calls == mjit_opts.min_calls) {
|
if (body->total_calls == mjit_opts.call_threshold) {
|
||||||
rb_mjit_add_iseq_to_process(iseq);
|
rb_mjit_add_iseq_to_process(iseq);
|
||||||
if (UNLIKELY(mjit_opts.wait && (uintptr_t)body->jit_func > LAST_JIT_ISEQ_FUNC)) {
|
if (UNLIKELY(mjit_opts.wait && (uintptr_t)body->jit_func > LAST_JIT_ISEQ_FUNC)) {
|
||||||
return body->jit_func(ec, ec->cfp);
|
return body->jit_func(ec, ec->cfp);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user