# HG changeset patch # User vlivanov # Date 1366990419 25200 # Node ID 93b8272814cf7dfbf8ea51cf74b728e85424f445 # Parent a5c95fcf7cb720d8eedf39d8f8827df17c4f96d1# Parent d1c9384eecb4772fcd6b86df75dc95f2e74b11a1 Merge diff -r a5c95fcf7cb7 -r 93b8272814cf src/share/vm/classfile/classLoader.cpp --- a/src/share/vm/classfile/classLoader.cpp Tue Apr 23 18:06:54 2013 +0200 +++ b/src/share/vm/classfile/classLoader.cpp Fri Apr 26 08:33:39 2013 -0700 @@ -1345,9 +1345,10 @@ tty->print_cr("CompileTheWorld (%d) : %s", _compile_the_world_class_counter, buffer); // Preload all classes to get around uncommon traps // Iterate over all methods in class + int comp_level = CompilationPolicy::policy()->initial_compile_level(); for (int n = 0; n < k->methods()->length(); n++) { methodHandle m (THREAD, k->methods()->at(n)); - if (CompilationPolicy::can_be_compiled(m)) { + if (CompilationPolicy::can_be_compiled(m, comp_level)) { if (++_codecache_sweep_counter == CompileTheWorldSafepointInterval) { // Give sweeper a chance to keep up with CTW @@ -1356,7 +1357,7 @@ _codecache_sweep_counter = 0; } // Force compilation - CompileBroker::compile_method(m, InvocationEntryBci, CompilationPolicy::policy()->initial_compile_level(), + CompileBroker::compile_method(m, InvocationEntryBci, comp_level, methodHandle(), 0, "CTW", THREAD); if (HAS_PENDING_EXCEPTION) { clear_pending_exception_if_not_oom(CHECK); diff -r a5c95fcf7cb7 -r 93b8272814cf src/share/vm/runtime/compilationPolicy.cpp --- a/src/share/vm/runtime/compilationPolicy.cpp Tue Apr 23 18:06:54 2013 +0200 +++ b/src/share/vm/runtime/compilationPolicy.cpp Fri Apr 26 08:33:39 2013 -0700 @@ -109,6 +109,9 @@ // Returns true if m is allowed to be compiled bool CompilationPolicy::can_be_compiled(methodHandle m, int comp_level) { + // allow any levels for WhiteBox + assert(WhiteBoxAPI || comp_level == CompLevel_all || is_compile(comp_level), "illegal compilation level"); + if (m->is_abstract()) return false; if (DontCompileHugeMethods && m->code_size() > HugeMethodLimit) return false; @@ -122,7 +125,13 @@ return false; } if (comp_level == CompLevel_all) { - return !m->is_not_compilable(CompLevel_simple) && !m->is_not_compilable(CompLevel_full_optimization); + if (TieredCompilation) { + // enough to be compilable at any level for tiered + return !m->is_not_compilable(CompLevel_simple) || !m->is_not_compilable(CompLevel_full_optimization); + } else { + // must be compilable at available level for non-tiered + return !m->is_not_compilable(CompLevel_highest_tier); + } } else if (is_compile(comp_level)) { return !m->is_not_compilable(comp_level); } @@ -436,7 +445,7 @@ reset_counter_for_invocation_event(m); const char* comment = "count"; - if (is_compilation_enabled() && can_be_compiled(m)) { + if (is_compilation_enabled() && can_be_compiled(m, comp_level)) { nmethod* nm = m->code(); if (nm == NULL ) { CompileBroker::compile_method(m, InvocationEntryBci, comp_level, m, hot_count, comment, thread); @@ -449,7 +458,7 @@ const int hot_count = m->backedge_count(); const char* comment = "backedge_count"; - if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m)) { + if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m, comp_level)) { CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) } @@ -467,7 +476,7 @@ reset_counter_for_invocation_event(m); const char* comment = "count"; - if (is_compilation_enabled() && m->code() == NULL && can_be_compiled(m)) { + if (is_compilation_enabled() && m->code() == NULL && can_be_compiled(m, comp_level)) { ResourceMark rm(thread); frame fr = thread->last_frame(); assert(fr.is_interpreted_frame(), "must be interpreted"); @@ -505,7 +514,7 @@ const int hot_count = m->backedge_count(); const char* comment = "backedge_count"; - if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m)) { + if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m, comp_level)) { CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) } @@ -600,7 +609,7 @@ // If the caller method is too big or something then we do not want to // compile it just to inline a method - if (!can_be_compiled(next_m)) { + if (!can_be_compiled(next_m, CompLevel_any)) { msg = "caller cannot be compiled"; break; } diff -r a5c95fcf7cb7 -r 93b8272814cf test/compiler/whitebox/CompilerWhiteBoxTest.java --- a/test/compiler/whitebox/CompilerWhiteBoxTest.java Tue Apr 23 18:06:54 2013 +0200 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Fri Apr 26 08:33:39 2013 -0700 @@ -42,6 +42,11 @@ protected static int COMP_LEVEL_NONE = 0; /** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */ protected static int COMP_LEVEL_ANY = -1; + /** {@code CompLevel::CompLevel_simple} -- C1 */ + protected static int COMP_LEVEL_SIMPLE = 1; + /** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */ + protected static int COMP_LEVEL_FULL_OPTIMIZATION = 4; + /** Instance of WhiteBox */ protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); /** Value of {@code -XX:CompileThreshold} */ @@ -91,6 +96,17 @@ return result == null ? defaultValue : result; } + /** copy of is_c1_compile(int) from utilities/globalDefinitions.hpp */ + protected static boolean isC1Compile(int compLevel) { + return (compLevel > COMP_LEVEL_NONE) + && (compLevel < COMP_LEVEL_FULL_OPTIMIZATION); + } + + /** copy of is_c2_compile(int) from utilities/globalDefinitions.hpp */ + protected static boolean isC2Compile(int compLevel) { + return compLevel == COMP_LEVEL_FULL_OPTIMIZATION; + } + /** tested method */ protected final Executable method; private final Callable callable; diff -r a5c95fcf7cb7 -r 93b8272814cf test/compiler/whitebox/MakeMethodNotCompilableTest.java --- a/test/compiler/whitebox/MakeMethodNotCompilableTest.java Tue Apr 23 18:06:54 2013 +0200 +++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Apr 26 08:33:39 2013 -0700 @@ -23,6 +23,7 @@ /* * @test MakeMethodNotCompilableTest + * @bug 8012322 * @library /testlibrary /testlibrary/whitebox * @build MakeMethodNotCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -67,28 +68,69 @@ } if (TIERED_COMPILATION) { - for (int i = 1, n = TIERED_STOP_AT_LEVEL + 1; i < n; ++i) { - WHITE_BOX.makeMethodNotCompilable(method, i); - if (WHITE_BOX.isMethodCompilable(method, i)) { + final int tierLimit = TIERED_STOP_AT_LEVEL + 1; + for (int testedTier = 1; testedTier < tierLimit; ++testedTier) { + testTier(testedTier); + } + for (int testedTier = 1; testedTier < tierLimit; ++testedTier) { + WHITE_BOX.makeMethodNotCompilable(method, testedTier); + if (WHITE_BOX.isMethodCompilable(method, testedTier)) { throw new RuntimeException(method - + " must be not compilable at level" + i); + + " must be not compilable at level" + testedTier); } - WHITE_BOX.enqueueMethodForCompilation(method, i); + WHITE_BOX.enqueueMethodForCompilation(method, testedTier); checkNotCompiled(); if (!WHITE_BOX.isMethodCompilable(method)) { System.out.println(method - + " is not compilable after level " + i); + + " is not compilable after level " + testedTier); } } + } else { + compile(); + checkCompiled(); + int compLevel = WHITE_BOX.getMethodCompilationLevel(method); + WHITE_BOX.deoptimizeMethod(method); + WHITE_BOX.makeMethodNotCompilable(method, compLevel); + if (WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY)) { + throw new RuntimeException(method + + " must be not compilable at CompLevel::CompLevel_any," + + " after it is not compilable at " + compLevel); + } + WHITE_BOX.clearMethodState(method); + + // nocompilable at opposite level must make no sense + int oppositeLevel; + if (isC1Compile(compLevel)) { + oppositeLevel = COMP_LEVEL_FULL_OPTIMIZATION; + } else { + oppositeLevel = COMP_LEVEL_SIMPLE; + } + WHITE_BOX.makeMethodNotCompilable(method, oppositeLevel); + + if (!WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY)) { + throw new RuntimeException(method + + " must be compilable at CompLevel::CompLevel_any," + + " even it is not compilable at opposite level [" + + compLevel + "]"); + } - // WB.clearMethodState() must reset no-compilable flags - WHITE_BOX.clearMethodState(method); - if (!WHITE_BOX.isMethodCompilable(method)) { - throw new RuntimeException(method - + " is not compilable after clearMethodState()"); + if (!WHITE_BOX.isMethodCompilable(method, compLevel)) { + throw new RuntimeException(method + + " must be compilable at level " + compLevel + + ", even it is not compilable at opposite level [" + + compLevel + "]"); } } + + // clearing after tiered/non-tiered tests + // WB.clearMethodState() must reset no-compilable flags + WHITE_BOX.clearMethodState(method); + if (!WHITE_BOX.isMethodCompilable(method)) { + throw new RuntimeException(method + + " is not compilable after clearMethodState()"); + } + WHITE_BOX.makeMethodNotCompilable(method); if (WHITE_BOX.isMethodCompilable(method)) { throw new RuntimeException(method + " must be not compilable"); @@ -108,4 +150,65 @@ compile(); checkCompiled(); } + + // separately tests each tier + private void testTier(int testedTier) { + if (!WHITE_BOX.isMethodCompilable(method, testedTier)) { + throw new RuntimeException(method + + " is not compilable on start"); + } + WHITE_BOX.makeMethodNotCompilable(method, testedTier); + + // tests for all other tiers + for (int anotherTier = 1, tierLimit = TIERED_STOP_AT_LEVEL + 1; + anotherTier < tierLimit; ++anotherTier) { + boolean isCompilable = WHITE_BOX.isMethodCompilable(method, + anotherTier); + if (sameCompile(testedTier, anotherTier)) { + if (isCompilable) { + throw new RuntimeException(method + + " must be not compilable at level " + anotherTier + + ", if it is not compilable at " + testedTier); + } + WHITE_BOX.enqueueMethodForCompilation(method, anotherTier); + checkNotCompiled(); + } else { + if (!isCompilable) { + throw new RuntimeException(method + + " must be compilable at level " + anotherTier + + ", even if it is not compilable at " + + testedTier); + } + WHITE_BOX.enqueueMethodForCompilation(method, anotherTier); + checkCompiled(); + WHITE_BOX.deoptimizeMethod(method); + } + + if (!WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY)) { + throw new RuntimeException(method + + " must be compilable at 'CompLevel::CompLevel_any'" + + ", if it is not compilable only at " + testedTier); + } + } + + // clear state after test + WHITE_BOX.clearMethodState(method); + if (!WHITE_BOX.isMethodCompilable(method, testedTier)) { + throw new RuntimeException(method + + " is not compilable after clearMethodState()"); + } + } + + private boolean sameCompile(int level1, int level2) { + if (level1 == level2) { + return true; + } + if (isC1Compile(level1) && isC1Compile(level2)) { + return true; + } + if (isC2Compile(level1) && isC2Compile(level2)) { + return true; + } + return false; + } }