bug 1368547 part 1 - Remove nsFrameManagerBase::mPlaceholderMap and store the placeholder on a frame property on the out-of-flow instead. r=jfkthame
authorMats Palmgren <mats@mozilla.com>
Wed, 31 May 2017 21:29:49 +0200
changeset 409780 ddcdb354143a9018a9bc94cef7a395ef46873f8b
parent 409779 422e3c006cf2b56d94f969d4b8e29b0982103437
child 409781 45409ba9a985de2d6572055f5d6f552dff74f4f6
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1368547
milestone55.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 1368547 part 1 - Remove nsFrameManagerBase::mPlaceholderMap and store the placeholder on a frame property on the out-of-flow instead. r=jfkthame MozReview-Commit-ID: 6AOxc2XgtO1
layout/base/nsFrameManager.cpp
layout/base/nsFrameManagerBase.h
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
layout/generic/nsPlaceholderFrame.cpp
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -41,44 +41,19 @@
 // #define DEBUG_UNDISPLAYED_MAP
 // #define DEBUG_DISPLAY_CONTENTS_MAP
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 
-struct PlaceholderMapEntry : public PLDHashEntryHdr {
-  // key (the out of flow frame) can be obtained through placeholder frame
-  nsPlaceholderFrame *placeholderFrame;
-};
-
-static bool
-PlaceholderMapMatchEntry(const PLDHashEntryHdr *hdr, const void *key)
-{
-  const PlaceholderMapEntry *entry =
-    static_cast<const PlaceholderMapEntry*>(hdr);
-  NS_ASSERTION(entry->placeholderFrame->GetOutOfFlowFrame() !=
-               (void*)0xdddddddd,
-               "Dead placeholder in placeholder map");
-  return entry->placeholderFrame->GetOutOfFlowFrame() == key;
-}
-
-static const PLDHashTableOps PlaceholderMapOps = {
-  PLDHashTable::HashVoidPtrKeyStub,
-  PlaceholderMapMatchEntry,
-  PLDHashTable::MoveEntryStub,
-  PLDHashTable::ClearEntryStub,
-  nullptr
-};
-
 nsFrameManagerBase::nsFrameManagerBase()
   : mPresShell(nullptr)
   , mRootFrame(nullptr)
-  , mPlaceholderMap(&PlaceholderMapOps, sizeof(PlaceholderMapEntry))
   , mUndisplayedMap(nullptr)
   , mDisplayContentsMap(nullptr)
   , mIsDestroyingFrames(false)
 {
 }
 
 //----------------------------------------------------------------------
 
@@ -159,57 +134,40 @@ nsFrameManager::Destroy()
 }
 
 //----------------------------------------------------------------------
 
 // Placeholder frame functions
 nsPlaceholderFrame*
 nsFrameManager::GetPlaceholderFrameFor(const nsIFrame* aFrame)
 {
-  NS_PRECONDITION(aFrame, "null param unexpected");
-
-  auto entry = static_cast<PlaceholderMapEntry*>
-    (const_cast<PLDHashTable*>(&mPlaceholderMap)->Search(aFrame));
-  if (entry) {
-    return entry->placeholderFrame;
-  }
-
-  return nullptr;
+  MOZ_ASSERT(aFrame);
+  MOZ_ASSERT(aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
+  return aFrame->GetProperty(nsIFrame::PlaceholderFrameProperty());
 }
 
 void
 nsFrameManager::RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
 {
-  MOZ_ASSERT(aPlaceholderFrame, "null param unexpected");
-  MOZ_ASSERT(aPlaceholderFrame->IsPlaceholderFrame(), "unexpected frame type");
-  auto entry = static_cast<PlaceholderMapEntry*>
-    (mPlaceholderMap.Add(aPlaceholderFrame->GetOutOfFlowFrame()));
-  MOZ_ASSERT(!entry->placeholderFrame,
+  MOZ_ASSERT(aPlaceholderFrame);
+  MOZ_ASSERT(!GetPlaceholderFrameFor(aPlaceholderFrame->GetOutOfFlowFrame()),
              "Registering a placeholder for a frame that already has a placeholder!");
-  entry->placeholderFrame = aPlaceholderFrame;
+  aPlaceholderFrame->GetOutOfFlowFrame()->SetProperty(nsIFrame::PlaceholderFrameProperty(), aPlaceholderFrame);
 }
 
 void
 nsFrameManager::UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
 {
-  NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
-  NS_PRECONDITION(aPlaceholderFrame->IsPlaceholderFrame(),
-                  "unexpected frame type");
-
-  mPlaceholderMap.Remove(aPlaceholderFrame->GetOutOfFlowFrame());
+  MOZ_ASSERT(aPlaceholderFrame);
+  aPlaceholderFrame->GetOutOfFlowFrame()->DeleteProperty(nsIFrame::PlaceholderFrameProperty());
 }
 
 void
 nsFrameManager::ClearPlaceholderFrameMap()
 {
-  for (auto iter = mPlaceholderMap.Iter(); !iter.Done(); iter.Next()) {
-    auto entry = static_cast<PlaceholderMapEntry*>(iter.Get());
-    entry->placeholderFrame->SetOutOfFlowFrame(nullptr);
-  }
-  mPlaceholderMap.Clear();
 }
 
 //----------------------------------------------------------------------
 
 static nsIContent*
 ParentForUndisplayedMap(const nsIContent* aContent)
 {
   MOZ_ASSERT(aContent);
--- a/layout/base/nsFrameManagerBase.h
+++ b/layout/base/nsFrameManagerBase.h
@@ -46,15 +46,14 @@ public:
   }
 
 protected:
   class UndisplayedMap;
 
   // weak link, because the pres shell owns us
   nsIPresShell* MOZ_NON_OWNING_REF mPresShell;
   nsIFrame*                       mRootFrame;
-  PLDHashTable                    mPlaceholderMap;
   UndisplayedMap*                 mUndisplayedMap;
   UndisplayedMap*                 mDisplayContentsMap;
   bool                            mIsDestroyingFrames;  // The frame manager is destroying some frame(s).
 };
 
 #endif
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -730,17 +730,16 @@ nsFrame::DestroyFrom(nsIFrame* aDestruct
       shell->FrameManager()->GetPlaceholderFrameFor(this);
     NS_ASSERTION(!placeholder || (aDestructRoot != this),
                  "Don't call Destroy() on OOFs, call Destroy() on the placeholder.");
     NS_ASSERTION(!placeholder ||
                  nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, placeholder),
                  "Placeholder relationship should have been torn down already; "
                  "this might mean we have a stray placeholder in the tree.");
     if (placeholder) {
-      shell->FrameManager()->UnregisterPlaceholderFrame(placeholder);
       placeholder->SetOutOfFlowFrame(nullptr);
     }
   }
 
   // If we have any IB split siblings, clear their references to us.
   // (Note: This has to happen before we clear our Properties() table.)
   if (mState & NS_FRAME_PART_OF_IBSPLIT) {
     // Delete previous sibling's reference to me.
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -78,16 +78,17 @@ class nsDisplayListSet;
 class nsDisplayList;
 class gfxSkipChars;
 class gfxSkipCharsIterator;
 class gfxContext;
 class nsLineList_iterator;
 class nsAbsoluteContainingBlock;
 class nsIContent;
 class nsContainerFrame;
+class nsPlaceholderFrame;
 class nsStyleChangeList;
 
 struct nsPeekOffsetStruct;
 struct nsPoint;
 struct nsRect;
 struct nsSize;
 struct nsMargin;
 struct CharacterDataChangeInfo;
@@ -1181,16 +1182,18 @@ public:
   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty, nscoord)
   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty, nscoord)
 
   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(GenConProperty, ContentArray,
                                       DestroyContentArray)
 
   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty, mozilla::FrameBidiData)
 
+  NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty, nsPlaceholderFrame)
+
   mozilla::FrameBidiData GetBidiData() const
   {
     bool exists;
     mozilla::FrameBidiData bidiData = GetProperty(BidiDataProperty(), &exists);
     if (!exists) {
       bidiData.precedingControl = mozilla::kBidiLevelNone;
     }
     return bidiData;
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -155,26 +155,25 @@ nsPlaceholderFrame::Reflow(nsPresContext
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 void
 nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsIFrame* oof = mOutOfFlowFrame;
   if (oof) {
-    // Unregister out-of-flow frame
-    nsFrameManager* fm = PresContext()->GetPresShell()->FrameManager();
-    fm->UnregisterPlaceholderFrame(this);
     mOutOfFlowFrame = nullptr;
+    oof->DeleteProperty(nsIFrame::PlaceholderFrameProperty());
     // If aDestructRoot is not an ancestor of the out-of-flow frame,
     // then call RemoveFrame on it here.
     // Also destroy it here if it's a popup frame. (Bug 96291)
     if ((GetStateBits() & PLACEHOLDER_FOR_POPUP) ||
         !nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, oof)) {
       ChildListID listId = nsLayoutUtils::GetChildListNameFor(oof);
+      nsFrameManager* fm = PresContext()->GetPresShell()->FrameManager();
       fm->RemoveFrame(listId, oof);
     }
     // else oof will be destroyed by its parent
   }
 
   nsFrame::DestroyFrom(aDestructRoot);
 }