Bug 1339891 part 2. Make FlushPendingNotifications on a presshell quickly no-op if there is nothing to flush. r=heycam
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 17 Feb 2017 13:38:44 -0500
changeset 372800 44d588184435c92321e7a0d207d57dd2012c1e81
parent 372799 32242abfde5d17bcc1c7c82df0d395c1cc64f955
child 372801 323bcdc5575f0a0fc2a12d1cbe2db5ce91a4135b
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1339891
milestone54.0a1
Bug 1339891 part 2. Make FlushPendingNotifications on a presshell quickly no-op if there is nothing to flush. r=heycam
dom/base/nsDocument.cpp
layout/base/PresShell.cpp
layout/base/PresShell.h
layout/base/nsIPresShell.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -7962,23 +7962,18 @@ nsDocument::FlushPendingNotifications(Fl
   // correct size to determine the correct style.
   if (mParentDocument && IsSafeToFlush()) {
     FlushType parentType = aType;
     if (aType >= FlushType::Style)
       parentType = std::max(FlushType::Layout, aType);
     mParentDocument->FlushPendingNotifications(parentType);
   }
 
-  // Call nsIPresShell::NeedFlush (inline, non-virtual) to check whether we
-  // really need to flush the shell (virtual, and needs a strong reference).
   if (nsIPresShell* shell = GetShell()) {
-    if (shell->NeedFlush(aType)) {
-      nsCOMPtr<nsIPresShell> presShell = shell;
-      presShell->FlushPendingNotifications(aType);
-    }
+    shell->FlushPendingNotifications(aType);
   }
 }
 
 static bool
 Copy(nsIDocument* aDocument, void* aData)
 {
   nsTArray<nsCOMPtr<nsIDocument> >* resources =
     static_cast<nsTArray<nsCOMPtr<nsIDocument> >* >(aData);
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -4060,36 +4060,38 @@ PresShell::IsSafeToFlush() const
     }
   }
 
   return isSafeToFlush;
 }
 
 
 void
-PresShell::FlushPendingNotifications(FlushType aType)
+PresShell::DoFlushPendingNotifications(FlushType aType)
 {
   // by default, flush animations if aType >= FlushType::Style
   mozilla::ChangesToFlush flush(aType, aType >= FlushType::Style);
   FlushPendingNotifications(flush);
 }
 
 void
-PresShell::FlushPendingNotifications(mozilla::ChangesToFlush aFlush)
+PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush)
 {
   // Per our API contract, hold a strong ref to ourselves until we return.
   nsCOMPtr<nsIPresShell> kungFuDeathGrip = this;
 
   /**
    * VERY IMPORTANT: If you add some sort of new flushing to this
    * method, make sure to add the relevant SetNeedLayoutFlush or
    * SetNeedStyleFlush calls on the shell.
    */
   FlushType flushType = aFlush.mFlushType;
 
+  MOZ_ASSERT(NeedFlush(flushType), "Why did we get called?");
+
 #ifdef MOZ_GECKO_PROFILER
   static const EnumeratedArray<FlushType,
                                FlushType::Count,
                                const char*> flushTypeNames = {
     "",
     "Content",
     "ContentAndNotify",
     "Style",
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -121,18 +121,18 @@ public:
   virtual nsIFrame* GetPlaceholderFrameFor(nsIFrame* aFrame) const override;
   virtual void FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
                                 nsFrameState aBitToAdd,
                                 ReflowRootHandling aRootHandling =
                                   eInferFromBitToAdd) override;
   virtual void FrameNeedsToContinueReflow(nsIFrame *aFrame) override;
   virtual void CancelAllPendingReflows() override;
   virtual bool IsSafeToFlush() const override;
-  virtual void FlushPendingNotifications(mozilla::FlushType aType) override;
-  virtual void FlushPendingNotifications(mozilla::ChangesToFlush aType) override;
+  virtual void DoFlushPendingNotifications(mozilla::FlushType aType) override;
+  virtual void DoFlushPendingNotifications(mozilla::ChangesToFlush aType) override;
   virtual void DestroyFramesFor(nsIContent*  aContent,
                                 nsIContent** aDestroyedFramesFor) override;
   virtual void CreateFramesFor(nsIContent* aContent) override;
 
   /**
    * Recreates the frames for a node
    */
   virtual nsresult RecreateFramesFor(nsIContent* aContent) override;
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -583,19 +583,43 @@ public:
    * This method can execute script, which can destroy this presshell object
    * unless someone is holding a reference to it on the stack.  The presshell
    * itself will ensure it lives up until the method returns, but callers who
    * plan to use the presshell after this call should hold a strong ref
    * themselves!
    *
    * @param aType the type of notifications to flush
    */
-  virtual void FlushPendingNotifications(mozilla::FlushType aType) = 0;
-  virtual void FlushPendingNotifications(mozilla::ChangesToFlush aType) = 0;
+public:
+  void FlushPendingNotifications(mozilla::FlushType aType)
+  {
+    if (!NeedFlush(aType)) {
+      return;
+    }
+
+    DoFlushPendingNotifications(aType);
+  }
 
+  void FlushPendingNotifications(mozilla::ChangesToFlush aType)
+  {
+    if (!NeedFlush(aType.mFlushType)) {
+      return;
+    }
+
+    DoFlushPendingNotifications(aType);
+  }
+
+protected:
+  /**
+   * Implementation methods for FlushPendingNotifications.
+   */
+  virtual void DoFlushPendingNotifications(mozilla::FlushType aType) = 0;
+  virtual void DoFlushPendingNotifications(mozilla::ChangesToFlush aType) = 0;
+
+public:
   /**
    * Whether we might need a flush for the given flush type.  If this
    * function returns false, we definitely don't need to flush.
    *
    * @param aFlushType The flush type to check.  This must be
    *   >= FlushType::Style.  This also returns true if a throttled
    *   animation flush is required.
    */