Bug 1296516: Stop using the raw PLDHashTable API for the placeholder map.
MozReview-Commit-ID: Ck4yNzyYvDB
--- 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