提交 af8f4bbe 编写于 作者: I iveresov

7066339: Tiered: policy should make consistent decisions about osr levels

Summary: Added feedback disabling flag to common(), fixed handling of TieredStopAtLevel.
Reviewed-by: kvn, never
上级 41830f90
......@@ -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) {
......
......@@ -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);
}
}
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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.
......
......@@ -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);
......
......@@ -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);
}
......
......@@ -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.
......
......@@ -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) { }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册