8261225: TieredStopAtLevel should have no effect if TieredCompilation is disabled

Reviewed-by: kvn
This commit is contained in:
Igor Veresov 2021-02-19 19:44:58 +00:00
parent c53acc2a89
commit 977a21add8
3 changed files with 118 additions and 37 deletions

View File

@ -326,7 +326,7 @@ double CompilationPolicy::threshold_scale(CompLevel level, int feedback_k) {
// than specified by IncreaseFirstTierCompileThresholdAt percentage.
// The main intention is to keep enough free space for C2 compiled code
// to achieve peak performance if the code cache is under stress.
if (!CompilationModeFlag::disable_intermediate() && TieredStopAtLevel == CompLevel_full_optimization && level != CompLevel_full_optimization) {
if (CompilerConfig::is_tiered() && !CompilationModeFlag::disable_intermediate() && is_c1_compile(level)) {
double current_reverse_free_ratio = CodeCache::reverse_free_ratio(CodeCache::get_code_blob_type(level));
if (current_reverse_free_ratio > _increase_threshold_at_ratio) {
k *= exp(current_reverse_free_ratio - _increase_threshold_at_ratio);
@ -509,6 +509,17 @@ void CompilationPolicy::initialize() {
#ifdef ASSERT
bool CompilationPolicy::verify_level(CompLevel level) {
if (TieredCompilation && level > TieredStopAtLevel) {
return false;
}
// Check if there is a compiler to process the requested level
if (!CompilerConfig::is_c1_enabled() && is_c1_compile(level)) {
return false;
}
if (!CompilerConfig::is_c2_or_jvmci_compiler_enabled() && is_c2_compile(level)) {
return false;
}
// AOT and interpreter levels are always valid.
if (level == CompLevel_aot || level == CompLevel_none) {
return true;
@ -528,49 +539,54 @@ bool CompilationPolicy::verify_level(CompLevel level) {
CompLevel CompilationPolicy::highest_compile_level() {
CompLevel max_level = CompLevel_none;
CompLevel level = CompLevel_none;
// Setup the maximum level availible for the current compiler configuration.
if (!CompilerConfig::is_interpreter_only()) {
if (CompilerConfig::is_c2_or_jvmci_compiler_enabled()) {
max_level = CompLevel_full_optimization;
level = CompLevel_full_optimization;
} else if (CompilerConfig::is_c1_enabled()) {
if (CompilerConfig::is_c1_simple_only()) {
max_level = CompLevel_simple;
level = CompLevel_simple;
} else {
max_level = CompLevel_full_profile;
level = CompLevel_full_profile;
}
}
max_level = MAX2(max_level, (CompLevel) TieredStopAtLevel);
}
return max_level;
// Clamp the maximum level with TieredStopAtLevel.
if (TieredCompilation) {
level = MIN2(level, (CompLevel) TieredStopAtLevel);
}
// Fix it up if after the clamping it has become invalid.
// Bring it monotonically down depending on the next available level for
// the compilation mode.
if (!CompilationModeFlag::normal()) {
// a) quick_only - levels 2,3,4 are invalid; levels -1,0,1 are valid;
// b) high_only - levels 1,2,3 are invalid; levels -1,0,4 are valid;
// c) high_only_quick_internal - levels 2,3 are invalid; levels -1,0,1,4 are valid.
if (CompilationModeFlag::quick_only()) {
if (level == CompLevel_limited_profile || level == CompLevel_full_profile || level == CompLevel_full_optimization) {
level = CompLevel_simple;
}
} else if (CompilationModeFlag::high_only()) {
if (level == CompLevel_simple || level == CompLevel_limited_profile || level == CompLevel_full_profile) {
level = CompLevel_none;
}
} else if (CompilationModeFlag::high_only_quick_internal()) {
if (level == CompLevel_limited_profile || level == CompLevel_full_profile) {
level = CompLevel_simple;
}
}
}
assert(verify_level(level), "Invalid highest compilation level: %d", level);
return level;
}
CompLevel CompilationPolicy::limit_level(CompLevel level) {
if (CompilationModeFlag::quick_only()) {
level = MIN2(level, CompLevel_simple);
}
assert(verify_level(level), "Invalid compilation level %d", level);
if (level <= TieredStopAtLevel) {
return level;
}
// Some compilation levels are not valid depending on a compilation mode:
// a) quick_only - levels 2,3,4 are invalid; levels -1,0,1 are valid;
// b) high_only - levels 1,2,3 are invalid; levels -1,0,4 are valid;
// c) high_only_quick_internal - levels 2,3 are invalid; levels -1,0,1,4 are valid.
// The invalid levels are actually sequential so a single comparison is sufficient.
// Down here we already have (level > TieredStopAtLevel), which also implies that
// (TieredStopAtLevel < Highest Possible Level), so we need to return a level that is:
// a) a max level that is strictly less than the highest for a given compilation mode
// b) less or equal to TieredStopAtLevel
if (CompilationModeFlag::normal() || CompilationModeFlag::quick_only()) {
return (CompLevel)TieredStopAtLevel;
}
if (CompilationModeFlag::high_only() || CompilationModeFlag::high_only_quick_internal()) {
return MIN2(CompLevel_none, (CompLevel)TieredStopAtLevel);
}
ShouldNotReachHere();
return CompLevel_any;
level = MIN2(level, highest_compile_level());
assert(verify_level(level), "Invalid compilation level: %d", level);
return level;
}
CompLevel CompilationPolicy::initial_compile_level(const methodHandle& method) {
@ -740,7 +756,7 @@ nmethod* CompilationPolicy::event(const methodHandle& method, const methodHandle
// Check if the method can be compiled, change level if necessary
void CompilationPolicy::compile(const methodHandle& mh, int bci, CompLevel level, TRAPS) {
assert(verify_level(level) && level <= TieredStopAtLevel, "Invalid compilation level %d", level);
assert(verify_level(level), "Invalid compilation level requested: %d", level);
if (level == CompLevel_none) {
if (mh->has_compiled_code()) {

View File

@ -158,7 +158,7 @@ public:
static bool is_c1_only() {
if (!is_interpreter_only() && has_c1()) {
const bool c1_only = !has_c2() && !is_jvmci_compiler();
const bool tiered_degraded_to_c1_only = TieredStopAtLevel >= CompLevel_simple && TieredStopAtLevel < CompLevel_full_optimization;
const bool tiered_degraded_to_c1_only = TieredCompilation && TieredStopAtLevel >= CompLevel_simple && TieredStopAtLevel < CompLevel_full_optimization;
const bool c1_only_compilation_mode = CompilationModeFlag::quick_only();
return c1_only || tiered_degraded_to_c1_only || c1_only_compilation_mode;
}
@ -177,9 +177,10 @@ public:
// Is the JVM in a configuration that permits only c1-compiled methods at level 1?
static bool is_c1_simple_only() {
if (is_c1_only()) {
const bool tiered_degraded_to_level_1 = TieredStopAtLevel == CompLevel_simple;
const bool tiered_degraded_to_level_1 = TieredCompilation && TieredStopAtLevel == CompLevel_simple;
const bool c1_only_compilation_mode = CompilationModeFlag::quick_only();
return tiered_degraded_to_level_1 || c1_only_compilation_mode;
const bool tiered_off = !TieredCompilation;
return tiered_degraded_to_level_1 || c1_only_compilation_mode || tiered_off;
}
return false;
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test TestEnqueueMethodForCompilation
* @summary If TieredCompilation is disabled, TieredStopAtLevel should have no effect.
* @requires vm.flavor == "server"
* @library /test/lib /
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:TieredStopAtLevel=1 -XX:-TieredCompilation
* compiler.tiered.TestEnqueueMethodForCompilation
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:TieredStopAtLevel=2 -XX:-TieredCompilation
* compiler.tiered.TestEnqueueMethodForCompilation
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:TieredStopAtLevel=3 -XX:-TieredCompilation
* compiler.tiered.TestEnqueueMethodForCompilation
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:TieredStopAtLevel=4 -XX:-TieredCompilation
* compiler.tiered.TestEnqueueMethodForCompilation
*/
package compiler.tiered;
import java.lang.reflect.Method;
import compiler.whitebox.CompilerWhiteBoxTest;
import sun.hotspot.WhiteBox;
public class TestEnqueueMethodForCompilation {
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
public void test() { }
public static void main(String[] args) throws Exception {
Method method = TestEnqueueMethodForCompilation.class.getMethod("test");
boolean success = WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!success) {
throw new RuntimeException("Method could not be enqueued for compilation at level " + CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
}
}
}