Fri, 26 Apr 2013 07:21:41 -0700
8012322: Tiered: CompilationPolicy::can_be_compiled(CompLevel_all) mistakenly return false
Reviewed-by: kvn, vlivanov
1.1 --- a/src/share/vm/classfile/classLoader.cpp Thu Apr 25 11:09:24 2013 -0700 1.2 +++ b/src/share/vm/classfile/classLoader.cpp Fri Apr 26 07:21:41 2013 -0700 1.3 @@ -1345,9 +1345,10 @@ 1.4 tty->print_cr("CompileTheWorld (%d) : %s", _compile_the_world_class_counter, buffer); 1.5 // Preload all classes to get around uncommon traps 1.6 // Iterate over all methods in class 1.7 + int comp_level = CompilationPolicy::policy()->initial_compile_level(); 1.8 for (int n = 0; n < k->methods()->length(); n++) { 1.9 methodHandle m (THREAD, k->methods()->at(n)); 1.10 - if (CompilationPolicy::can_be_compiled(m)) { 1.11 + if (CompilationPolicy::can_be_compiled(m, comp_level)) { 1.12 1.13 if (++_codecache_sweep_counter == CompileTheWorldSafepointInterval) { 1.14 // Give sweeper a chance to keep up with CTW 1.15 @@ -1356,7 +1357,7 @@ 1.16 _codecache_sweep_counter = 0; 1.17 } 1.18 // Force compilation 1.19 - CompileBroker::compile_method(m, InvocationEntryBci, CompilationPolicy::policy()->initial_compile_level(), 1.20 + CompileBroker::compile_method(m, InvocationEntryBci, comp_level, 1.21 methodHandle(), 0, "CTW", THREAD); 1.22 if (HAS_PENDING_EXCEPTION) { 1.23 clear_pending_exception_if_not_oom(CHECK);
2.1 --- a/src/share/vm/runtime/compilationPolicy.cpp Thu Apr 25 11:09:24 2013 -0700 2.2 +++ b/src/share/vm/runtime/compilationPolicy.cpp Fri Apr 26 07:21:41 2013 -0700 2.3 @@ -109,6 +109,9 @@ 2.4 2.5 // Returns true if m is allowed to be compiled 2.6 bool CompilationPolicy::can_be_compiled(methodHandle m, int comp_level) { 2.7 + // allow any levels for WhiteBox 2.8 + assert(WhiteBoxAPI || comp_level == CompLevel_all || is_compile(comp_level), "illegal compilation level"); 2.9 + 2.10 if (m->is_abstract()) return false; 2.11 if (DontCompileHugeMethods && m->code_size() > HugeMethodLimit) return false; 2.12 2.13 @@ -122,7 +125,13 @@ 2.14 return false; 2.15 } 2.16 if (comp_level == CompLevel_all) { 2.17 - return !m->is_not_compilable(CompLevel_simple) && !m->is_not_compilable(CompLevel_full_optimization); 2.18 + if (TieredCompilation) { 2.19 + // enough to be compilable at any level for tiered 2.20 + return !m->is_not_compilable(CompLevel_simple) || !m->is_not_compilable(CompLevel_full_optimization); 2.21 + } else { 2.22 + // must be compilable at available level for non-tiered 2.23 + return !m->is_not_compilable(CompLevel_highest_tier); 2.24 + } 2.25 } else if (is_compile(comp_level)) { 2.26 return !m->is_not_compilable(comp_level); 2.27 } 2.28 @@ -436,7 +445,7 @@ 2.29 reset_counter_for_invocation_event(m); 2.30 const char* comment = "count"; 2.31 2.32 - if (is_compilation_enabled() && can_be_compiled(m)) { 2.33 + if (is_compilation_enabled() && can_be_compiled(m, comp_level)) { 2.34 nmethod* nm = m->code(); 2.35 if (nm == NULL ) { 2.36 CompileBroker::compile_method(m, InvocationEntryBci, comp_level, m, hot_count, comment, thread); 2.37 @@ -449,7 +458,7 @@ 2.38 const int hot_count = m->backedge_count(); 2.39 const char* comment = "backedge_count"; 2.40 2.41 - if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m)) { 2.42 + if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m, comp_level)) { 2.43 CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); 2.44 NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) 2.45 } 2.46 @@ -467,7 +476,7 @@ 2.47 reset_counter_for_invocation_event(m); 2.48 const char* comment = "count"; 2.49 2.50 - if (is_compilation_enabled() && m->code() == NULL && can_be_compiled(m)) { 2.51 + if (is_compilation_enabled() && m->code() == NULL && can_be_compiled(m, comp_level)) { 2.52 ResourceMark rm(thread); 2.53 frame fr = thread->last_frame(); 2.54 assert(fr.is_interpreted_frame(), "must be interpreted"); 2.55 @@ -505,7 +514,7 @@ 2.56 const int hot_count = m->backedge_count(); 2.57 const char* comment = "backedge_count"; 2.58 2.59 - if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m)) { 2.60 + if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m, comp_level)) { 2.61 CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); 2.62 NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) 2.63 } 2.64 @@ -600,7 +609,7 @@ 2.65 2.66 // If the caller method is too big or something then we do not want to 2.67 // compile it just to inline a method 2.68 - if (!can_be_compiled(next_m)) { 2.69 + if (!can_be_compiled(next_m, CompLevel_any)) { 2.70 msg = "caller cannot be compiled"; 2.71 break; 2.72 }
3.1 --- a/test/compiler/whitebox/CompilerWhiteBoxTest.java Thu Apr 25 11:09:24 2013 -0700 3.2 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Fri Apr 26 07:21:41 2013 -0700 3.3 @@ -42,6 +42,11 @@ 3.4 protected static int COMP_LEVEL_NONE = 0; 3.5 /** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */ 3.6 protected static int COMP_LEVEL_ANY = -1; 3.7 + /** {@code CompLevel::CompLevel_simple} -- C1 */ 3.8 + protected static int COMP_LEVEL_SIMPLE = 1; 3.9 + /** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */ 3.10 + protected static int COMP_LEVEL_FULL_OPTIMIZATION = 4; 3.11 + 3.12 /** Instance of WhiteBox */ 3.13 protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); 3.14 /** Value of {@code -XX:CompileThreshold} */ 3.15 @@ -91,6 +96,17 @@ 3.16 return result == null ? defaultValue : result; 3.17 } 3.18 3.19 + /** copy of is_c1_compile(int) from utilities/globalDefinitions.hpp */ 3.20 + protected static boolean isC1Compile(int compLevel) { 3.21 + return (compLevel > COMP_LEVEL_NONE) 3.22 + && (compLevel < COMP_LEVEL_FULL_OPTIMIZATION); 3.23 + } 3.24 + 3.25 + /** copy of is_c2_compile(int) from utilities/globalDefinitions.hpp */ 3.26 + protected static boolean isC2Compile(int compLevel) { 3.27 + return compLevel == COMP_LEVEL_FULL_OPTIMIZATION; 3.28 + } 3.29 + 3.30 /** tested method */ 3.31 protected final Executable method; 3.32 private final Callable<Integer> callable;
4.1 --- a/test/compiler/whitebox/MakeMethodNotCompilableTest.java Thu Apr 25 11:09:24 2013 -0700 4.2 +++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Apr 26 07:21:41 2013 -0700 4.3 @@ -23,6 +23,7 @@ 4.4 4.5 /* 4.6 * @test MakeMethodNotCompilableTest 4.7 + * @bug 8012322 4.8 * @library /testlibrary /testlibrary/whitebox 4.9 * @build MakeMethodNotCompilableTest 4.10 * @run main ClassFileInstaller sun.hotspot.WhiteBox 4.11 @@ -67,28 +68,69 @@ 4.12 } 4.13 4.14 if (TIERED_COMPILATION) { 4.15 - for (int i = 1, n = TIERED_STOP_AT_LEVEL + 1; i < n; ++i) { 4.16 - WHITE_BOX.makeMethodNotCompilable(method, i); 4.17 - if (WHITE_BOX.isMethodCompilable(method, i)) { 4.18 + final int tierLimit = TIERED_STOP_AT_LEVEL + 1; 4.19 + for (int testedTier = 1; testedTier < tierLimit; ++testedTier) { 4.20 + testTier(testedTier); 4.21 + } 4.22 + for (int testedTier = 1; testedTier < tierLimit; ++testedTier) { 4.23 + WHITE_BOX.makeMethodNotCompilable(method, testedTier); 4.24 + if (WHITE_BOX.isMethodCompilable(method, testedTier)) { 4.25 throw new RuntimeException(method 4.26 - + " must be not compilable at level" + i); 4.27 + + " must be not compilable at level" + testedTier); 4.28 } 4.29 - WHITE_BOX.enqueueMethodForCompilation(method, i); 4.30 + WHITE_BOX.enqueueMethodForCompilation(method, testedTier); 4.31 checkNotCompiled(); 4.32 4.33 if (!WHITE_BOX.isMethodCompilable(method)) { 4.34 System.out.println(method 4.35 - + " is not compilable after level " + i); 4.36 + + " is not compilable after level " + testedTier); 4.37 } 4.38 } 4.39 + } else { 4.40 + compile(); 4.41 + checkCompiled(); 4.42 + int compLevel = WHITE_BOX.getMethodCompilationLevel(method); 4.43 + WHITE_BOX.deoptimizeMethod(method); 4.44 + WHITE_BOX.makeMethodNotCompilable(method, compLevel); 4.45 + if (WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY)) { 4.46 + throw new RuntimeException(method 4.47 + + " must be not compilable at CompLevel::CompLevel_any," 4.48 + + " after it is not compilable at " + compLevel); 4.49 + } 4.50 + WHITE_BOX.clearMethodState(method); 4.51 4.52 - // WB.clearMethodState() must reset no-compilable flags 4.53 - WHITE_BOX.clearMethodState(method); 4.54 - if (!WHITE_BOX.isMethodCompilable(method)) { 4.55 - throw new RuntimeException(method 4.56 - + " is not compilable after clearMethodState()"); 4.57 + // nocompilable at opposite level must make no sense 4.58 + int oppositeLevel; 4.59 + if (isC1Compile(compLevel)) { 4.60 + oppositeLevel = COMP_LEVEL_FULL_OPTIMIZATION; 4.61 + } else { 4.62 + oppositeLevel = COMP_LEVEL_SIMPLE; 4.63 + } 4.64 + WHITE_BOX.makeMethodNotCompilable(method, oppositeLevel); 4.65 + 4.66 + if (!WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY)) { 4.67 + throw new RuntimeException(method 4.68 + + " must be compilable at CompLevel::CompLevel_any," 4.69 + + " even it is not compilable at opposite level [" 4.70 + + compLevel + "]"); 4.71 + } 4.72 + 4.73 + if (!WHITE_BOX.isMethodCompilable(method, compLevel)) { 4.74 + throw new RuntimeException(method 4.75 + + " must be compilable at level " + compLevel 4.76 + + ", even it is not compilable at opposite level [" 4.77 + + compLevel + "]"); 4.78 } 4.79 } 4.80 + 4.81 + // clearing after tiered/non-tiered tests 4.82 + // WB.clearMethodState() must reset no-compilable flags 4.83 + WHITE_BOX.clearMethodState(method); 4.84 + if (!WHITE_BOX.isMethodCompilable(method)) { 4.85 + throw new RuntimeException(method 4.86 + + " is not compilable after clearMethodState()"); 4.87 + } 4.88 + 4.89 WHITE_BOX.makeMethodNotCompilable(method); 4.90 if (WHITE_BOX.isMethodCompilable(method)) { 4.91 throw new RuntimeException(method + " must be not compilable"); 4.92 @@ -108,4 +150,65 @@ 4.93 compile(); 4.94 checkCompiled(); 4.95 } 4.96 + 4.97 + // separately tests each tier 4.98 + private void testTier(int testedTier) { 4.99 + if (!WHITE_BOX.isMethodCompilable(method, testedTier)) { 4.100 + throw new RuntimeException(method 4.101 + + " is not compilable on start"); 4.102 + } 4.103 + WHITE_BOX.makeMethodNotCompilable(method, testedTier); 4.104 + 4.105 + // tests for all other tiers 4.106 + for (int anotherTier = 1, tierLimit = TIERED_STOP_AT_LEVEL + 1; 4.107 + anotherTier < tierLimit; ++anotherTier) { 4.108 + boolean isCompilable = WHITE_BOX.isMethodCompilable(method, 4.109 + anotherTier); 4.110 + if (sameCompile(testedTier, anotherTier)) { 4.111 + if (isCompilable) { 4.112 + throw new RuntimeException(method 4.113 + + " must be not compilable at level " + anotherTier 4.114 + + ", if it is not compilable at " + testedTier); 4.115 + } 4.116 + WHITE_BOX.enqueueMethodForCompilation(method, anotherTier); 4.117 + checkNotCompiled(); 4.118 + } else { 4.119 + if (!isCompilable) { 4.120 + throw new RuntimeException(method 4.121 + + " must be compilable at level " + anotherTier 4.122 + + ", even if it is not compilable at " 4.123 + + testedTier); 4.124 + } 4.125 + WHITE_BOX.enqueueMethodForCompilation(method, anotherTier); 4.126 + checkCompiled(); 4.127 + WHITE_BOX.deoptimizeMethod(method); 4.128 + } 4.129 + 4.130 + if (!WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY)) { 4.131 + throw new RuntimeException(method 4.132 + + " must be compilable at 'CompLevel::CompLevel_any'" 4.133 + + ", if it is not compilable only at " + testedTier); 4.134 + } 4.135 + } 4.136 + 4.137 + // clear state after test 4.138 + WHITE_BOX.clearMethodState(method); 4.139 + if (!WHITE_BOX.isMethodCompilable(method, testedTier)) { 4.140 + throw new RuntimeException(method 4.141 + + " is not compilable after clearMethodState()"); 4.142 + } 4.143 + } 4.144 + 4.145 + private boolean sameCompile(int level1, int level2) { 4.146 + if (level1 == level2) { 4.147 + return true; 4.148 + } 4.149 + if (isC1Compile(level1) && isC1Compile(level2)) { 4.150 + return true; 4.151 + } 4.152 + if (isC2Compile(level1) && isC2Compile(level2)) { 4.153 + return true; 4.154 + } 4.155 + return false; 4.156 + } 4.157 }