Bug 1350930 - Move profiler markers for reflow and style flushes from the refresh driver into the PresShell. r?bzbarsky draft
authorMarkus Stange <mstange@themasta.com>
Wed, 15 Nov 2017 16:10:32 -0500
changeset 698482 bf67311197dfc59b799e3e2ef1d33d7b1051635a
parent 697862 76e5a7a35e8ea445911ff53b4508082a96e8f041
child 740393 2f787ed93cc7dcb5333329200154125af39bccea
push id89305
push userbmo:mstange@themasta.com
push dateWed, 15 Nov 2017 21:13:13 +0000
reviewersbzbarsky
bugs1350930
milestone59.0a1
Bug 1350930 - Move profiler markers for reflow and style flushes from the refresh driver into the PresShell. r?bzbarsky MozReview-Commit-ID: FQs2zsIU2zO
layout/base/PresShell.cpp
layout/base/nsIPresShell.h
layout/base/nsIPresShellInlines.h
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -4205,30 +4205,41 @@ PresShell::DoFlushPendingNotifications(m
     // events.  At the same time, we still need up-to-date style data.
     // In particular, reflow depends on style being completely up to
     // date.  If it's not, then style context reparenting, which can
     // happen during reflow, might suddenly pick up the new rules and
     // we'll end up with frames whose style doesn't match the frame
     // type.
     if (!mIsDestroying) {
       nsAutoScriptBlocker scriptBlocker;
+#ifdef MOZ_GECKO_PROFILER
+      AutoProfilerTracing tracingStyleFlush("Paint", "Styles",
+                                            Move(mStyleCause));
+      mStyleCause = nullptr;
+#endif
+
       mPresContext->RestyleManager()->ProcessPendingRestyles();
     }
 
     didStyleFlush = true;
 
 
     // There might be more pending constructors now, but we're not going to
     // worry about them.  They can't be triggered during reflow, so we should
     // be good.
 
     if (flushType >= (SuppressInterruptibleReflows()
                         ? FlushType::Layout
                         : FlushType::InterruptibleLayout) &&
         !mIsDestroying) {
+#ifdef MOZ_GECKO_PROFILER
+      AutoProfilerTracing tracingLayoutFlush("Paint", "Reflow",
+                                              Move(mReflowCause));
+      mReflowCause = nullptr;
+#endif
       didLayoutFlush = true;
       mFrameConstructor->RecalcQuotesAndCounters();
       viewManager->FlushDelayedResize(true);
       if (ProcessReflowCommands(flushType < FlushType::Layout) &&
           mContentToScrollTo) {
         // We didn't get interrupted.  Go ahead and scroll to our content
         DoScrollContentIntoView();
         if (mContentToScrollTo) {
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -12,16 +12,17 @@
 #include "mozilla/ArenaObjectID.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/FlushType.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/WeakPtr.h"
+#include "GeckoProfiler.h"
 #include "gfxPoint.h"
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
 #include "nsISupports.h"
 #include "nsIContent.h"
 #include "nsISelectionController.h"
 #include "nsQueryFrame.h"
 #include "nsStringFwd.h"
@@ -1692,16 +1693,24 @@ protected:
   nsSize                    mScrollPositionClampingScrollPortSize;
 
   // A list of stack weak frames. This is a pointer to the last item in the list.
   AutoWeakFrame*            mAutoWeakFrames;
 
   // A hash table of heap allocated weak frames.
   nsTHashtable<nsPtrHashKey<WeakFrame>> mWeakFrames;
 
+#ifdef MOZ_GECKO_PROFILER
+  // These two fields capture call stacks of any changes that require a restyle
+  // or a reflow. Only the first change per restyle / reflow is recorded (the
+  // one that caused a call to SetNeedStyleFlush() / SetNeedLayoutFlush()).
+  UniqueProfilerBacktrace mStyleCause;
+  UniqueProfilerBacktrace mReflowCause;
+#endif
+
   // Most recent canvas background color.
   nscolor                   mCanvasBackgroundColor;
 
   // Used to force allocation and rendering of proportionally more or
   // less pixels in both dimensions.
   mozilla::Maybe<float>     mResolution;
 
   int16_t                   mSelectionFlags;
--- a/layout/base/nsIPresShellInlines.h
+++ b/layout/base/nsIPresShellInlines.h
@@ -13,27 +13,39 @@ void
 nsIPresShell::SetNeedLayoutFlush()
 {
   mNeedLayoutFlush = true;
   if (nsIDocument* doc = mDocument->GetDisplayDocument()) {
     if (nsIPresShell* shell = doc->GetShell()) {
       shell->mNeedLayoutFlush = true;
     }
   }
+
+#ifdef MOZ_GECKO_PROFILER
+  if (!mReflowCause) {
+    mReflowCause = profiler_get_backtrace();
+  }
+#endif
 }
 
 void
 nsIPresShell::SetNeedStyleFlush()
 {
   mNeedStyleFlush = true;
   if (nsIDocument* doc = mDocument->GetDisplayDocument()) {
     if (nsIPresShell* shell = doc->GetShell()) {
       shell->mNeedStyleFlush = true;
     }
   }
+
+#ifdef MOZ_GECKO_PROFILER
+  if (!mStyleCause) {
+    mStyleCause = profiler_get_backtrace();
+  }
+#endif
 }
 
 void
 nsIPresShell::EnsureStyleFlush()
 {
   SetNeedStyleFlush();
   ObserveStyleFlushes();
 }
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1852,71 +1852,51 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
       // This is the FlushType::Style case.
 
       DispatchAnimationEvents();
       DispatchPendingEvents();
       RunFrameRequestCallbacks(aNowTime);
       DispatchScrollEvents();
 
       if (mPresContext && mPresContext->GetPresShell()) {
-#ifdef MOZ_GECKO_PROFILER
-        Maybe<AutoProfilerTracing> tracingStyleFlush;
-#endif
         AutoTArray<nsIPresShell*, 16> observers;
         observers.AppendElements(mStyleFlushObservers);
         for (uint32_t j = observers.Length();
              j && mPresContext && mPresContext->GetPresShell(); --j) {
           // Make sure to not process observers which might have been removed
           // during previous iterations.
           nsIPresShell* shell = observers[j - 1];
           if (!mStyleFlushObservers.RemoveElement(shell))
             continue;
 
-#ifdef MOZ_GECKO_PROFILER
-          if (!tracingStyleFlush) {
-            tracingStyleFlush.emplace("Paint", "Styles", Move(mStyleCause));
-            mStyleCause = nullptr;
-          }
-#endif
-
           nsCOMPtr<nsIPresShell> shellKungFuDeathGrip(shell);
           shell->mObservingStyleFlushes = false;
           shell->FlushPendingNotifications(ChangesToFlush(FlushType::Style, false));
           // Inform the FontFaceSet that we ticked, so that it can resolve its
           // ready promise if it needs to (though it might still be waiting on
           // a layout flush).
           nsPresContext* presContext = shell->GetPresContext();
           if (presContext) {
             presContext->NotifyFontFaceSetOnRefresh();
           }
           mNeedToRecomputeVisibility = true;
         }
       }
     } else if  (i == 2) {
       // This is the FlushType::Layout case.
-#ifdef MOZ_GECKO_PROFILER
-      Maybe<AutoProfilerTracing> tracingLayoutFlush;
-#endif
       AutoTArray<nsIPresShell*, 16> observers;
       observers.AppendElements(mLayoutFlushObservers);
       for (uint32_t j = observers.Length();
            j && mPresContext && mPresContext->GetPresShell(); --j) {
         // Make sure to not process observers which might have been removed
         // during previous iterations.
         nsIPresShell* shell = observers[j - 1];
         if (!mLayoutFlushObservers.RemoveElement(shell))
           continue;
 
-#ifdef MOZ_GECKO_PROFILER
-        if (!tracingLayoutFlush) {
-          tracingLayoutFlush.emplace("Paint", "Reflow", Move(mReflowCause));
-          mReflowCause = nullptr;
-        }
-#endif
-
         nsCOMPtr<nsIPresShell> shellKungFuDeathGrip(shell);
         shell->mObservingLayoutFlushes = false;
         shell->mWasLastReflowInterrupted = false;
         FlushType flushType = HasPendingAnimations(shell)
                                ? FlushType::Layout
                                : FlushType::InterruptibleLayout;
         shell->FlushPendingNotifications(ChangesToFlush(flushType, false));
         // Inform the FontFaceSet that we ticked, so that it can resolve its
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -19,17 +19,16 @@
 #include "nsTObserverArray.h"
 #include "nsTArray.h"
 #include "nsTHashtable.h"
 #include "nsTObserverArray.h"
 #include "nsClassHashtable.h"
 #include "nsHashKeys.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
-#include "GeckoProfiler.h"
 #include "mozilla/layers/TransactionIdAllocator.h"
 
 class nsPresContext;
 class nsIPresShell;
 class nsIDocument;
 class imgIRequest;
 class nsIDOMEvent;
 class nsINode;
@@ -155,45 +154,27 @@ public:
   void RemoveImageRequest(imgIRequest* aRequest);
 
   /**
    * Add / remove presshells that we should flush style and layout on
    */
   bool AddStyleFlushObserver(nsIPresShell* aShell) {
     NS_ASSERTION(!mStyleFlushObservers.Contains(aShell),
                  "Double-adding style flush observer");
-    // We only get the cause for the first observer each frame because capturing
-    // a stack is expensive. This is still useful if (1) you're trying to remove
-    // all flushes for a particial frame or (2) the costly flush is triggered
-    // near the call site where the first observer is triggered.
-#ifdef MOZ_GECKO_PROFILER
-    if (!mStyleCause) {
-      mStyleCause = profiler_get_backtrace();
-    }
-#endif
     bool appended = mStyleFlushObservers.AppendElement(aShell) != nullptr;
     EnsureTimerStarted();
 
     return appended;
   }
   void RemoveStyleFlushObserver(nsIPresShell* aShell) {
     mStyleFlushObservers.RemoveElement(aShell);
   }
   bool AddLayoutFlushObserver(nsIPresShell* aShell) {
     NS_ASSERTION(!IsLayoutFlushObserver(aShell),
                  "Double-adding layout flush observer");
-#ifdef MOZ_GECKO_PROFILER
-    // We only get the cause for the first observer each frame because capturing
-    // a stack is expensive. This is still useful if (1) you're trying to remove
-    // all flushes for a particial frame or (2) the costly flush is triggered
-    // near the call site where the first observer is triggered.
-    if (!mReflowCause) {
-      mReflowCause = profiler_get_backtrace();
-    }
-#endif
     bool appended = mLayoutFlushObservers.AppendElement(aShell) != nullptr;
     EnsureTimerStarted();
     return appended;
   }
   void RemoveLayoutFlushObserver(nsIPresShell* aShell) {
     mLayoutFlushObservers.RemoveElement(aShell);
   }
   bool IsLayoutFlushObserver(nsIPresShell* aShell) {
@@ -415,21 +396,16 @@ private:
     return mFrameRequestCallbackDocs.Length() != 0;
   }
 
   void FinishedWaitingForTransaction();
 
   mozilla::RefreshDriverTimer* ChooseTimer() const;
   mozilla::RefreshDriverTimer* mActiveTimer;
 
-#ifdef MOZ_GECKO_PROFILER
-  UniqueProfilerBacktrace mReflowCause;
-  UniqueProfilerBacktrace mStyleCause;
-#endif
-
   // nsPresContext passed in constructor and unset in Disconnect.
   mozilla::WeakPtr<nsPresContext> mPresContext;
 
   RefPtr<nsRefreshDriver> mRootRefresh;
 
   // The most recently allocated transaction id.
   uint64_t mPendingTransaction;
   // The most recently completed transaction id.