// update_rate() is called from select_task() while holding a compile queue lock. void AdvancedThresholdPolicy::update_rate(jlong t, methodOop m) { if (is_old(m)) { // We don't remove old methods from the queue, // so we can just zero the rate. m->set_rate(0); return; } // We don't update the rate if we've just came out of a safepoint. // delta_s is the time since last safepoint in milliseconds. jlong delta_s = t - SafepointSynchronize::end_of_last_safepoint(); jlong delta_t = t - (m->prev_time() != 0 ? m->prev_time() : start_time()); // milliseconds since the last measurement // How many events were there since the last time? int event_count = m->invocation_count() + m->backedge_count(); int delta_e = event_count - m->prev_event_count(); // We should be running for at least 1ms. if (delta_s >= TieredRateUpdateMinTime) { // And we must've taken the previous point at least 1ms before. if (delta_t >= TieredRateUpdateMinTime && delta_e > 0) { m->set_prev_time(t); m->set_prev_event_count(event_count); m->set_rate((float)delta_e / (float)delta_t); // Rate is events per millisecond } else if (delta_t > TieredRateUpdateMaxTime && delta_e == 0) { // If nothing happened for 25ms, zero the rate. Don't modify prev values. m->set_rate(0); } } }
// Check if this method has been stale from a given number of milliseconds. // See select_task(). bool AdvancedThresholdPolicy::is_stale(jlong t, jlong timeout, methodOop m) { jlong delta_s = t - SafepointSynchronize::end_of_last_safepoint(); jlong delta_t = t - m->prev_time(); if (delta_t > timeout && delta_s > timeout) { int event_count = m->invocation_count() + m->backedge_count(); int delta_e = event_count - m->prev_event_count(); // Return true if there were no events. return delta_e == 0; } return false; }
// If a method is old enough and is still in the interpreter we would want to // start profiling without waiting for the compiled method to arrive. // We also take the load on compilers into the account. bool AdvancedThresholdPolicy::should_create_mdo(methodOop method, CompLevel cur_level) { if (cur_level == CompLevel_none && CompileBroker::queue_size(CompLevel_full_optimization) <= Tier3DelayOn * compiler_count(CompLevel_full_optimization)) { int i = method->invocation_count(); int b = method->backedge_count(); double k = Tier0ProfilingStartPercentage / 100.0; return call_predicate_helper<CompLevel_none>(i, b, k) || loop_predicate_helper<CompLevel_none>(i, b, k); } return false; }
// Get a measure of how much mileage the method has on it. int methodDataOopDesc::mileage_of(methodOop method) { int mileage = 0; if (TieredCompilation) { mileage = MAX2(method->invocation_count(), method->backedge_count()); } else { int iic = method->interpreter_invocation_count(); if (mileage < iic) mileage = iic; InvocationCounter* ic = method->invocation_counter(); InvocationCounter* bc = method->backedge_counter(); int icval = ic->count(); if (ic->carry()) icval += CompileThreshold; if (mileage < icval) mileage = icval; int bcval = bc->count(); if (bc->carry()) bcval += CompileThreshold; if (mileage < bcval) mileage = bcval; } return mileage; }
// 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; }
double AdvancedThresholdPolicy::weight(methodOop method) { return (method->rate() + 1) * ((method->invocation_count() + 1) * (method->backedge_count() + 1)); }
// We don't remove old methods from the compile queue even if they have // very low activity. See select_task(). bool AdvancedThresholdPolicy::is_old(methodOop method) { return method->invocation_count() > 50000 || method->backedge_count() > 500000; }