Bug 1415780 - Don't count all observers for nsRefreshDriver. r?smaug
We just need information whether there is still an observer or not in most
cases. The only case we need to know the count is in an assertion in the
dtor of nsRefreshDriver. In the dtor we are checking there remains no
observers other than early runners.
Note that the order in HasObserver() was adjusted to reflect that we check
boolean flag first (mViewManagerFlushIsPending) and subsequently check observer
which is likey happen to. mFrameRequestCallbackDocs should have checked prior
to mResizeEventFlushObservers though.
MozReview-Commit-ID: E1qplusqw1Y
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1434,24 +1434,45 @@ nsRefreshDriver::ObserverCount() const
sum += mPendingEvents.Length();
sum += mFrameRequestCallbackDocs.Length();
sum += mThrottledFrameRequestCallbackDocs.Length();
sum += mViewManagerFlushIsPending;
sum += mEarlyRunners.Length();
return sum;
}
-uint32_t
-nsRefreshDriver::ImageRequestCount() const
+bool
+nsRefreshDriver::HasObservers() const
{
- uint32_t count = 0;
+ for (uint32_t i = 0; i < ArrayLength(mObservers); ++i) {
+ if (!mObservers[i].IsEmpty()) {
+ return true;
+ }
+ }
+
+ return mViewManagerFlushIsPending ||
+ !mStyleFlushObservers.IsEmpty() ||
+ !mLayoutFlushObservers.IsEmpty() ||
+ !mResizeEventFlushObservers.IsEmpty() ||
+ !mPendingEvents.IsEmpty() ||
+ !mFrameRequestCallbackDocs.IsEmpty() ||
+ !mThrottledFrameRequestCallbackDocs.IsEmpty() ||
+ !mEarlyRunners.IsEmpty();
+}
+
+bool
+nsRefreshDriver::HasImageRequests() const
+{
for (auto iter = mStartTable.ConstIter(); !iter.Done(); iter.Next()) {
- count += iter.UserData()->mEntries.Count();
+ if (!iter.UserData()->mEntries.IsEmpty()) {
+ return true;
+ }
}
- return count + mRequests.Count();
+
+ return !mRequests.IsEmpty();
}
nsRefreshDriver::ObserverArray&
nsRefreshDriver::ArrayFor(FlushType aFlushType)
{
switch (aFlushType) {
case FlushType::Event:
return mObservers[0];
@@ -1813,17 +1834,18 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
if (mRootRefresh) {
mRootRefresh->RemoveRefreshObserver(this, FlushType::Style);
mRootRefresh = nullptr;
}
mSkippedPaints = false;
mWarningThreshold = 1;
nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
- if (!presShell || (ObserverCount() == 0 && ImageRequestCount() == 0 && mScrollEvents.Length() == 0)) {
+ if (!presShell ||
+ (!HasObservers() && !HasImageRequests() && mScrollEvents.IsEmpty())) {
// Things are being destroyed, or we no longer have any observers.
// We don't want to stop the timer when observers are initially
// removed, because sometimes observers can be added and removed
// often depending on what other things are going on and in that
// situation we don't want to thrash our timer. So instead we
// wait until we get a Notify() call when we have no observers
// before stopping the timer.
StopTimer();
@@ -2135,17 +2157,17 @@ nsRefreshDriver::Thaw()
{
NS_ASSERTION(mFreezeCount > 0, "Thaw() called on an unfrozen refresh driver");
if (mFreezeCount > 0) {
mFreezeCount--;
}
if (mFreezeCount == 0) {
- if (ObserverCount() || ImageRequestCount()) {
+ if (HasObservers() || HasImageRequests()) {
// FIXME: This isn't quite right, since our EnsureTimerStarted call
// updates our mMostRecentRefresh, but the DoRefresh call won't run
// and notify our observers until we get back to the event loop.
// Thus MostRecentRefresh() will lie between now and the DoRefresh.
RefPtr<nsRunnableMethod<nsRefreshDriver>> event = NewRunnableMethod(
"nsRefreshDriver::DoRefresh", this, &nsRefreshDriver::DoRefresh);
nsPresContext* pc = GetPresContext();
if (pc) {
@@ -2160,17 +2182,17 @@ nsRefreshDriver::Thaw()
}
void
nsRefreshDriver::FinishedWaitingForTransaction()
{
mWaitingForTransaction = false;
if (mSkippedPaints &&
!IsInRefresh() &&
- (ObserverCount() || ImageRequestCount())) {
+ (HasObservers() || HasImageRequests())) {
AUTO_PROFILER_TRACING("Paint", "RefreshDriverTick");
DoRefresh();
}
mSkippedPaints = false;
mWarningThreshold = 1;
}
uint64_t
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -392,18 +392,19 @@ private:
eNone = 0,
eForceAdjustTimer = 1 << 0,
eAllowTimeToGoBackwards = 1 << 1,
eNeverAdjustTimer = 1 << 2,
};
void EnsureTimerStarted(EnsureTimerStartedFlags aFlags = eNone);
void StopTimer();
+ bool HasObservers() const;
uint32_t ObserverCount() const;
- uint32_t ImageRequestCount() const;
+ bool HasImageRequests() const;
ObserverArray& ArrayFor(mozilla::FlushType aFlushType);
// Trigger a refresh immediately, if haven't been disconnected or frozen.
void DoRefresh();
double GetRefreshTimerInterval() const;
double GetRegularTimerInterval(bool *outIsDefault = nullptr) const;
static double GetThrottledTimerInterval();