Bug 1296516: Stop using the raw PLDHashTable API for the placeholder map. draft
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Thu, 18 Aug 2016 17:31:12 -0700
changeset 403108 e7f5496656363a231ce0b35cada9f2a8760c9518
parent 403104 59b88d2b46adab506eb4a4aecde94da8a7ca4921
child 403109 183fd834cbf0b7d85d1f8959b9cca6c2f3472e78
push id26827
push userbmo:ealvarez@mozilla.com
push dateFri, 19 Aug 2016 04:18:50 +0000
bugs1296516
milestone51.0a1
Bug 1296516: Stop using the raw PLDHashTable API for the placeholder map. MozReview-Commit-ID: Ck4yNzyYvDB
layout/base/nsFrameManager.cpp
layout/base/nsFrameManagerBase.h
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -46,44 +46,33 @@
     #undef DEBUG_DISPLAY_CONTENTS_MAP
   #endif
 
 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;
+PlaceholderMapEntry::KeyType
+PlaceholderMapEntry::GetKey() const {
+  MOZ_ASSERT(mPlaceholderFrame->GetOutOfFlowFrame() != (void*)0xdddddddd,
+             "Dead placeholder in placeholder map");
+  return mPlaceholderFrame->GetOutOfFlowFrame();
 }
 
-static const PLDHashTableOps PlaceholderMapOps = {
-  PLDHashTable::HashVoidPtrKeyStub,
-  PlaceholderMapMatchEntry,
-  PLDHashTable::MoveEntryStub,
-  PLDHashTable::ClearEntryStub,
-  nullptr
-};
+void
+PlaceholderMapEntry::SetPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
+{
+  MOZ_ASSERT(aPlaceholderFrame->GetOutOfFlowFrame() == mOriginalOutOfFlowFrame);
+  mPlaceholderFrame = aPlaceholderFrame;
+}
 
 nsFrameManagerBase::nsFrameManagerBase()
   : mPresShell(nullptr)
   , mRootFrame(nullptr)
-  , mPlaceholderMap(&PlaceholderMapOps, sizeof(PlaceholderMapEntry))
   , mUndisplayedMap(nullptr)
   , mDisplayContentsMap(nullptr)
   , mIsDestroyingFrames(false)
 {
 }
 
 //----------------------------------------------------------------------
 
@@ -151,17 +140,17 @@ void
 nsFrameManager::Destroy()
 {
   NS_ASSERTION(mPresShell, "Frame manager already shut down.");
 
   // Destroy the frame hierarchy.
   mPresShell->SetIgnoreFrameDestruction(true);
 
   // Unregister all placeholders before tearing down the frame tree
-  nsFrameManager::ClearPlaceholderFrameMap();
+  ClearPlaceholderFrameMap();
 
   if (mRootFrame) {
     mRootFrame->Destroy();
     mRootFrame = nullptr;
   }
 
   delete mUndisplayedMap;
   mUndisplayedMap = nullptr;
@@ -172,62 +161,59 @@ nsFrameManager::Destroy()
 }
 
 //----------------------------------------------------------------------
 
 // Placeholder frame functions
 nsPlaceholderFrame*
 nsFrameManager::GetPlaceholderFrameFor(const nsIFrame* aFrame)
 {
-  NS_PRECONDITION(aFrame, "null param unexpected");
+  MOZ_ASSERT(aFrame, "null param unexpected");
 
-  auto entry = static_cast<PlaceholderMapEntry*>
-    (const_cast<PLDHashTable*>(&mPlaceholderMap)->Search(aFrame));
-  if (entry) {
-    return entry->placeholderFrame;
-  }
-
-  return nullptr;
+  PlaceholderMapEntry* entry = mPlaceholderMap.GetEntry(aFrame);
+  return entry ? entry->PlaceholderFrame() : nullptr;
 }
 
 nsresult
 nsFrameManager::RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
 {
   NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
   NS_PRECONDITION(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
                   "unexpected frame type");
-  auto entry = static_cast<PlaceholderMapEntry*>
-    (mPlaceholderMap.Add(aPlaceholderFrame->GetOutOfFlowFrame(), fallible));
-  if (!entry)
+  auto entry =
+    mPlaceholderMap.PutEntry(aPlaceholderFrame->GetOutOfFlowFrame(), fallible);
+  if (!entry) {
     return NS_ERROR_OUT_OF_MEMORY;
+  }
 
-  NS_ASSERTION(!entry->placeholderFrame, "Registering a placeholder for a frame that already has a placeholder!");
-  entry->placeholderFrame = aPlaceholderFrame;
+  MOZ_ASSERT(!entry->PlaceholderFrame(),
+             "Registering a placeholder for a frame that already has a placeholder!");
+  entry->SetPlaceholderFrame(aPlaceholderFrame);
 
   return NS_OK;
 }
 
 void
 nsFrameManager::UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
 {
-  NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
-  NS_PRECONDITION(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
-                  "unexpected frame type");
+  MOZ_ASSERT(aPlaceholderFrame, "null param unexpected");
+  MOZ_ASSERT(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
+             "unexpected frame type");
 
-  mPlaceholderMap.Remove(aPlaceholderFrame->GetOutOfFlowFrame());
+  mPlaceholderMap.RemoveEntry(aPlaceholderFrame->GetOutOfFlowFrame());
 }
 
 void
 nsFrameManager::ClearPlaceholderFrameMap()
 {
   for (auto iter = mPlaceholderMap.Iter(); !iter.Done(); iter.Next()) {
-    auto entry = static_cast<PlaceholderMapEntry*>(iter.Get());
-    entry->placeholderFrame->SetOutOfFlowFrame(nullptr);
+    auto entry = iter.Get();
+    entry->PlaceholderFrame()->SetOutOfFlowFrame(nullptr);
+    iter.Remove();
   }
-  mPlaceholderMap.Clear();
 }
 
 //----------------------------------------------------------------------
 
 /* static */ nsStyleContext*
 nsFrameManager::GetStyleContextInMap(UndisplayedMap* aMap, nsIContent* aContent)
 {
   if (!aContent) {
--- a/layout/base/nsFrameManagerBase.h
+++ b/layout/base/nsFrameManagerBase.h
@@ -17,19 +17,58 @@
 /* part of nsFrameManager, to work around header inclusionordering */
 
 #ifndef _nsFrameManagerBase_h_
 #define _nsFrameManagerBase_h_
 
 #include "nsDebug.h"
 #include "PLDHashTable.h"
 #include "mozilla/Attributes.h"
+#include "nsTHashtable.h"
 
 class nsIFrame;
 class nsIPresShell;
+class nsPlaceholderFrame;
+
+class PlaceholderMapEntry final : public PLDHashEntryHdr {
+public:
+  // The key is the out of flow frame, that can be obtained via the
+  // mPlaceholderFrame member.
+  typedef const nsIFrame* KeyType;
+  typedef const nsIFrame* KeyTypePointer;
+
+  explicit PlaceholderMapEntry(const nsIFrame* aOutOfFlowFrame)
+    : mPlaceholderFrame(nullptr)
+#ifdef DEBUG
+    , mOriginalOutOfFlowFrame(aOutOfFlowFrame)
+#endif
+  {}
+
+  KeyType GetKey() const;
+
+  bool KeyEquals(KeyTypePointer aKey) const {
+    return GetKey() == aKey;
+  }
+
+  static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
+  // Straight from nsPtrHashKey.
+  static PLDHashNumber HashKey(KeyTypePointer aKey)
+  {
+    return NS_PTR_TO_UINT32(aKey) >> 2;
+  }
+
+  enum { ALLOW_MEMMOVE = true };
+
+  nsPlaceholderFrame* PlaceholderFrame() { return mPlaceholderFrame; }
+  void SetPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame);
+
+private:
+  nsPlaceholderFrame* mPlaceholderFrame;
+  const nsIFrame* mOriginalOutOfFlowFrame;
+};
 
 class nsFrameManagerBase
 {
 public:
   nsFrameManagerBase();
 
   bool IsDestroyingFrames() { return mIsDestroyingFrames; }
 
@@ -46,22 +85,22 @@ public:
   }
 
   static uint32_t GetGlobalGenerationNumber() { return sGlobalGenerationNumber; }
 
 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).
+  nsIPresShell* MOZ_NON_OWNING_REF  mPresShell;
+  nsIFrame*                         mRootFrame;
+  nsTHashtable<PlaceholderMapEntry> mPlaceholderMap;
+  UndisplayedMap*                   mUndisplayedMap;
+  UndisplayedMap*                   mDisplayContentsMap;
+  bool                              mIsDestroyingFrames;  // The frame manager is destroying some frame(s).
 
   // The frame tree generation number
   // We use this to avoid unnecessary screenshotting
   // on Android. Unfortunately, this is static to match
   // the single consumer which is also static. Keeping
   // this the same greatly simplifies lifetime issues and
   // makes sure we always using the correct number.
   // A per PresContext generation number is available