Bug 1343912 P2 Only execute consecutive timeout handlers for a limit period of time. r=ehsan

This commit is contained in:
Ben Kelly 2017-05-15 11:58:51 -07:00
Родитель ea4ddea556
Коммит dff08d6c5d
2 изменённых файлов: 37 добавлений и 0 удалений

Просмотреть файл

@ -184,6 +184,11 @@ uint32_t TimeoutManager::sNestingLevel = 0;
namespace {
// The maximum number of milliseconds to allow consecutive timer callbacks
// to run in a single event loop runnable.
#define DEFAULT_MAX_CONSECUTIVE_CALLBACK_MILLISECONDS 4
uint32_t gMaxConsecutiveCallbackMilliseconds;
// The maximum number of timer callbacks we will try to run in a single event
// loop runnable.
#define DEFAULT_TARGET_MAX_CONSECUTIVE_CALLBACKS 5
@ -304,6 +309,10 @@ TimeoutManager::Initialize()
Preferences::AddUintVarCache(&gTargetMaxConsecutiveCallbacks,
"dom.timeout.max_consecutive_callbacks",
DEFAULT_TARGET_MAX_CONSECUTIVE_CALLBACKS);
Preferences::AddUintVarCache(&gMaxConsecutiveCallbackMilliseconds,
"dom.timeout.max_consecutive_callback_ms",
DEFAULT_MAX_CONSECUTIVE_CALLBACK_MILLISECONDS);
}
uint32_t
@ -662,6 +671,12 @@ TimeoutManager::RunTimeout(Timeout* aTimeout)
mTrackingTimeouts.SetInsertionPoint(dummy_tracking_timeout);
}
uint32_t timeLimitMS = std::max(1u, gMaxConsecutiveCallbackMilliseconds);
const TimeDuration timeLimit = TimeDuration::FromMilliseconds(timeLimitMS);
TimeStamp start = TimeStamp::Now();
bool targetTimeoutSeen = false;
// We stop iterating each list when we go past the last expired timeout from
// that list that we have observed above. That timeout will either be the
// dummy timeout for the list that the last expired timeout came from, or it
@ -720,6 +735,24 @@ TimeoutManager::RunTimeout(Timeout* aTimeout)
continue;
}
// Check to see if we have run out of time to execute timeout handlers.
// If we've exceeded our time budget simply cleanup our remaining
// handlers to run by marking their firing depth back to zero.
//
// Note, we only do this if we have seen the Timeout object explicitly
// passed to RunTimeout(). The target timeout must always be executed.
if (targetTimeoutSeen) {
TimeDuration elapsed = TimeStamp::Now() - start;
if (elapsed >= timeLimit) {
timeout->mFiringDepth = 0;
continue;
}
}
if (timeout == aTimeout) {
targetTimeoutSeen = true;
}
// This timeout is good to run
bool timeout_was_cleared = mWindow.RunTimeoutHandler(timeout, scx);
MOZ_LOG(gLog, LogLevel::Debug,

Просмотреть файл

@ -5701,6 +5701,10 @@ pref("dom.moduleScripts.enabled", false);
// event loop runnable. Minimum value of 1.
pref("dom.timeout.max_consecutive_callbacks", 5);
// Maximum amount of time in milliseconds consecutive setTimeout()/setInterval()
// callback are allowed to run before yielding the event loop.
pref("dom.timeout.max_consecutive_callback_ms", 4);
#ifdef FUZZING
pref("fuzzing.enabled", false);
#endif