// Called with the queue locked and with at least one element CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { #if INCLUDE_JVMCI CompileTask *max_non_jvmci_task = NULL; #endif CompileTask *max_task = NULL; Method* max_method = NULL; jlong t = os::javaTimeMillis(); // Iterate through the queue and find a method with a maximum rate. for (CompileTask* task = compile_queue->first(); task != NULL;) { CompileTask* next_task = task->next(); Method* method = task->method(); update_rate(t, method); if (max_task == NULL) { max_task = task; max_method = method; } else { // 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(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level()); } task->log_task_dequeued("stale"); compile_queue->remove_and_mark_stale(task); method->clear_queued_for_compilation(); task = next_task; continue; } // Select a method with a higher rate if (compare_methods(method, max_method)) { max_task = task; max_method = method; } } task = next_task; } #if INCLUDE_JVMCI if (UseJVMCICompiler) { if (max_non_jvmci_task != NULL) { max_task = max_non_jvmci_task; max_method = max_task->method(); } } #endif 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()); } } return max_task; }
// Called with the queue locked and with at least one element CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { CompileTask *max_task = NULL; methodOop max_method; jlong t = os::javaTimeMillis(); // Iterate through the queue and find a method with a maximum rate. for (CompileTask* task = compile_queue->first(); task != NULL;) { CompileTask* next_task = task->next(); methodOop method = (methodOop)JNIHandles::resolve(task->method_handle()); methodDataOop mdo = method->method_data(); update_rate(t, method); if (max_task == NULL) { max_task = task; max_method = method; } else { // 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()); } CompileTaskWrapper ctw(task); // Frees the task compile_queue->remove(task); method->clear_queued_for_compilation(); task = next_task; continue; } // Select a method with a higher rate if (compare_methods(method, max_method)) { max_task = task; max_method = method; } } task = next_task; } 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()); } } return max_task; }
// 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 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; } } 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; } } 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)) { next_level = CompLevel_full_optimization; } } else { next_level = CompLevel_full_optimization; } } } break; } return next_level; }
// Common transition function. Given a predicate determines if a method should transition to another level. CompLevel AdvancedThresholdPolicy::common(Predicate p, Method* method, CompLevel cur_level, bool disable_feedback) { CompLevel next_level = cur_level; int i = method->invocation_count(); int b = method->backedge_count(); 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, method)) { #if INCLUDE_JVMCI if (UseJVMCICompiler) { // Since JVMCI takes a while to warm up, its queue inevitably backs up during // early VM execution. next_level = CompLevel_full_profile; break; } #endif // 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 { MethodData* 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, method))) { next_level = CompLevel_full_profile; } } else { next_level = CompLevel_full_optimization; } } } break; case CompLevel_full_profile: { MethodData* 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, method)) { next_level = CompLevel_full_optimization; } } else { next_level = CompLevel_full_optimization; } } } break; } } return MIN2(next_level, (CompLevel)TieredStopAtLevel); }