diff --git a/src/share/vm/classfile/classLoader.cpp b/src/share/vm/classfile/classLoader.cpp index 88dd6166856e94b68f22ff687e9d021a3db4c6c5..0a3b5caf19f2ae910aa7a1278dcb0c93eec3e30b 100644 --- a/src/share/vm/classfile/classLoader.cpp +++ b/src/share/vm/classfile/classLoader.cpp @@ -1350,13 +1350,13 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { _codecache_sweep_counter = 0; } // Force compilation - CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_initial_compile, + CompileBroker::compile_method(m, InvocationEntryBci, CompilationPolicy::policy()->initial_compile_level(), methodHandle(), 0, "CTW", THREAD); if (HAS_PENDING_EXCEPTION) { clear_pending_exception_if_not_oom(CHECK); tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string()); } - if (TieredCompilation) { + if (TieredCompilation && TieredStopAtLevel >= CompLevel_full_optimization) { // Clobber the first compile and force second tier compilation nmethod* nm = m->code(); if (nm != NULL) { diff --git a/src/share/vm/interpreter/linkResolver.cpp b/src/share/vm/interpreter/linkResolver.cpp index 7b42fe34f332524bcc512a6b9210e8e686715b4f..3d655afb402d160dacd42a5968bd028916533367 100644 --- a/src/share/vm/interpreter/linkResolver.cpp +++ b/src/share/vm/interpreter/linkResolver.cpp @@ -132,7 +132,7 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass return; } CompileBroker::compile_method(selected_method, InvocationEntryBci, - CompLevel_initial_compile, + CompilationPolicy::policy()->initial_compile_level(), methodHandle(), 0, "must_be_compiled", CHECK); } } diff --git a/src/share/vm/prims/methodHandles.cpp b/src/share/vm/prims/methodHandles.cpp index 6dc40a32b5ceb30b5e7713fc62765284027c9564..172e5ef17f17955f61db36e3eadbc80b8bf1cbcb 100644 --- a/src/share/vm/prims/methodHandles.cpp +++ b/src/share/vm/prims/methodHandles.cpp @@ -1016,7 +1016,7 @@ oop MethodHandles::encode_target(Handle mh, int format, TRAPS) { && CompilationPolicy::can_be_compiled(m)) { // Force compilation CompileBroker::compile_method(m, InvocationEntryBci, - CompLevel_initial_compile, + CompilationPolicy::policy()->initial_compile_level(), methodHandle(), 0, "MethodHandleNatives.getTarget", CHECK_NULL); } @@ -2713,7 +2713,7 @@ static void stress_method_handle_walk_impl(Handle mh, TRAPS) { && CompilationPolicy::can_be_compiled(m)) { // Force compilation CompileBroker::compile_method(m, InvocationEntryBci, - CompLevel_initial_compile, + CompilationPolicy::policy()->initial_compile_level(), methodHandle(), 0, "StressMethodHandleWalk", CHECK); } diff --git a/src/share/vm/runtime/advancedThresholdPolicy.cpp b/src/share/vm/runtime/advancedThresholdPolicy.cpp index 550d84d4ad1d18251df3cf38309a5fe620ed8484..758bf5ce5058f1914fdf1ae23fa077e1a7d175de 100644 --- a/src/share/vm/runtime/advancedThresholdPolicy.cpp +++ b/src/share/vm/runtime/advancedThresholdPolicy.cpp @@ -189,7 +189,8 @@ CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { task = next_task; } - if (max_task->comp_level() == CompLevel_full_profile && is_method_profiled(max_method)) { + if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile + && is_method_profiled(max_method)) { max_task->set_comp_level(CompLevel_limited_profile); if (PrintTieredEvents) { print_event(UPDATE_IN_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level()); @@ -321,77 +322,79 @@ void AdvancedThresholdPolicy::create_mdo(methodHandle mh, TRAPS) { */ // Common transition function. Given a predicate determines if a method should transition to another level. -CompLevel AdvancedThresholdPolicy::common(Predicate p, methodOop method, CompLevel cur_level) { - if (is_trivial(method)) return CompLevel_simple; - +CompLevel AdvancedThresholdPolicy::common(Predicate p, methodOop method, CompLevel cur_level, bool disable_feedback) { CompLevel next_level = cur_level; int i = method->invocation_count(); int b = method->backedge_count(); - switch(cur_level) { - case CompLevel_none: - // If we were at full profile level, would we switch to full opt? - if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) { - next_level = CompLevel_full_optimization; - } else if ((this->*p)(i, b, cur_level)) { - // C1-generated fully profiled code is about 30% slower than the limited profile - // code that has only invocation and backedge counters. The observation is that - // if C2 queue is large enough we can spend too much time in the fully profiled code - // while waiting for C2 to pick the method from the queue. To alleviate this problem - // we introduce a feedback on the C2 queue size. If the C2 queue is sufficiently long - // we choose to compile a limited profiled version and then recompile with full profiling - // when the load on C2 goes down. - if (CompileBroker::queue_size(CompLevel_full_optimization) > - Tier3DelayOn * compiler_count(CompLevel_full_optimization)) { - next_level = CompLevel_limited_profile; - } else { - next_level = CompLevel_full_profile; + if (is_trivial(method)) { + next_level = CompLevel_simple; + } else { + switch(cur_level) { + case CompLevel_none: + // If we were at full profile level, would we switch to full opt? + if (common(p, method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) { + next_level = CompLevel_full_optimization; + } else if ((this->*p)(i, b, cur_level)) { + // C1-generated fully profiled code is about 30% slower than the limited profile + // code that has only invocation and backedge counters. The observation is that + // if C2 queue is large enough we can spend too much time in the fully profiled code + // while waiting for C2 to pick the method from the queue. To alleviate this problem + // we introduce a feedback on the C2 queue size. If the C2 queue is sufficiently long + // we choose to compile a limited profiled version and then recompile with full profiling + // when the load on C2 goes down. + if (!disable_feedback && CompileBroker::queue_size(CompLevel_full_optimization) > + Tier3DelayOn * compiler_count(CompLevel_full_optimization)) { + next_level = CompLevel_limited_profile; + } else { + next_level = CompLevel_full_profile; + } } - } - break; - case CompLevel_limited_profile: - if (is_method_profiled(method)) { - // Special case: we got here because this method was fully profiled in the interpreter. - next_level = CompLevel_full_optimization; - } else { - methodDataOop mdo = method->method_data(); - if (mdo != NULL) { - if (mdo->would_profile()) { - if (CompileBroker::queue_size(CompLevel_full_optimization) <= - Tier3DelayOff * compiler_count(CompLevel_full_optimization) && - (this->*p)(i, b, cur_level)) { - next_level = CompLevel_full_profile; + break; + case CompLevel_limited_profile: + if (is_method_profiled(method)) { + // Special case: we got here because this method was fully profiled in the interpreter. + next_level = CompLevel_full_optimization; + } else { + methodDataOop mdo = method->method_data(); + if (mdo != NULL) { + if (mdo->would_profile()) { + if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <= + Tier3DelayOff * compiler_count(CompLevel_full_optimization) && + (this->*p)(i, b, cur_level))) { + next_level = CompLevel_full_profile; + } + } else { + next_level = CompLevel_full_optimization; } - } else { - next_level = CompLevel_full_optimization; } } - } - break; - case CompLevel_full_profile: - { - methodDataOop mdo = method->method_data(); - if (mdo != NULL) { - if (mdo->would_profile()) { - int mdo_i = mdo->invocation_count_delta(); - int mdo_b = mdo->backedge_count_delta(); - if ((this->*p)(mdo_i, mdo_b, cur_level)) { + break; + case CompLevel_full_profile: + { + methodDataOop mdo = method->method_data(); + if (mdo != NULL) { + if (mdo->would_profile()) { + int mdo_i = mdo->invocation_count_delta(); + int mdo_b = mdo->backedge_count_delta(); + if ((this->*p)(mdo_i, mdo_b, cur_level)) { + next_level = CompLevel_full_optimization; + } + } else { next_level = CompLevel_full_optimization; } - } else { - next_level = CompLevel_full_optimization; } } + break; } - break; } - return next_level; + return MIN2(next_level, (CompLevel)TieredStopAtLevel); } // Determine if a method should be compiled with a normal entry point at a different level. CompLevel AdvancedThresholdPolicy::call_event(methodOop method, CompLevel cur_level) { CompLevel osr_level = MIN2((CompLevel) method->highest_osr_comp_level(), - common(&AdvancedThresholdPolicy::loop_predicate, method, cur_level)); + common(&AdvancedThresholdPolicy::loop_predicate, method, cur_level, true)); CompLevel next_level = common(&AdvancedThresholdPolicy::call_predicate, method, cur_level); // If OSR method level is greater than the regular method level, the levels should be @@ -406,13 +409,12 @@ CompLevel AdvancedThresholdPolicy::call_event(methodOop method, CompLevel cur_le } else { next_level = MAX2(osr_level, next_level); } - return next_level; } // Determine if we should do an OSR compilation of a given method. CompLevel AdvancedThresholdPolicy::loop_event(methodOop method, CompLevel cur_level) { - CompLevel next_level = common(&AdvancedThresholdPolicy::loop_predicate, method, cur_level); + CompLevel next_level = common(&AdvancedThresholdPolicy::loop_predicate, method, cur_level, true); if (cur_level == CompLevel_none) { // If there is a live OSR method that means that we deopted to the interpreter // for the transition. @@ -460,22 +462,9 @@ void AdvancedThresholdPolicy::method_back_branch_event(methodHandle mh, methodHa if (is_compilation_enabled()) { CompLevel next_osr_level = loop_event(imh(), level); CompLevel max_osr_level = (CompLevel)imh->highest_osr_comp_level(); - if (next_osr_level == CompLevel_limited_profile) { - next_osr_level = CompLevel_full_profile; // OSRs are supposed to be for very hot methods. - } - // At the very least compile the OSR version - if (!CompileBroker::compilation_is_in_queue(imh, bci)) { - // Check if there's a method like that already - nmethod* osr_nm = NULL; - if (max_osr_level >= next_osr_level) { - // There is an osr method already with the same - // or greater level, check if it has the bci we need - osr_nm = imh->lookup_osr_nmethod_for(bci, next_osr_level, false); - } - if (osr_nm == NULL) { - compile(imh, bci, next_osr_level, THREAD); - } + if (!CompileBroker::compilation_is_in_queue(imh, bci) && next_osr_level != level) { + compile(imh, bci, next_osr_level, THREAD); } // Use loop event as an opportunity to also check if there's been diff --git a/src/share/vm/runtime/advancedThresholdPolicy.hpp b/src/share/vm/runtime/advancedThresholdPolicy.hpp index 7f000b9866617dd652e710a3bbd33d9cf469f499..58be8b2dc91fba82bb58f180bbbcfccac7ca8a7f 100644 --- a/src/share/vm/runtime/advancedThresholdPolicy.hpp +++ b/src/share/vm/runtime/advancedThresholdPolicy.hpp @@ -168,7 +168,7 @@ class AdvancedThresholdPolicy : public SimpleThresholdPolicy { bool call_predicate(int i, int b, CompLevel cur_level); bool loop_predicate(int i, int b, CompLevel cur_level); // Common transition function. Given a predicate determines if a method should transition to another level. - CompLevel common(Predicate p, methodOop method, CompLevel cur_level); + CompLevel common(Predicate p, methodOop method, CompLevel cur_level, bool disable_feedback = false); // Transition functions. // call_event determines if a method should be compiled at a different // level with a regular invocation entry. diff --git a/src/share/vm/runtime/compilationPolicy.hpp b/src/share/vm/runtime/compilationPolicy.hpp index 6282688a266c13cd1a02ad113950bf1724964693..b9d70664b989daaa340d31bde2d88e230848c114 100644 --- a/src/share/vm/runtime/compilationPolicy.hpp +++ b/src/share/vm/runtime/compilationPolicy.hpp @@ -59,6 +59,8 @@ public: // Profiling elapsedTimer* accumulated_time() { return &_accumulated_time; } void print_time() PRODUCT_RETURN; + // Return initial compile level that is used with Xcomp + virtual CompLevel initial_compile_level() = 0; virtual int compiler_count(CompLevel comp_level) = 0; // main notification entry, return a pointer to an nmethod if the OSR is required, // returns NULL otherwise. @@ -94,6 +96,7 @@ protected: void reset_counter_for_back_branch_event(methodHandle method); public: NonTieredCompPolicy() : _compiler_count(0) { } + virtual CompLevel initial_compile_level() { return CompLevel_initial_compile; } virtual int compiler_count(CompLevel comp_level); virtual void do_safepoint_work(); virtual void reprofile(ScopeDesc* trap_scope, bool is_osr); diff --git a/src/share/vm/runtime/javaCalls.cpp b/src/share/vm/runtime/javaCalls.cpp index eca02a49629fa12fa2b080309c452c6a50011fde..d422c6c868f458a01cb0ed9a8cc1068550e25057 100644 --- a/src/share/vm/runtime/javaCalls.cpp +++ b/src/share/vm/runtime/javaCalls.cpp @@ -355,7 +355,7 @@ void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArgument assert(!thread->is_Compiler_thread(), "cannot compile from the compiler"); if (CompilationPolicy::must_be_compiled(method)) { CompileBroker::compile_method(method, InvocationEntryBci, - CompLevel_initial_compile, + CompilationPolicy::policy()->initial_compile_level(), methodHandle(), 0, "must_be_compiled", CHECK); } diff --git a/src/share/vm/runtime/simpleThresholdPolicy.cpp b/src/share/vm/runtime/simpleThresholdPolicy.cpp index 13e3b82a15b803598573f7ae257a50d5f8e9cabe..d132c0e96b26a9a2654bd95185edb6352f2d8889 100644 --- a/src/share/vm/runtime/simpleThresholdPolicy.cpp +++ b/src/share/vm/runtime/simpleThresholdPolicy.cpp @@ -206,11 +206,7 @@ nmethod* SimpleThresholdPolicy::event(methodHandle method, methodHandle inlinee, // Check if the method can be compiled, change level if necessary void SimpleThresholdPolicy::compile(methodHandle mh, int bci, CompLevel level, TRAPS) { - // Take the given ceiling into the account. - // NOTE: You can set it to 1 to get a pure C1 version. - if ((CompLevel)TieredStopAtLevel < level) { - level = (CompLevel)TieredStopAtLevel; - } + assert(level <= TieredStopAtLevel, "Invalid compilation level"); if (level == CompLevel_none) { return; } @@ -227,10 +223,10 @@ void SimpleThresholdPolicy::compile(methodHandle mh, int bci, CompLevel level, T if (bci != InvocationEntryBci && mh->is_not_osr_compilable()) { return; } - if (PrintTieredEvents) { - print_event(COMPILE, mh, mh, bci, level); - } if (!CompileBroker::compilation_is_in_queue(mh, bci)) { + if (PrintTieredEvents) { + print_event(COMPILE, mh, mh, bci, level); + } submit_compile(mh, bci, level, THREAD); } } @@ -288,40 +284,42 @@ bool SimpleThresholdPolicy::is_mature(methodOop method) { // Common transition function. Given a predicate determines if a method should transition to another level. CompLevel SimpleThresholdPolicy::common(Predicate p, methodOop method, CompLevel cur_level) { - if (is_trivial(method)) return CompLevel_simple; - CompLevel next_level = cur_level; int i = method->invocation_count(); int b = method->backedge_count(); - switch(cur_level) { - case CompLevel_none: - // If we were at full profile level, would we switch to full opt? - if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) { - next_level = CompLevel_full_optimization; - } else if ((this->*p)(i, b, cur_level)) { - next_level = CompLevel_full_profile; - } - break; - case CompLevel_limited_profile: - case CompLevel_full_profile: - { - methodDataOop mdo = method->method_data(); - if (mdo != NULL) { - if (mdo->would_profile()) { - int mdo_i = mdo->invocation_count_delta(); - int mdo_b = mdo->backedge_count_delta(); - if ((this->*p)(mdo_i, mdo_b, cur_level)) { + if (is_trivial(method)) { + next_level = CompLevel_simple; + } else { + switch(cur_level) { + case CompLevel_none: + // If we were at full profile level, would we switch to full opt? + if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) { + next_level = CompLevel_full_optimization; + } else if ((this->*p)(i, b, cur_level)) { + next_level = CompLevel_full_profile; + } + break; + case CompLevel_limited_profile: + case CompLevel_full_profile: + { + methodDataOop mdo = method->method_data(); + if (mdo != NULL) { + if (mdo->would_profile()) { + int mdo_i = mdo->invocation_count_delta(); + int mdo_b = mdo->backedge_count_delta(); + if ((this->*p)(mdo_i, mdo_b, cur_level)) { + next_level = CompLevel_full_optimization; + } + } else { next_level = CompLevel_full_optimization; } - } else { - next_level = CompLevel_full_optimization; } } + break; } - break; } - return next_level; + return MIN2(next_level, (CompLevel)TieredStopAtLevel); } // Determine if a method should be compiled with a normal entry point at a different level. diff --git a/src/share/vm/runtime/simpleThresholdPolicy.hpp b/src/share/vm/runtime/simpleThresholdPolicy.hpp index a7bad850b155eed41389385fb10e4a374362d630..5aad121c3ecb780a1bdd98d551909719ae6f2803 100644 --- a/src/share/vm/runtime/simpleThresholdPolicy.hpp +++ b/src/share/vm/runtime/simpleThresholdPolicy.hpp @@ -98,6 +98,7 @@ public: if (is_c2_compile(comp_level)) return c2_count(); return 0; } + virtual CompLevel initial_compile_level() { return MIN2((CompLevel)TieredStopAtLevel, CompLevel_initial_compile); } virtual void do_safepoint_work() { } virtual void delay_compilation(methodOop method) { } virtual void disable_compilation(methodOop method) { }