Bug 1466024 - Cleanup nsDisplaySubDocument display items when we swap the subdoc into a different outer document. r=miko
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 01 Jun 2018 17:23:55 +1200
changeset 422895 4432fb67de2d1e2658a36fed800979c1968c1f94
parent 422894 693ff336db30ae54237b1b6c64ac23b4e3d0b9af
child 422933 257c191e7903523a1132e04460a0b2460d950809
child 422934 fce6b794a239a5341e6b8da4bd53a970626e1120
push id34157
push userrgurzau@mozilla.com
push dateTue, 19 Jun 2018 10:01:19 +0000
treeherdermozilla-central@4432fb67de2d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmiko
bugs1466024
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1466024 - Cleanup nsDisplaySubDocument display items when we swap the subdoc into a different outer document. r=miko MozReview-Commit-ID: E4NKiIdXZsY
layout/base/nsLayoutUtils.cpp
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsSubDocumentFrame.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3818,17 +3818,18 @@ nsLayoutUtils::PaintFrame(gfxContext* aR
     flags |= nsDisplayList::PAINT_EXISTING_TRANSACTION;
   }
   if (aFlags & PaintFrameFlags::PAINT_NO_COMPOSITE) {
     flags |= nsDisplayList::PAINT_NO_COMPOSITE;
   }
   if (aFlags & PaintFrameFlags::PAINT_COMPRESSED) {
     flags |= nsDisplayList::PAINT_COMPRESSED;
   }
-  if (updateState == PartialUpdateResult::NoChange) {
+  if (updateState == PartialUpdateResult::NoChange &&
+      !aRenderingContext) {
     flags |= nsDisplayList::PAINT_IDENTICAL_DISPLAY_LIST;
   }
 
   TimeStamp paintStart = TimeStamp::Now();
   RefPtr<LayerManager> layerManager
     = list.PaintRoot(&builder, aRenderingContext, flags);
   Telemetry::AccumulateTimeDelta(Telemetry::PAINT_RASTERIZE_TIME,
                                  paintStart);
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -38,16 +38,17 @@
 #include "nsLayoutUtils.h"
 #include "FrameLayerBuilder.h"
 #include "nsPluginFrame.h"
 #include "nsContentUtils.h"
 #include "nsIPermissionManager.h"
 #include "nsServiceManagerUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/HTMLFrameElement.h"
+#include "RetainedDisplayListBuilder.h"
 
 using namespace mozilla;
 using mozilla::layout::RenderFrameParent;
 
 static bool sShowPreviousPage = true;
 
 static nsIDocument*
 GetDocumentFromView(nsView* aView)
@@ -1152,16 +1153,19 @@ nsSubDocumentFrame::BeginSwapDocShells(n
   }
 
   nsSubDocumentFrame* other = static_cast<nsSubDocumentFrame*>(aOther);
   if (!mFrameLoader || !mDidCreateDoc || mCallingShow ||
       !other->mFrameLoader || !other->mDidCreateDoc) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
+  ClearDisplayItems();
+  other->ClearDisplayItems();
+
   if (mInnerView && other->mInnerView) {
     nsView* ourSubdocViews = mInnerView->GetFirstChild();
     nsView* ourRemovedViews = ::BeginSwapDocShellsForViews(ourSubdocViews);
     nsView* otherSubdocViews = other->mInnerView->GetFirstChild();
     nsView* otherRemovedViews = ::BeginSwapDocShellsForViews(otherSubdocViews);
 
     ::InsertViewsInReverseOrder(ourRemovedViews, other->mInnerView);
     ::InsertViewsInReverseOrder(otherRemovedViews, mInnerView);
@@ -1256,16 +1260,40 @@ nsSubDocumentFrame::EndSwapDocShells(nsI
   }
   if (weakOther.IsAlive()) {
     other->PresShell()->
       FrameNeedsReflow(other, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
     other->InvalidateFrameSubtree();
   }
 }
 
+void
+nsSubDocumentFrame::ClearDisplayItems()
+{
+  DisplayItemArray* items = GetProperty(DisplayItems());
+  if (!items) {
+    return;
+  }
+
+  nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(this);
+  MOZ_ASSERT(displayRoot);
+
+  RetainedDisplayListBuilder* retainedBuilder =
+    displayRoot->GetProperty(RetainedDisplayListBuilder::Cached());
+  MOZ_ASSERT(retainedBuilder);
+
+  for (nsDisplayItem* i : *items) {
+    if (i->GetType() == DisplayItemType::TYPE_SUBDOCUMENT) {
+      i->GetChildren()->DeleteAll(retainedBuilder->Builder());
+      static_cast<nsDisplaySubDocument*>(i)->Disown();
+      break;
+    }
+  }
+}
+
 nsView*
 nsSubDocumentFrame::EnsureInnerView()
 {
   if (mInnerView) {
     return mInnerView;
   }
 
   // create, init, set the parent of the view
--- a/layout/generic/nsSubDocumentFrame.h
+++ b/layout/generic/nsSubDocumentFrame.h
@@ -147,16 +147,18 @@ protected:
   nscoord GetIntrinsicISize();
   nscoord GetIntrinsicBSize();
 
   // Show our document viewer. The document viewer is hidden via a script
   // runner, so that we can save and restore the presentation if we're
   // being reframed.
   void ShowViewer();
 
+  void ClearDisplayItems();
+
   /* Obtains the frame we should use for intrinsic size information if we are
    * an HTML <object> or <embed>  (a replaced element - not <iframe>)
    * and our sub-document has an intrinsic size. The frame returned is the
    * frame for the document element of the document we're embedding.
    *
    * Called "Obtain*" and not "Get*" because of comment on GetDocShell that
    * says it should be called ObtainDocShell because of its side effects.
    */
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6931,16 +6931,29 @@ void
 nsDisplaySubDocument::RemoveFrame(nsIFrame* aFrame)
 {
   if (aFrame == mSubDocFrame) {
     mSubDocFrame = nullptr;
   }
   nsDisplayItem::RemoveFrame(aFrame);
 }
 
+void
+nsDisplaySubDocument::Disown()
+{
+  if (mFrame) {
+    mFrame->RemoveDisplayItem(this);
+    mFrame = nullptr;
+  }
+  if (mSubDocFrame) {
+    mSubDocFrame->RemoveDisplayItem(this);
+    mSubDocFrame = nullptr;
+  }
+}
+
 UniquePtr<ScrollMetadata>
 nsDisplaySubDocument::ComputeScrollMetadata(LayerManager* aLayerManager,
                                             const ContainerLayerParameters& aContainerParameters)
 {
   if (!(mFlags & nsDisplayOwnLayerFlags::eGenerateScrollableLayer)) {
     return UniquePtr<ScrollMetadata>(nullptr);
   }
 
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -5625,16 +5625,18 @@ public:
                                                            const ContainerLayerParameters& aContainerParameters);
 
   virtual nsIFrame* FrameForInvalidation() const override;
 
   virtual bool HasDeletedFrame() const override;
 
   virtual void RemoveFrame(nsIFrame* aFrame) override;
 
+  void Disown();
+
 protected:
   ViewID mScrollParentId;
   bool mForceDispatchToContentRegion;
   bool mShouldFlatten;
   nsSubDocumentFrame* mSubDocFrame;
 };
 
 /**