From a59888777c1f18a303c2fa1008d01745ba956c7b Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 9 Apr 2015 22:59:10 -0400 Subject: [PATCH] Backed out changeset 3366d180e8ee (bug 1145439) for test_scroll_event_ordering.html failures. --- dom/base/nsDocument.cpp | 36 ------- dom/base/nsIDocument.h | 7 -- layout/base/nsRefreshDriver.cpp | 167 +++++++++----------------------- layout/base/nsRefreshDriver.h | 11 +-- layout/generic/nsIFrame.h | 20 +--- 5 files changed, 52 insertions(+), 189 deletions(-) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index c1202f60d80f..2b6c1cac4dd5 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -3921,42 +3921,6 @@ nsIDocument::TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks) mFrameRequestCallbacks.Clear(); } -bool -nsIDocument::ShouldThrottleFrameRequests() -{ - if (!mIsShowing) { - // We're not showing (probably in a background tab or the bf cache). - return true; - } - - if (!mPresShell) { - return false; // Can't do anything smarter. - } - - nsIFrame* frame = mPresShell->GetRootFrame(); - if (!frame) { - return false; // Can't do anything smarter. - } - - nsIFrame* displayRootFrame = nsLayoutUtils::GetDisplayRootFrame(frame); - if (!displayRootFrame) { - return false; // Can't do anything smarter. - } - - if (!displayRootFrame->DidPaintPresShell(mPresShell)) { - // We didn't get painted during the last paint, so we're not visible. - // Throttle. Note that because we have to paint this document at least - // once to unthrottle it, we will drop one requestAnimationFrame frame - // when a document that previously wasn't visible scrolls into view. This - // is acceptable since it would happen outside the viewport on APZ - // platforms and is unlikely to be human-perceivable on non-APZ platforms. - return true; - } - - // We got painted during the last paint, so run at full speed. - return false; -} - PLDHashOperator RequestDiscardEnumerator(imgIRequest* aKey, uint32_t aData, void* userArg) diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index 389c17b2a2d6..474c5a40552b 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -2103,13 +2103,6 @@ public: */ void TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks); - /** - * @return true if this document's frame request callbacks should be - * throttled. We throttle requestAnimationFrame for documents which aren't - * visible (e.g. scrolled out of the viewport). - */ - bool ShouldThrottleFrameRequests(); - // This returns true when the document tree is being teared down. bool InUnlinkOrDeletion() { return mInUnlinkOrDeletion; } diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 888ae933792d..a43b4d7e4e4f 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -966,8 +966,8 @@ nsRefreshDriver::GetRegularTimerInterval(bool *outIsDefault) const return 1000.0 / rate; } -/* static */ double -nsRefreshDriver::GetThrottledTimerInterval() +double +nsRefreshDriver::GetThrottledTimerInterval() const { int32_t rate = Preferences::GetInt("layout.throttled_frame_rate", -1); if (rate <= 0) { @@ -1020,8 +1020,6 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext) mPendingTransaction(0), mCompletedTransaction(0), mFreezeCount(0), - mThrottledFrameRequestInterval(TimeDuration::FromMilliseconds( - GetThrottledTimerInterval())), mThrottled(false), mTestControllingRefreshes(false), mViewManagerFlushIsPending(false), @@ -1033,7 +1031,6 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext) mMostRecentRefreshEpochTime = JS_Now(); mMostRecentRefresh = TimeStamp::Now(); mMostRecentTick = mMostRecentRefresh; - mNextThrottledFrameRequestTick = mMostRecentTick; } nsRefreshDriver::~nsRefreshDriver() @@ -1257,15 +1254,13 @@ DisableHighPrecisionTimersCallback(nsITimer *aTimer, void *aClosure) void nsRefreshDriver::ConfigureHighPrecision() { - bool haveUnthrottledFrameRequestCallbacks = - mFrameRequestCallbackDocs.Length() > 0; + bool haveFrameRequestCallbacks = mFrameRequestCallbackDocs.Length() > 0; // if the only change that's needed is that we need high precision, // then just set that - if (!mThrottled && !mRequestedHighPrecision && - haveUnthrottledFrameRequestCallbacks) { + if (!mThrottled && !mRequestedHighPrecision && haveFrameRequestCallbacks) { SetHighPrecisionTimersEnabled(true); - } else if (mRequestedHighPrecision && !haveUnthrottledFrameRequestCallbacks) { + } else if (mRequestedHighPrecision && !haveFrameRequestCallbacks) { SetHighPrecisionTimersEnabled(false); } } @@ -1333,7 +1328,6 @@ nsRefreshDriver::ObserverCount() const sum += mStyleFlushObservers.Length(); sum += mLayoutFlushObservers.Length(); sum += mFrameRequestCallbackDocs.Length(); - sum += mThrottledFrameRequestCallbackDocs.Length(); sum += mViewManagerFlushIsPending; return sum; } @@ -1459,105 +1453,6 @@ static void GetProfileTimelineSubDocShells(nsDocShell* aRootDocShell, }; } -static void -TakeFrameRequestCallbacksFrom(nsIDocument* aDocument, - nsTArray& aTarget) -{ - aTarget.AppendElement(aDocument); - aDocument->TakeFrameRequestCallbacks(aTarget.LastElement().mCallbacks); -} - -void -nsRefreshDriver::RunFrameRequestCallbacks(int64_t aNowEpoch, TimeStamp aNowTime) -{ - // Grab all of our frame request callbacks up front. - nsTArray - frameRequestCallbacks(mFrameRequestCallbackDocs.Length() + - mThrottledFrameRequestCallbackDocs.Length()); - - // First, grab throttled frame request callbacks. - { - nsTArray docsToRemove; - - // We always tick throttled frame requests if the entire refresh driver is - // throttled, because in that situation throttled frame requests tick at the - // same frequency as non-throttled frame requests. - bool tickThrottledFrameRequests = mThrottled; - - if (!tickThrottledFrameRequests && - aNowTime >= mNextThrottledFrameRequestTick) { - mNextThrottledFrameRequestTick = aNowTime + mThrottledFrameRequestInterval; - tickThrottledFrameRequests = true; - } - - for (nsIDocument* doc : mThrottledFrameRequestCallbackDocs) { - if (tickThrottledFrameRequests) { - // We're ticking throttled documents, so grab this document's requests. - // We don't bother appending to docsToRemove because we're going to - // clear mThrottledFrameRequestCallbackDocs anyway. - TakeFrameRequestCallbacksFrom(doc, frameRequestCallbacks); - } else if (!doc->ShouldThrottleFrameRequests()) { - // This document is no longer throttled, so grab its requests even - // though we're not ticking throttled frame requests right now. If - // this is the first unthrottled document with frame requests, we'll - // enter high precision mode the next time the callback is scheduled. - TakeFrameRequestCallbacksFrom(doc, frameRequestCallbacks); - docsToRemove.AppendElement(doc); - } - } - - // Remove all the documents we're ticking from - // mThrottledFrameRequestCallbackDocs so they can be readded as needed. - if (tickThrottledFrameRequests) { - mThrottledFrameRequestCallbackDocs.Clear(); - } else { - // XXX(seth): We're using this approach to avoid concurrent modification - // of mThrottledFrameRequestCallbackDocs. docsToRemove usually has either - // zero elements or a very small number, so this should be OK in practice. - for (nsIDocument* doc : docsToRemove) { - mThrottledFrameRequestCallbackDocs.RemoveElement(doc); - } - } - } - - // Now grab unthrottled frame request callbacks. - for (nsIDocument* doc : mFrameRequestCallbackDocs) { - TakeFrameRequestCallbacksFrom(doc, frameRequestCallbacks); - } - - // Reset mFrameRequestCallbackDocs so they can be readded as needed. - mFrameRequestCallbackDocs.Clear(); - - profiler_tracing("Paint", "Scripts", TRACING_INTERVAL_START); - int64_t eventTime = aNowEpoch / PR_USEC_PER_MSEC; - for (uint32_t i = 0; i < frameRequestCallbacks.Length(); ++i) { - const DocumentFrameCallbacks& docCallbacks = frameRequestCallbacks[i]; - // XXXbz Bug 863140: GetInnerWindow can return the outer - // window in some cases. - nsPIDOMWindow* innerWindow = docCallbacks.mDocument->GetInnerWindow(); - DOMHighResTimeStamp timeStamp = 0; - if (innerWindow && innerWindow->IsInnerWindow()) { - nsPerformance* perf = innerWindow->GetPerformance(); - if (perf) { - timeStamp = perf->GetDOMTiming()->TimeStampToDOMHighRes(aNowTime); - } - // else window is partially torn down already - } - for (uint32_t j = 0; j < docCallbacks.mCallbacks.Length(); ++j) { - const nsIDocument::FrameRequestCallbackHolder& holder = - docCallbacks.mCallbacks[j]; - nsAutoMicroTask mt; - if (holder.HasWebIDLCallback()) { - ErrorResult ignored; - holder.GetWebIDLCallback()->Call(timeStamp, ignored); - } else { - holder.GetXPCOMCallback()->Sample(eventTime); - } - } - } - profiler_tracing("Paint", "Scripts", TRACING_INTERVAL_END); -} - void nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) { @@ -1648,7 +1543,46 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) if (i == 0) { // This is the Flush_Style case. - RunFrameRequestCallbacks(aNowEpoch, aNowTime); + // Grab all of our frame request callbacks up front. + nsTArray + frameRequestCallbacks(mFrameRequestCallbackDocs.Length()); + for (uint32_t i = 0; i < mFrameRequestCallbackDocs.Length(); ++i) { + frameRequestCallbacks.AppendElement(mFrameRequestCallbackDocs[i]); + mFrameRequestCallbackDocs[i]-> + TakeFrameRequestCallbacks(frameRequestCallbacks.LastElement().mCallbacks); + } + // OK, now reset mFrameRequestCallbackDocs so they can be + // readded as needed. + mFrameRequestCallbackDocs.Clear(); + + profiler_tracing("Paint", "Scripts", TRACING_INTERVAL_START); + int64_t eventTime = aNowEpoch / PR_USEC_PER_MSEC; + for (uint32_t i = 0; i < frameRequestCallbacks.Length(); ++i) { + const DocumentFrameCallbacks& docCallbacks = frameRequestCallbacks[i]; + // XXXbz Bug 863140: GetInnerWindow can return the outer + // window in some cases. + nsPIDOMWindow* innerWindow = docCallbacks.mDocument->GetInnerWindow(); + DOMHighResTimeStamp timeStamp = 0; + if (innerWindow && innerWindow->IsInnerWindow()) { + nsPerformance* perf = innerWindow->GetPerformance(); + if (perf) { + timeStamp = perf->GetDOMTiming()->TimeStampToDOMHighRes(aNowTime); + } + // else window is partially torn down already + } + for (uint32_t j = 0; j < docCallbacks.mCallbacks.Length(); ++j) { + const nsIDocument::FrameRequestCallbackHolder& holder = + docCallbacks.mCallbacks[j]; + nsAutoMicroTask mt; + if (holder.HasWebIDLCallback()) { + ErrorResult ignored; + holder.GetWebIDLCallback()->Call(timeStamp, ignored); + } else { + holder.GetXPCOMCallback()->Sample(eventTime); + } + } + } + profiler_tracing("Paint", "Scripts", TRACING_INTERVAL_END); if (mPresContext && mPresContext->GetPresShell()) { bool tracingStyleFlush = false; @@ -2091,15 +2025,9 @@ void nsRefreshDriver::ScheduleFrameRequestCallbacks(nsIDocument* aDocument) { NS_ASSERTION(mFrameRequestCallbackDocs.IndexOf(aDocument) == - mFrameRequestCallbackDocs.NoIndex && - mThrottledFrameRequestCallbackDocs.IndexOf(aDocument) == - mThrottledFrameRequestCallbackDocs.NoIndex, + mFrameRequestCallbackDocs.NoIndex, "Don't schedule the same document multiple times"); - if (aDocument->ShouldThrottleFrameRequests()) { - mThrottledFrameRequestCallbackDocs.AppendElement(aDocument); - } else { - mFrameRequestCallbackDocs.AppendElement(aDocument); - } + mFrameRequestCallbackDocs.AppendElement(aDocument); // make sure that the timer is running ConfigureHighPrecision(); @@ -2110,7 +2038,6 @@ void nsRefreshDriver::RevokeFrameRequestCallbacks(nsIDocument* aDocument) { mFrameRequestCallbackDocs.RemoveElement(aDocument); - mThrottledFrameRequestCallbackDocs.RemoveElement(aDocument); ConfigureHighPrecision(); // No need to worry about restarting our timer in slack mode if it's already // running; that will happen automatically when it fires. diff --git a/layout/base/nsRefreshDriver.h b/layout/base/nsRefreshDriver.h index 9bc464b5ea34..e001e7fa381e 100644 --- a/layout/base/nsRefreshDriver.h +++ b/layout/base/nsRefreshDriver.h @@ -308,8 +308,6 @@ private: }; typedef nsClassHashtable ImageStartTable; - void RunFrameRequestCallbacks(int64_t aNowEpoch, mozilla::TimeStamp aNowTime); - void Tick(int64_t aNowEpoch, mozilla::TimeStamp aNowTime); enum EnsureTimerStartedFlags { @@ -338,7 +336,7 @@ private: double GetRefreshTimerInterval() const; double GetRegularTimerInterval(bool *outIsDefault = nullptr) const; - static double GetThrottledTimerInterval(); + double GetThrottledTimerInterval() const; bool HaveFrameRequestCallbacks() const { return mFrameRequestCallbackDocs.Length() != 0; @@ -363,11 +361,6 @@ private: uint64_t mCompletedTransaction; uint32_t mFreezeCount; - - // How long we wait between ticks for throttled (which generally means - // non-visible) documents registered with a non-throttled refresh driver. - const mozilla::TimeDuration mThrottledFrameRequestInterval; - bool mThrottled; bool mTestControllingRefreshes; bool mViewManagerFlushIsPending; @@ -386,7 +379,6 @@ private: mozilla::TimeStamp mMostRecentRefresh; mozilla::TimeStamp mMostRecentTick; mozilla::TimeStamp mTickStart; - mozilla::TimeStamp mNextThrottledFrameRequestTick; // separate arrays for each flush type we support ObserverArray mObservers[3]; @@ -398,7 +390,6 @@ private: nsAutoTArray mPresShellsToInvalidateIfHidden; // nsTArray on purpose, because we want to be able to swap. nsTArray mFrameRequestCallbackDocs; - nsTArray mThrottledFrameRequestCallbackDocs; nsTArray mPostRefreshObservers; // Helper struct for processing image requests diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 6b2b9747db08..a3453427aa6c 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -2808,28 +2808,16 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty())) * the last repaint. */ void UpdatePaintCountForPaintedPresShells() { - for (nsWeakPtr& item : *PaintedPresShellList()) { - nsCOMPtr shell = do_QueryReferent(item); + nsTArray * list = PaintedPresShellList(); + for (int i = 0, l = list->Length(); i < l; i++) { + nsCOMPtr shell = do_QueryReferent(list->ElementAt(i)); + if (shell) { shell->IncrementPaintCount(); } } } - /** - * @return true if we painted @aShell during the last repaint. - */ - bool DidPaintPresShell(nsIPresShell* aShell) - { - for (nsWeakPtr& item : *PaintedPresShellList()) { - nsCOMPtr shell = do_QueryReferent(item); - if (shell == aShell) { - return true; - } - } - return false; - } - /** * Accessors for the absolute containing block. */