1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Avoid infinite loop on --jit-wait

This commit is contained in:
Takashi Kokubun 2020-02-28 23:20:44 -08:00
parent 5e897227ff
commit a8dcab7233
No known key found for this signature in database
GPG key ID: 6FFC433B12EE23DD
2 changed files with 34 additions and 5 deletions

9
mjit.c
View file

@ -376,7 +376,14 @@ unload_units(void)
remove_from_list(worst, &active_units);
free_unit(worst);
}
verbose(1, "Too many JIT code -- %d units unloaded", units_num - active_units.length);
if (units_num == active_units.length && mjit_opts.wait) {
mjit_opts.max_cache_size++; // avoid infinite loop on `rb_mjit_wait_call`. Note that --jit-wait is just for testing.
verbose(1, "No units can be unloaded -- incremented max-cache-size to %d for --jit-wait", mjit_opts.max_cache_size);
}
else {
verbose(1, "Too many JIT code -- %d units unloaded", units_num - active_units.length);
}
}
static void

View file

@ -610,6 +610,28 @@ class TestJIT < Test::Unit::TestCase
assert_match(/^Successful MJIT finish$/, err)
end
def test_nothing_to_unload_with_jit_wait
ignorable_patterns = [
/\AJIT compaction \([^)]+\): .+\n\z/,
/\ANo units can be unloaded -- .+\n\z/,
]
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 11, max_cache: 10, ignorable_patterns: ignorable_patterns)
begin;
def a1() a2() end
def a2() a3() end
def a3() a4() end
def a4() a5() end
def a5() a6() end
def a6() a7() end
def a7() a8() end
def a8() a9() end
def a9() a10() end
def a10() a11() end
def a11() print('hello') end
a1
end;
end
def test_unload_units_and_compaction
Dir.mktmpdir("jit_test_unload_units_") do |dir|
# MIN_CACHE_SIZE is 10
@ -1006,13 +1028,13 @@ class TestJIT < Test::Unit::TestCase
end
# Shorthand for normal test cases
def assert_eval_with_jit(script, stdout: nil, success_count:, min_calls: 1, insns: [], uplevel: 1)
out, err = eval_with_jit(script, verbose: 1, min_calls: min_calls)
def assert_eval_with_jit(script, stdout: nil, success_count:, min_calls: 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)
actual = err.scan(/^#{JIT_SUCCESS_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.
if RUBY_PLATFORM.match?(/mswin/) && success_count != actual
out2, err2 = eval_with_jit(script, verbose: 2, min_calls: min_calls)
out2, err2 = eval_with_jit(script, verbose: 2, min_calls: min_calls, max_cache: max_cache)
end
# Make sure that the script has insns expected to be tested
@ -1032,7 +1054,7 @@ class TestJIT < Test::Unit::TestCase
assert_equal(stdout, out, "Expected stdout #{out.inspect} to match #{stdout.inspect} with script:\n#{code_block(script)}")
end
err_lines = err.lines.reject! do |l|
l.chomp.empty? || l.match?(/\A#{JIT_SUCCESS_PREFIX}/) || IGNORABLE_PATTERNS.any? { |pat| pat.match?(l) }
l.chomp.empty? || l.match?(/\A#{JIT_SUCCESS_PREFIX}/) || (IGNORABLE_PATTERNS + ignorable_patterns).any? { |pat| pat.match?(l) }
end
unless err_lines.empty?
warn err_lines.join(''), uplevel: uplevel