--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Fri Jul 01 10:35:54 2011 -0700
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Fri Jul 01 10:37:37 2011 -0700
@@ -171,7 +171,7 @@
// If a method has been stale for some time, remove it from the queue.
if (is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) {
if (PrintTieredEvents) {
- print_event(KILL, method, method, task->osr_bci(), (CompLevel)task->comp_level());
+ print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level());
}
CompileTaskWrapper ctw(task); // Frees the task
compile_queue->remove(task);
@@ -192,7 +192,7 @@
if (max_task->comp_level() == CompLevel_full_profile && is_method_profiled(max_method)) {
max_task->set_comp_level(CompLevel_limited_profile);
if (PrintTieredEvents) {
- print_event(UPDATE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level());
+ print_event(UPDATE_IN_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level());
}
}
@@ -259,6 +259,17 @@
return false;
}
+// Inlining control: if we're compiling a profiled method with C1 and the callee
+// is known to have OSRed in a C2 version, don't inline it.
+bool AdvancedThresholdPolicy::should_not_inline(ciEnv* env, ciMethod* callee) {
+ CompLevel comp_level = (CompLevel)env->comp_level();
+ if (comp_level == CompLevel_full_profile ||
+ comp_level == CompLevel_limited_profile) {
+ return callee->highest_osr_comp_level() == CompLevel_full_optimization;
+ }
+ return false;
+}
+
// Create MDO if necessary.
void AdvancedThresholdPolicy::create_mdo(methodHandle mh, TRAPS) {
if (mh->is_native() || mh->is_abstract() || mh->is_accessor()) return;
@@ -420,10 +431,9 @@
CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", THREAD);
}
-
// Handle the invocation event.
void AdvancedThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh,
- CompLevel level, TRAPS) {
+ CompLevel level, nmethod* nm, TRAPS) {
if (should_create_mdo(mh(), level)) {
create_mdo(mh, THREAD);
}
@@ -438,32 +448,81 @@
// Handle the back branch event. Notice that we can compile the method
// with a regular entry from here.
void AdvancedThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh,
- int bci, CompLevel level, TRAPS) {
+ int bci, CompLevel level, nmethod* nm, TRAPS) {
if (should_create_mdo(mh(), level)) {
create_mdo(mh, THREAD);
}
+ // Check if MDO should be created for the inlined method
+ if (should_create_mdo(imh(), level)) {
+ create_mdo(imh, THREAD);
+ }
- // If the method is already compiling, quickly bail out.
- if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, bci)) {
- // Use loop event as an opportinity to also check there's been
- // enough calls.
- CompLevel cur_level = comp_level(mh());
- CompLevel next_level = call_event(mh(), cur_level);
- CompLevel next_osr_level = loop_event(mh(), level);
+ 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.
}
- next_level = MAX2(next_level,
- next_osr_level < CompLevel_full_optimization ? next_osr_level : cur_level);
- bool is_compiling = false;
- if (next_level != cur_level) {
- compile(mh, InvocationEntryBci, next_level, THREAD);
- is_compiling = true;
+
+ // 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);
+ }
}
- // Do the OSR version
- if (!is_compiling && next_osr_level != level) {
- compile(mh, bci, next_osr_level, THREAD);
+ // Use loop event as an opportunity to also check if there's been
+ // enough calls.
+ CompLevel cur_level, next_level;
+ if (mh() != imh()) { // If there is an enclosing method
+ guarantee(nm != NULL, "Should have nmethod here");
+ cur_level = comp_level(mh());
+ next_level = call_event(mh(), cur_level);
+
+ if (max_osr_level == CompLevel_full_optimization) {
+ // The inlinee OSRed to full opt, we need to modify the enclosing method to avoid deopts
+ bool make_not_entrant = false;
+ if (nm->is_osr_method()) {
+ // This is an osr method, just make it not entrant and recompile later if needed
+ make_not_entrant = true;
+ } else {
+ if (next_level != CompLevel_full_optimization) {
+ // next_level is not full opt, so we need to recompile the
+ // enclosing method without the inlinee
+ cur_level = CompLevel_none;
+ make_not_entrant = true;
+ }
+ }
+ if (make_not_entrant) {
+ if (PrintTieredEvents) {
+ int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci;
+ print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level);
+ }
+ nm->make_not_entrant();
+ }
+ }
+ if (!CompileBroker::compilation_is_in_queue(mh, InvocationEntryBci)) {
+ // Fix up next_level if necessary to avoid deopts
+ if (next_level == CompLevel_limited_profile && max_osr_level == CompLevel_full_profile) {
+ next_level = CompLevel_full_profile;
+ }
+ if (cur_level != next_level) {
+ compile(mh, InvocationEntryBci, next_level, THREAD);
+ }
+ }
+ } else {
+ cur_level = comp_level(imh());
+ next_level = call_event(imh(), cur_level);
+ if (!CompileBroker::compilation_is_in_queue(imh, bci) && next_level != cur_level) {
+ compile(imh, InvocationEntryBci, next_level, THREAD);
+ }
}
}
}