summaryrefslogtreecommitdiff
path: root/layout/base
diff options
context:
space:
mode:
authorwin7-7 <win7-7@users.noreply.github.com>2019-06-26 01:51:45 +0300
committerwin7-7 <win7-7@users.noreply.github.com>2019-06-26 01:51:45 +0300
commit00812e30dfa70f9b1a752cf0d09de00f6d401c85 (patch)
treee7eec9b55dd4e5825d3196f196c7f981be56e17a /layout/base
parentd7359c38b197c221c43def1e24cb48d4aee51bba (diff)
downloaduxp-00812e30dfa70f9b1a752cf0d09de00f6d401c85.tar.gz
Attach FrameProperties to each frame instead of using a shared hashtable
Dispense the shared hashtable and instead attach the frame property list directly to nsIFrame.
Diffstat (limited to 'layout/base')
-rw-r--r--layout/base/ActiveLayerTracker.cpp15
-rw-r--r--layout/base/FrameLayerBuilder.cpp32
-rw-r--r--layout/base/FrameProperties.h (renamed from layout/base/FramePropertyTable.h)272
-rw-r--r--layout/base/FramePropertyTable.cpp239
-rw-r--r--layout/base/OverflowChangedTracker.h4
-rw-r--r--layout/base/RestyleManager.cpp10
-rw-r--r--layout/base/RestyleManagerBase.cpp88
-rw-r--r--layout/base/RestyleManagerBase.h13
-rw-r--r--layout/base/moz.build3
-rw-r--r--layout/base/nsBidiPresUtils.cpp5
-rw-r--r--layout/base/nsCSSFrameConstructor.cpp23
-rw-r--r--layout/base/nsCSSRendering.cpp10
-rw-r--r--layout/base/nsDisplayList.cpp8
-rw-r--r--layout/base/nsDisplayList.h2
-rw-r--r--layout/base/nsIPresShell.h11
-rw-r--r--layout/base/nsLayoutUtils.cpp16
-rw-r--r--layout/base/nsPresContext.cpp3
-rw-r--r--layout/base/nsPresContext.h11
-rw-r--r--layout/base/nsPresShell.cpp35
-rw-r--r--layout/base/nsPresShell.h11
20 files changed, 285 insertions, 526 deletions
diff --git a/layout/base/ActiveLayerTracker.cpp b/layout/base/ActiveLayerTracker.cpp
index 4f60f82d76..ecee4897ae 100644
--- a/layout/base/ActiveLayerTracker.cpp
+++ b/layout/base/ActiveLayerTracker.cpp
@@ -178,7 +178,7 @@ LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
f->SchedulePaint();
}
f->RemoveStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
- f->Properties().Delete(LayerActivityProperty());
+ f->DeleteProperty(LayerActivityProperty());
} else {
c->DeleteProperty(nsGkAtoms::LayerActivity);
}
@@ -190,15 +190,13 @@ GetLayerActivity(nsIFrame* aFrame)
if (!aFrame->HasAnyStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)) {
return nullptr;
}
- FrameProperties properties = aFrame->Properties();
- return properties.Get(LayerActivityProperty());
+ return aFrame->GetProperty(LayerActivityProperty());
}
static LayerActivity*
GetLayerActivityForUpdate(nsIFrame* aFrame)
{
- FrameProperties properties = aFrame->Properties();
- LayerActivity* layerActivity = properties.Get(LayerActivityProperty());
+ LayerActivity* layerActivity = aFrame->GetProperty(LayerActivityProperty());
if (layerActivity) {
gLayerActivityTracker->MarkUsed(layerActivity);
} else {
@@ -208,7 +206,7 @@ GetLayerActivityForUpdate(nsIFrame* aFrame)
layerActivity = new LayerActivity(aFrame);
gLayerActivityTracker->AddObject(layerActivity);
aFrame->AddStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
- properties.Set(LayerActivityProperty(), layerActivity);
+ aFrame->SetProperty(LayerActivityProperty(), layerActivity);
}
return layerActivity;
}
@@ -225,8 +223,7 @@ ActiveLayerTracker::TransferActivityToContent(nsIFrame* aFrame, nsIContent* aCon
if (!aFrame->HasAnyStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)) {
return;
}
- FrameProperties properties = aFrame->Properties();
- LayerActivity* layerActivity = properties.Remove(LayerActivityProperty());
+ LayerActivity* layerActivity = aFrame->RemoveProperty(LayerActivityProperty());
aFrame->RemoveStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
if (!layerActivity) {
return;
@@ -248,7 +245,7 @@ ActiveLayerTracker::TransferActivityToFrame(nsIContent* aContent, nsIFrame* aFra
layerActivity->mContent = nullptr;
layerActivity->mFrame = aFrame;
aFrame->AddStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
- aFrame->Properties().Set(LayerActivityProperty(), layerActivity);
+ aFrame->SetProperty(LayerActivityProperty(), layerActivity);
}
static void
diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
index 9aaa28fb55..e87d9dc09e 100644
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -165,10 +165,10 @@ FrameLayerBuilder::DisplayItemData::AddFrame(nsIFrame* aFrame)
mFrameList.AppendElement(aFrame);
nsTArray<DisplayItemData*>* array =
- aFrame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty());
+ aFrame->GetProperty(FrameLayerBuilder::LayerManagerDataProperty());
if (!array) {
array = new nsTArray<DisplayItemData*>();
- aFrame->Properties().Set(FrameLayerBuilder::LayerManagerDataProperty(), array);
+ aFrame->SetProperty(FrameLayerBuilder::LayerManagerDataProperty(), array);
}
array->AppendElement(this);
}
@@ -181,7 +181,7 @@ FrameLayerBuilder::DisplayItemData::RemoveFrame(nsIFrame* aFrame)
MOZ_RELEASE_ASSERT(result, "Can't remove a frame that wasn't added!");
nsTArray<DisplayItemData*>* array =
- aFrame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty());
+ aFrame->GetProperty(FrameLayerBuilder::LayerManagerDataProperty());
MOZ_RELEASE_ASSERT(array, "Must be already stored on the frame!");
array->RemoveElement(this);
}
@@ -268,7 +268,7 @@ FrameLayerBuilder::DisplayItemData::~DisplayItemData()
continue;
}
nsTArray<DisplayItemData*> *array =
- reinterpret_cast<nsTArray<DisplayItemData*>*>(frame->Properties().Get(LayerManagerDataProperty()));
+ reinterpret_cast<nsTArray<DisplayItemData*>*>(frame->GetProperty(LayerManagerDataProperty()));
array->RemoveElement(this);
}
@@ -390,8 +390,7 @@ public:
/* static */ void
FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame)
{
- FrameProperties props = aFrame->Properties();
- props.Delete(LayerManagerDataProperty());
+ aFrame->DeleteProperty(LayerManagerDataProperty());
}
struct AssignedDisplayItem
@@ -1823,7 +1822,7 @@ FrameLayerBuilder::DisplayItemData*
FrameLayerBuilder::GetDisplayItemData(nsIFrame* aFrame, uint32_t aKey)
{
const nsTArray<DisplayItemData*>* array =
- aFrame->Properties().Get(LayerManagerDataProperty());
+ aFrame->GetProperty(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
DisplayItemData* item = AssertDisplayItemData(array->ElementAt(i));
@@ -2052,7 +2051,7 @@ FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem,
LayerManager* aManager)
{
const nsTArray<DisplayItemData*>* array =
- aItem->Frame()->Properties().Get(LayerManagerDataProperty());
+ aItem->Frame()->GetProperty(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
DisplayItemData* item = AssertDisplayItemData(array->ElementAt(i));
@@ -2069,7 +2068,7 @@ bool
FrameLayerBuilder::HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
{
const nsTArray<DisplayItemData*>* array =
- aFrame->Properties().Get(LayerManagerDataProperty());
+ aFrame->GetProperty(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
if (AssertDisplayItemData(array->ElementAt(i))->mDisplayItemKey == aDisplayItemKey) {
@@ -2084,7 +2083,7 @@ void
FrameLayerBuilder::IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback)
{
const nsTArray<DisplayItemData*>* array =
- aFrame->Properties().Get(LayerManagerDataProperty());
+ aFrame->GetProperty(LayerManagerDataProperty());
if (!array) {
return;
}
@@ -2151,7 +2150,7 @@ FrameLayerBuilder::ClearCachedGeometry(nsDisplayItem* aItem)
FrameLayerBuilder::GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
{
const nsTArray<DisplayItemData*>* array =
- aFrame->Properties().Get(LayerManagerDataProperty());
+ aFrame->GetProperty(LayerManagerDataProperty());
if (!array) {
return nullptr;
@@ -2171,7 +2170,7 @@ FrameLayerBuilder::GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKe
FrameLayerBuilder::GetDebugSingleOldPaintedLayerForFrame(nsIFrame* aFrame)
{
const nsTArray<DisplayItemData*>* array =
- aFrame->Properties().Get(LayerManagerDataProperty());
+ aFrame->GetProperty(LayerManagerDataProperty());
if (!array) {
return nullptr;
@@ -5656,7 +5655,7 @@ FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
FrameLayerBuilder::InvalidateAllLayersForFrame(nsIFrame *aFrame)
{
const nsTArray<DisplayItemData*>* array =
- aFrame->Properties().Get(LayerManagerDataProperty());
+ aFrame->GetProperty(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
AssertDisplayItemData(array->ElementAt(i))->mParent->mInvalidateAllLayers = true;
@@ -5673,7 +5672,7 @@ FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey)
// in the secondary manager
const nsTArray<DisplayItemData*>* array =
- aFrame->Properties().Get(LayerManagerDataProperty());
+ aFrame->GetProperty(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
DisplayItemData *element = AssertDisplayItemData(array->ElementAt(i));
@@ -5729,7 +5728,7 @@ FrameLayerBuilder::GetPaintedLayerScaleForFrame(nsIFrame* aFrame)
}
const nsTArray<DisplayItemData*>* array =
- f->Properties().Get(LayerManagerDataProperty());
+ f->GetProperty(LayerManagerDataProperty());
if (!array) {
continue;
}
@@ -6165,9 +6164,8 @@ FrameLayerBuilder::GetMostRecentGeometry(nsDisplayItem* aItem)
typedef nsTArray<DisplayItemData*> DataArray;
// Retrieve the array of DisplayItemData associated with our frame.
- FrameProperties properties = aItem->Frame()->Properties();
const DataArray* dataArray =
- properties.Get(LayerManagerDataProperty());
+ aItem->Frame()->GetProperty(LayerManagerDataProperty());
if (!dataArray) {
return nullptr;
}
diff --git a/layout/base/FramePropertyTable.h b/layout/base/FrameProperties.h
index e9847efbf7..bba3ee06b2 100644
--- a/layout/base/FramePropertyTable.h
+++ b/layout/base/FrameProperties.h
@@ -3,15 +3,15 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#ifndef FRAMEPROPERTYTABLE_H_
-#define FRAMEPROPERTYTABLE_H_
+#ifndef FRAMEPROPERTIES_H_
+#define FRAMEPROPERTIES_H_
+#include "mozilla/DebugOnly.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Unused.h"
#include "nsTArray.h"
-#include "nsTHashtable.h"
-#include "nsHashKeys.h"
+#include "nsThreadUtils.h"
class nsIFrame;
@@ -131,7 +131,7 @@ struct FramePropertyTypeHelper<SmallValueHolder<T>>
}
/**
- * The FramePropertyTable is optimized for storing 0 or 1 properties on
+ * The FrameProperties class is optimized for storing 0 or 1 properties on
* a given frame. Storing very large numbers of properties on a single
* frame will not be efficient.
*
@@ -141,7 +141,8 @@ struct FramePropertyTypeHelper<SmallValueHolder<T>>
* Of course, the destructor function (if any) must handle such values
* correctly.
*/
-class FramePropertyTable {
+class FrameProperties
+{
public:
template<typename T>
using Descriptor = const FramePropertyDescriptor<T>*;
@@ -150,32 +151,31 @@ public:
template<typename T>
using PropertyType = typename detail::FramePropertyTypeHelper<T>::Type;
- FramePropertyTable() : mLastFrame(nullptr), mLastEntry(nullptr)
+ explicit FrameProperties()
{
}
- ~FramePropertyTable()
+
+ ~FrameProperties()
{
- DeleteAll();
+ MOZ_ASSERT(mProperties.Length() == 0, "forgot to delete properties");
}
/**
- * Set a property value on a frame. This requires one hashtable
- * lookup (using the frame as the key) and a linear search through
- * the properties of that frame. Any existing value for the property
+ * Set a property value. This requires a linear search through
+ * the properties of the frame. Any existing value for the property
* is destroyed.
*/
template<typename T>
- void Set(const nsIFrame* aFrame, Descriptor<T> aProperty,
- PropertyType<T> aValue)
+ void Set(Descriptor<T> aProperty, PropertyType<T> aValue,
+ const nsIFrame* aFrame)
{
void* ptr = ReinterpretHelper<T>::ToPointer(aValue);
- SetInternal(aFrame, aProperty, ptr);
+ SetInternal(aProperty, ptr, aFrame);
}
/**
- * @return true if @aProperty is set for @aFrame. This requires one hashtable
- * lookup (using the frame as the key) and a linear search through the
- * properties of that frame.
+ * @return true if @aProperty is set. This requires a linear search through the
+ * properties of the frame.
*
* In most cases, this shouldn't be used outside of assertions, because if
* you're doing a lookup anyway it would be far more efficient to call Get()
@@ -190,17 +190,15 @@ public:
* an existing value for the frame property.
*/
template<typename T>
- bool Has(const nsIFrame* aFrame, Descriptor<T> aProperty)
+ bool Has(Descriptor<T> aProperty) const
{
- bool foundResult = false;
- mozilla::Unused << GetInternal(aFrame, aProperty, &foundResult);
- return foundResult;
+ return mProperties.IndexOf(aProperty, 0, PropertyComparator()) != nsTArray<PropertyValue>::NoIndex;
}
/**
- * Get a property value for a frame. This requires one hashtable
+ * Get a property value. This requires a linear search through
* lookup (using the frame as the key) and a linear search through
- * the properties of that frame. If the frame has no such property,
+ * the properties of the frame. If the frame has no such property,
* returns zero-filled result, which means null for pointers and
* zero for integers and floating point types.
* @param aFoundResult if non-null, receives a value 'true' iff
@@ -209,16 +207,15 @@ public:
* 'property value is null'.
*/
template<typename T>
- PropertyType<T> Get(const nsIFrame* aFrame, Descriptor<T> aProperty,
- bool* aFoundResult = nullptr)
+ PropertyType<T> Get(Descriptor<T> aProperty,
+ bool* aFoundResult = nullptr) const
{
- void* ptr = GetInternal(aFrame, aProperty, aFoundResult);
+ void* ptr = GetInternal(aProperty, aFoundResult);
return ReinterpretHelper<T>::FromPointer(ptr);
}
/**
- * Remove a property value for a frame. This requires one hashtable
- * lookup (using the frame as the key) and a linear search through
- * the properties of that frame. The old property value is returned
+ * Remove a property value. This requires a linear search through
+ * the properties of the frame. The old property value is returned
* (and not destroyed). If the frame has no such property,
* returns zero-filled result, which means null for pointers and
* zero for integers and floating point types.
@@ -228,46 +225,63 @@ public:
* 'property value is null'.
*/
template<typename T>
- PropertyType<T> Remove(const nsIFrame* aFrame, Descriptor<T> aProperty,
+ PropertyType<T> Remove(Descriptor<T> aProperty,
bool* aFoundResult = nullptr)
{
- void* ptr = RemoveInternal(aFrame, aProperty, aFoundResult);
+ void* ptr = RemoveInternal(aProperty, aFoundResult);
return ReinterpretHelper<T>::FromPointer(ptr);
}
/**
- * Remove and destroy a property value for a frame. This requires one
- * hashtable lookup (using the frame as the key) and a linear search
- * through the properties of that frame. If the frame has no such
+ * Remove and destroy a property value. This requires a linear search
+ * through the properties of the frame. If the frame has no such
* property, nothing happens.
*/
template<typename T>
- void Delete(const nsIFrame* aFrame, Descriptor<T> aProperty)
+ void Delete(Descriptor<T> aProperty, const nsIFrame* aFrame)
{
- DeleteInternal(aFrame, aProperty);
+ DeleteInternal(aProperty, aFrame);
}
/**
- * Remove and destroy all property values for a frame. This requires one
- * hashtable lookup (using the frame as the key).
- */
- void DeleteAllFor(const nsIFrame* aFrame);
- /**
- * Remove and destroy all property values for all frames.
+ * Remove and destroy all property values for the frame.
*/
- void DeleteAll();
+ void DeleteAll(const nsIFrame* aFrame) {
+ mozilla::DebugOnly<size_t> len = mProperties.Length();
+ for (auto& prop : mProperties) {
+ prop.DestroyValueFor(aFrame);
+ MOZ_ASSERT(mProperties.Length() == len);
+ }
+ mProperties.Clear();
+ }
- size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+ size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
+ // We currently report only the shallow size of the mProperties array.
+ // As for the PropertyValue entries: we don't need to measure the mProperty
+ // field of because it always points to static memory, and we can't measure
+ // mValue because the type is opaque.
+ // XXX Can we do better, e.g. with a method on the descriptor?
+ return mProperties.ShallowSizeOfExcludingThis(aMallocSizeOf);
+ }
-protected:
- void SetInternal(const nsIFrame* aFrame, UntypedDescriptor aProperty,
- void* aValue);
+private:
+ friend class ::nsIFrame;
+
+ // Prevent copying of FrameProperties; we should always return/pass around
+ // references to it, not copies!
+ FrameProperties(const FrameProperties&) = delete;
+ FrameProperties& operator=(const FrameProperties&) = delete;
- void* GetInternal(const nsIFrame* aFrame, UntypedDescriptor aProperty,
- bool* aFoundResult);
+ inline void
+ SetInternal(UntypedDescriptor aProperty, void* aValue,
+ const nsIFrame* aFrame);
- void* RemoveInternal(const nsIFrame* aFrame, UntypedDescriptor aProperty,
- bool* aFoundResult);
+ inline void*
+ GetInternal(UntypedDescriptor aProperty, bool* aFoundResult) const;
- void DeleteInternal(const nsIFrame* aFrame, UntypedDescriptor aProperty);
+ inline void*
+ RemoveInternal(UntypedDescriptor aProperty, bool* aFoundResult);
+
+ inline void
+ DeleteInternal(UntypedDescriptor aProperty, const nsIFrame* aFrame);
template<typename T>
struct ReinterpretHelper
@@ -305,21 +319,13 @@ protected:
};
/**
- * Stores a property descriptor/value pair. It can also be used to
- * store an nsTArray of PropertyValues.
+ * Stores a property descriptor/value pair.
*/
struct PropertyValue {
PropertyValue() : mProperty(nullptr), mValue(nullptr) {}
PropertyValue(UntypedDescriptor aProperty, void* aValue)
: mProperty(aProperty), mValue(aValue) {}
- bool IsArray() { return !mProperty && mValue; }
- nsTArray<PropertyValue>* ToArray()
- {
- NS_ASSERTION(IsArray(), "Must be array");
- return reinterpret_cast<nsTArray<PropertyValue>*>(&mValue);
- }
-
void DestroyValueFor(const nsIFrame* aFrame) {
if (mProperty->mDestructor) {
mProperty->mDestructor(mValue);
@@ -328,20 +334,6 @@ protected:
}
}
- size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) {
- size_t n = 0;
- // We don't need to measure mProperty because it always points to static
- // memory. As for mValue: if it's a single value we can't measure it,
- // because the type is opaque; if it's an array, we measure the array
- // storage, but we can't measure the individual values, again because
- // their types are opaque.
- if (IsArray()) {
- nsTArray<PropertyValue>* array = ToArray();
- n += array->ShallowSizeOfExcludingThis(aMallocSizeOf);
- }
- return n;
- }
-
UntypedDescriptor mProperty;
void* mValue;
};
@@ -363,80 +355,86 @@ protected:
}
};
- /**
- * Our hashtable entry. The key is an nsIFrame*, the value is a
- * PropertyValue representing one or more property/value pairs.
- */
- class Entry : public nsPtrHashKey<const nsIFrame>
- {
- public:
- explicit Entry(KeyTypePointer aKey) : nsPtrHashKey<const nsIFrame>(aKey) {}
- Entry(const Entry &toCopy) :
- nsPtrHashKey<const nsIFrame>(toCopy), mProp(toCopy.mProp) {}
-
- size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) {
- return mProp.SizeOfExcludingThis(aMallocSizeOf);
- }
-
- PropertyValue mProp;
- };
-
- static void DeleteAllForEntry(Entry* aEntry);
-
- // Note that mLastEntry points into mEntries, so we need to be careful about
- // not triggering a resize of mEntries, e.g. use RawRemoveEntry() instead of
- // RemoveEntry() in some places.
- nsTHashtable<Entry> mEntries;
- const nsIFrame* mLastFrame;
- Entry* mLastEntry;
+ nsTArray<PropertyValue> mProperties;
};
/**
* This class encapsulates the properties of a frame.
*/
-class FrameProperties {
-public:
- template<typename T> using Descriptor = FramePropertyTable::Descriptor<T>;
- template<typename T> using PropertyType = FramePropertyTable::PropertyType<T>;
-
- FrameProperties(FramePropertyTable* aTable, const nsIFrame* aFrame)
- : mTable(aTable), mFrame(aFrame) {}
+inline void*
+FrameProperties::GetInternal(UntypedDescriptor aProperty,
+ bool* aFoundResult) const
+{
+ MOZ_ASSERT(aProperty, "Null property?");
- template<typename T>
- void Set(Descriptor<T> aProperty, PropertyType<T> aValue) const
- {
- mTable->Set(mFrame, aProperty, aValue);
+ auto index = mProperties.IndexOf(aProperty, 0, PropertyComparator());
+ if (index == nsTArray<PropertyValue>::NoIndex) {
+ if (aFoundResult) {
+ *aFoundResult = false;
+ }
+ return nullptr;
}
- template<typename T>
- bool Has(Descriptor<T> aProperty) const
- {
- return mTable->Has(mFrame, aProperty);
+ if (aFoundResult) {
+ *aFoundResult = true;
}
- template<typename T>
- PropertyType<T> Get(Descriptor<T> aProperty,
- bool* aFoundResult = nullptr) const
- {
- return mTable->Get(mFrame, aProperty, aFoundResult);
- }
- template<typename T>
- PropertyType<T> Remove(Descriptor<T> aProperty,
- bool* aFoundResult = nullptr) const
- {
- return mTable->Remove(mFrame, aProperty, aFoundResult);
+return mProperties.ElementAt(index).mValue;
+}
+
+inline void
+FrameProperties::SetInternal(UntypedDescriptor aProperty, void* aValue,
+ const nsIFrame* aFrame)
+{
+ MOZ_ASSERT(aProperty, "Null property?");
+
+ auto index = mProperties.IndexOf(aProperty, 0, PropertyComparator());
+ if (index != nsTArray<PropertyValue>::NoIndex) {
+ PropertyValue* pv = &mProperties.ElementAt(index);
+ pv->DestroyValueFor(aFrame);
+ pv->mValue = aValue;
+ return;
}
- template<typename T>
- void Delete(Descriptor<T> aProperty)
- {
- mTable->Delete(mFrame, aProperty);
+
+ mProperties.AppendElement(PropertyValue(aProperty, aValue));
+}
+
+inline void*
+FrameProperties::RemoveInternal(UntypedDescriptor aProperty, bool* aFoundResult)
+{
+ MOZ_ASSERT(aProperty, "Null property?");
+
+ auto index = mProperties.IndexOf(aProperty, 0, PropertyComparator());
+ if (index == nsTArray<PropertyValue>::NoIndex) {
+ if (aFoundResult) {
+ *aFoundResult = false;
+ }
+ return nullptr;
}
-private:
- FramePropertyTable* mTable;
- const nsIFrame* mFrame;
-};
+if (aFoundResult) {
+ *aFoundResult = true;
+}
+
+void* result = mProperties.ElementAt(index).mValue;
+mProperties.RemoveElementAt(index);
+
+return result;
+}
+
+inline void
+FrameProperties::DeleteInternal(UntypedDescriptor aProperty,
+ const nsIFrame* aFrame)
+{
+ MOZ_ASSERT(aProperty, "Null property?");
+
+ auto index = mProperties.IndexOf(aProperty, 0, PropertyComparator());
+ if (index != nsTArray<PropertyValue>::NoIndex) {
+ mProperties.ElementAt(index).DestroyValueFor(aFrame);
+ mProperties.RemoveElementAt(index);
+ }
+}
} // namespace mozilla
-#endif /* FRAMEPROPERTYTABLE_H_ */
+#endif /* FRAMEPROPERTIES_H_ */
diff --git a/layout/base/FramePropertyTable.cpp b/layout/base/FramePropertyTable.cpp
deleted file mode 100644
index 0fd9b1c377..0000000000
--- a/layout/base/FramePropertyTable.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "FramePropertyTable.h"
-
-#include "mozilla/MemoryReporting.h"
-
-namespace mozilla {
-
-void
-FramePropertyTable::SetInternal(
- const nsIFrame* aFrame, UntypedDescriptor aProperty, void* aValue)
-{
- NS_ASSERTION(aFrame, "Null frame?");
- NS_ASSERTION(aProperty, "Null property?");
-
- if (mLastFrame != aFrame || !mLastEntry) {
- mLastFrame = aFrame;
- mLastEntry = mEntries.PutEntry(aFrame);
- }
- Entry* entry = mLastEntry;
-
- if (!entry->mProp.IsArray()) {
- if (!entry->mProp.mProperty) {
- // Empty entry, so we can just store our property in the empty slot
- entry->mProp.mProperty = aProperty;
- entry->mProp.mValue = aValue;
- return;
- }
- if (entry->mProp.mProperty == aProperty) {
- // Just overwrite the current value
- entry->mProp.DestroyValueFor(aFrame);
- entry->mProp.mValue = aValue;
- return;
- }
-
- // We need to expand the single current entry to an array
- PropertyValue current = entry->mProp;
- entry->mProp.mProperty = nullptr;
- static_assert(sizeof(nsTArray<PropertyValue>) <= sizeof(void *),
- "Property array must fit entirely within entry->mProp.mValue");
- new (&entry->mProp.mValue) nsTArray<PropertyValue>(4);
- entry->mProp.ToArray()->AppendElement(current);
- }
-
- nsTArray<PropertyValue>* array = entry->mProp.ToArray();
- nsTArray<PropertyValue>::index_type index =
- array->IndexOf(aProperty, 0, PropertyComparator());
- if (index != nsTArray<PropertyValue>::NoIndex) {
- PropertyValue* pv = &array->ElementAt(index);
- pv->DestroyValueFor(aFrame);
- pv->mValue = aValue;
- return;
- }
-
- array->AppendElement(PropertyValue(aProperty, aValue));
-}
-
-void*
-FramePropertyTable::GetInternal(
- const nsIFrame* aFrame, UntypedDescriptor aProperty, bool* aFoundResult)
-{
- NS_ASSERTION(aFrame, "Null frame?");
- NS_ASSERTION(aProperty, "Null property?");
-
- if (aFoundResult) {
- *aFoundResult = false;
- }
-
- if (mLastFrame != aFrame) {
- mLastFrame = aFrame;
- mLastEntry = mEntries.GetEntry(mLastFrame);
- }
- Entry* entry = mLastEntry;
- if (!entry)
- return nullptr;
-
- if (entry->mProp.mProperty == aProperty) {
- if (aFoundResult) {
- *aFoundResult = true;
- }
- return entry->mProp.mValue;
- }
- if (!entry->mProp.IsArray()) {
- // There's just one property and it's not the one we want, bail
- return nullptr;
- }
-
- nsTArray<PropertyValue>* array = entry->mProp.ToArray();
- nsTArray<PropertyValue>::index_type index =
- array->IndexOf(aProperty, 0, PropertyComparator());
- if (index == nsTArray<PropertyValue>::NoIndex)
- return nullptr;
-
- if (aFoundResult) {
- *aFoundResult = true;
- }
-
- return array->ElementAt(index).mValue;
-}
-
-void*
-FramePropertyTable::RemoveInternal(
- const nsIFrame* aFrame, UntypedDescriptor aProperty, bool* aFoundResult)
-{
- NS_ASSERTION(aFrame, "Null frame?");
- NS_ASSERTION(aProperty, "Null property?");
-
- if (aFoundResult) {
- *aFoundResult = false;
- }
-
- if (mLastFrame != aFrame) {
- mLastFrame = aFrame;
- mLastEntry = mEntries.GetEntry(aFrame);
- }
- Entry* entry = mLastEntry;
- if (!entry)
- return nullptr;
-
- if (entry->mProp.mProperty == aProperty) {
- // There's only one entry and it's the one we want
- void* value = entry->mProp.mValue;
-
- // Here it's ok to use RemoveEntry() -- which may resize mEntries --
- // because we null mLastEntry at the same time.
- mEntries.RemoveEntry(entry);
- mLastEntry = nullptr;
- if (aFoundResult) {
- *aFoundResult = true;
- }
- return value;
- }
- if (!entry->mProp.IsArray()) {
- // There's just one property and it's not the one we want, bail
- return nullptr;
- }
-
- nsTArray<PropertyValue>* array = entry->mProp.ToArray();
- nsTArray<PropertyValue>::index_type index =
- array->IndexOf(aProperty, 0, PropertyComparator());
- if (index == nsTArray<PropertyValue>::NoIndex) {
- // No such property, bail
- return nullptr;
- }
-
- if (aFoundResult) {
- *aFoundResult = true;
- }
-
- void* result = array->ElementAt(index).mValue;
-
- uint32_t last = array->Length() - 1;
- array->ElementAt(index) = array->ElementAt(last);
- array->RemoveElementAt(last);
-
- if (last == 1) {
- PropertyValue pv = array->ElementAt(0);
- array->~nsTArray<PropertyValue>();
- entry->mProp = pv;
- }
-
- return result;
-}
-
-void
-FramePropertyTable::DeleteInternal(
- const nsIFrame* aFrame, UntypedDescriptor aProperty)
-{
- NS_ASSERTION(aFrame, "Null frame?");
- NS_ASSERTION(aProperty, "Null property?");
-
- bool found;
- void* v = RemoveInternal(aFrame, aProperty, &found);
- if (found) {
- PropertyValue pv(aProperty, v);
- pv.DestroyValueFor(aFrame);
- }
-}
-
-/* static */ void
-FramePropertyTable::DeleteAllForEntry(Entry* aEntry)
-{
- if (!aEntry->mProp.IsArray()) {
- aEntry->mProp.DestroyValueFor(aEntry->GetKey());
- return;
- }
-
- nsTArray<PropertyValue>* array = aEntry->mProp.ToArray();
- for (uint32_t i = 0; i < array->Length(); ++i) {
- array->ElementAt(i).DestroyValueFor(aEntry->GetKey());
- }
- array->~nsTArray<PropertyValue>();
-}
-
-void
-FramePropertyTable::DeleteAllFor(const nsIFrame* aFrame)
-{
- NS_ASSERTION(aFrame, "Null frame?");
-
- Entry* entry = mEntries.GetEntry(aFrame);
- if (!entry)
- return;
-
- if (mLastFrame == aFrame) {
- // Flush cache. We assume DeleteAllForEntry will be called before
- // a frame is destroyed.
- mLastFrame = nullptr;
- mLastEntry = nullptr;
- }
-
- DeleteAllForEntry(entry);
-
- // mLastEntry points into mEntries, so we use RawRemoveEntry() which will not
- // resize mEntries.
- mEntries.RawRemoveEntry(entry);
-}
-
-void
-FramePropertyTable::DeleteAll()
-{
- mLastFrame = nullptr;
- mLastEntry = nullptr;
-
- for (auto iter = mEntries.Iter(); !iter.Done(); iter.Next()) {
- DeleteAllForEntry(iter.Get());
- }
- mEntries.Clear();
-}
-
-size_t
-FramePropertyTable::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
-{
- return mEntries.SizeOfExcludingThis(aMallocSizeOf);
-}
-
-} // namespace mozilla
diff --git a/layout/base/OverflowChangedTracker.h b/layout/base/OverflowChangedTracker.h
index a18d64b469..40145c65c3 100644
--- a/layout/base/OverflowChangedTracker.h
+++ b/layout/base/OverflowChangedTracker.h
@@ -112,12 +112,12 @@ public:
// Take a faster path that doesn't require unioning the overflow areas
// of our children.
- NS_ASSERTION(frame->Properties().Get(
+ NS_ASSERTION(frame->GetProperty(
nsIFrame::DebugInitialOverflowPropertyApplied()),
"InitialOverflowProperty must be set first.");
nsOverflowAreas* overflow =
- frame->Properties().Get(nsIFrame::InitialOverflowProperty());
+ frame->GetProperty(nsIFrame::InitialOverflowProperty());
if (overflow) {
// FinishAndStoreOverflow will change the overflow areas passed in,
// so make a copy.
diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp
index de8f102241..124b5535e0 100644
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -1122,10 +1122,10 @@ GetPrevContinuationWithPossiblySameStyle(nsIFrame* aFrame)
// We're the first continuation, so we can just get the frame
// property directly
prevContinuation =
- aFrame->Properties().Get(nsIFrame::IBSplitPrevSibling());
+ aFrame->GetProperty(nsIFrame::IBSplitPrevSibling());
if (prevContinuation) {
prevContinuation =
- prevContinuation->Properties().Get(nsIFrame::IBSplitPrevSibling());
+ prevContinuation->GetProperty(nsIFrame::IBSplitPrevSibling());
}
}
@@ -1313,8 +1313,7 @@ RestyleManager::ReparentStyleContext(nsIFrame* aFrame)
// oldContext)" check will prevent us from redoing work.
if ((aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
!aFrame->GetPrevContinuation()) {
- nsIFrame* sib =
- aFrame->Properties().Get(nsIFrame::IBSplitSibling());
+ nsIFrame* sib = aFrame->GetProperty(nsIFrame::IBSplitSibling());
if (sib) {
ReparentStyleContext(sib);
}
@@ -3349,7 +3348,6 @@ ElementRestyler::ComputeStyleChangeFor(nsIFrame* aFrame,
// line), we might restyle more than that.
nsPresContext* presContext = aFrame->PresContext();
- FramePropertyTable* propTable = presContext->PropertyTable();
TreeMatchContext treeMatchContext(true,
nsRuleWalker::eRelevantLinkUnvisited,
@@ -3363,7 +3361,7 @@ ElementRestyler::ComputeStyleChangeFor(nsIFrame* aFrame,
nsTArray<nsIContent*> visibleKidsOfHiddenElement;
nsIFrame* nextIBSibling;
for (nsIFrame* ibSibling = aFrame; ibSibling; ibSibling = nextIBSibling) {
- nextIBSibling = RestyleManager::GetNextBlockInInlineSibling(propTable, ibSibling);
+ nextIBSibling = RestyleManager::GetNextBlockInInlineSibling(ibSibling);
if (nextIBSibling) {
// Don't allow some ib-split siblings to be processed with
diff --git a/layout/base/RestyleManagerBase.cpp b/layout/base/RestyleManagerBase.cpp
index d96d9dbbb0..6770f94642 100644
--- a/layout/base/RestyleManagerBase.cpp
+++ b/layout/base/RestyleManagerBase.cpp
@@ -385,8 +385,6 @@ RestyleManagerBase::DebugVerifyStyleTree(nsIFrame* aFrame)
#endif // DEBUG
-NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(ChangeListProperty, bool)
-
/**
* Sync views on aFrame and all of aFrame's descendants (following placeholders),
* if aChange has nsChangeHint_SyncFrameView.
@@ -521,10 +519,9 @@ RecomputePosition(nsIFrame* aFrame)
// normal position, go ahead and add the offsets directly.
// First, we need to ensure that the normal position is stored though.
nsPoint normalPosition = cont->GetNormalPosition();
- auto props = cont->Properties();
- const auto& prop = nsIFrame::NormalPositionProperty();
- if (!props.Get(prop)) {
- props.Set(prop, new nsPoint(normalPosition));
+ if (!cont->GetProperty(nsIFrame::NormalPositionProperty())) {
+ cont->SetProperty(nsIFrame::NormalPositionProperty(),
+ new nsPoint(normalPosition));
}
cont->SetPosition(normalPosition +
nsPoint(newOffsets.left, newOffsets.top));
@@ -739,8 +736,7 @@ RestyleManagerBase::GetNearestAncestorFrame(nsIContent* aContent)
}
/* static */ nsIFrame*
-RestyleManagerBase::GetNextBlockInInlineSibling(FramePropertyTable* aPropTable,
- nsIFrame* aFrame)
+RestyleManagerBase::GetNextBlockInInlineSibling(nsIFrame* aFrame)
{
NS_ASSERTION(!aFrame->GetPrevContinuation(),
"must start with the first continuation");
@@ -750,8 +746,7 @@ RestyleManagerBase::GetNextBlockInInlineSibling(FramePropertyTable* aPropTable,
return nullptr;
}
- return static_cast<nsIFrame*>
- (aPropTable->Get(aFrame, nsIFrame::IBSplitSibling()));
+ return aFrame->GetProperty(nsIFrame::IBSplitSibling());
}
static void
@@ -1028,10 +1023,10 @@ RestyleManagerBase::GetNextContinuationWithSameStyle(
// We're the last continuation, so we have to hop back to the first
// before getting the frame property
nextContinuation =
- aFrame->FirstContinuation()->Properties().Get(nsIFrame::IBSplitSibling());
+ aFrame->FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
if (nextContinuation) {
nextContinuation =
- nextContinuation->Properties().Get(nsIFrame::IBSplitSibling());
+ nextContinuation->GetProperty(nsIFrame::IBSplitSibling());
}
}
@@ -1060,14 +1055,52 @@ RestyleManagerBase::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
{
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
"Someone forgot a script blocker");
- if (aChangeList.IsEmpty())
- return NS_OK;
+
+// See bug 1378219 comment 9:
+// Recursive calls here are a bit worrying, but apparently do happen in the
+// wild (although not currently in any of our automated tests). Try to get a
+// stack from Nightly/Dev channel to figure out what's going on and whether
+// it's OK.
+MOZ_DIAGNOSTIC_ASSERT(!mDestroyedFrames, "ProcessRestyledFrames recursion");
+
+if (aChangeList.IsEmpty())
+ return NS_OK;
+
+// If mDestroyedFrames is null, we want to create a new hashtable here
+// and destroy it on exit; but if it is already non-null (because we're in
+// a recursive call), we will continue to use the existing table to
+// accumulate destroyed frames, and NOT clear mDestroyedFrames on exit.
+// We use a MaybeClearDestroyedFrames helper to conditionally reset the
+// mDestroyedFrames pointer when this method returns.
+typedef decltype(mDestroyedFrames) DestroyedFramesT;
+class MOZ_RAII MaybeClearDestroyedFrames
+{
+private:
+ DestroyedFramesT& mDestroyedFramesRef; // ref to caller's mDestroyedFrames
+ const bool mResetOnDestruction;
+public:
+ explicit MaybeClearDestroyedFrames(DestroyedFramesT& aTarget)
+ : mDestroyedFramesRef(aTarget)
+ , mResetOnDestruction(!aTarget) // reset only if target starts out null
+ {
+ }
+ ~MaybeClearDestroyedFrames()
+ {
+ if (mResetOnDestruction) {
+ mDestroyedFramesRef.reset(nullptr);
+ }
+ }
+};
+
+MaybeClearDestroyedFrames maybeClear(mDestroyedFrames);
+if (!mDestroyedFrames) {
+ mDestroyedFrames = MakeUnique<nsTHashtable<nsPtrHashKey<const nsIFrame>>>();
+}
PROFILER_LABEL("RestyleManager", "ProcessRestyledFrames",
js::ProfileEntry::Category::CSS);
nsPresContext* presContext = PresContext();
- FramePropertyTable* propTable = presContext->PropertyTable();
nsCSSFrameConstructor* frameConstructor = presContext->FrameConstructor();
// Handle nsChangeHint_CSSOverflowChange, by either updating the
@@ -1135,15 +1168,6 @@ RestyleManagerBase::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
// processing restyles
frameConstructor->BeginUpdate();
- // Mark frames so that we skip frames that die along the way, bug 123049.
- // A frame can be in the list multiple times with different hints. Further
- // optmization is possible if nsStyleChangeList::AppendChange could coalesce
- for (const nsStyleChangeData& data : aChangeList) {
- if (data.mFrame) {
- propTable->Set(data.mFrame, ChangeListProperty(), true);
- }
- }
-
bool didUpdateCursor = false;
for (const nsStyleChangeData& data : aChangeList) {
@@ -1157,7 +1181,7 @@ RestyleManagerBase::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
"Reflow hint bits set without actually asking for a reflow");
// skip any frame that has been destroyed due to a ripple effect
- if (frame && !propTable->Get(frame, ChangeListProperty())) {
+ if (frame && mDestroyedFrames->Contains(frame)) {
continue;
}
@@ -1409,15 +1433,11 @@ RestyleManagerBase::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
frameConstructor->EndUpdate();
- // cleanup references and verify the style tree. Note that the latter needs
- // to happen once we've processed the whole list, since until then the tree
- // is not in fact in a consistent state.
- for (const nsStyleChangeData& data : aChangeList) {
- if (data.mFrame) {
- propTable->Delete(data.mFrame, ChangeListProperty());
- }
-
#ifdef DEBUG
+ // Verify the style tree. Note that this needs to happen once we've
+ // processed the whole list, since until then the tree is not in fact in a
+ // consistent state.
+ for (const nsStyleChangeData& data : aChangeList) {
// reget frame from content since it may have been regenerated...
if (data.mContent) {
nsIFrame* frame = data.mContent->GetPrimaryFrame();
@@ -1429,8 +1449,8 @@ RestyleManagerBase::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
NS_WARNING("Unable to test style tree integrity -- no content node "
"(and not a viewport frame)");
}
-#endif
}
+#endif
aChangeList.Clear();
return NS_OK;
diff --git a/layout/base/RestyleManagerBase.h b/layout/base/RestyleManagerBase.h
index f81f5e73f5..d92c3d1f73 100644
--- a/layout/base/RestyleManagerBase.h
+++ b/layout/base/RestyleManagerBase.h
@@ -72,6 +72,11 @@ public:
// WillDestroyFrameTree hasn't been called yet.
void NotifyDestroyingFrame(nsIFrame* aFrame) {
mOverflowChangedTracker.RemoveFrame(aFrame);
+ // If ProcessRestyledFrames is tracking frames which have been
+ // destroyed (to avoid re-visiting them), add this one to its set.
+ if (mDestroyedFrames) {
+ mDestroyedFrames->PutEntry(aFrame);
+ }
}
// Note: It's the caller's responsibility to make sure to wrap a
@@ -127,6 +132,12 @@ private:
nsPresContext* mPresContext; // weak, can be null after Disconnect().
uint32_t mRestyleGeneration;
uint32_t mHoverGeneration;
+
+ // Used to keep track of frames that have been destroyed during
+ // ProcessRestyledFrames, so we don't try to touch them again even if
+ // they're referenced again later in the changelist.
+ mozilla::UniquePtr<nsTHashtable<nsPtrHashKey<const nsIFrame>>> mDestroyedFrames;
+
// True if we're already waiting for a refresh notification.
bool mObservingRefreshDriver;
@@ -146,7 +157,7 @@ protected:
GetNearestAncestorFrame(nsIContent* aContent);
static nsIFrame*
- GetNextBlockInInlineSibling(FramePropertyTable* aPropTable, nsIFrame* aFrame);
+ GetNextBlockInInlineSibling(nsIFrame* aFrame);
/**
* Get the next continuation or similar ib-split sibling (assuming
diff --git a/layout/base/moz.build b/layout/base/moz.build
index d3e417f16b..4308a6e4d0 100644
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -61,7 +61,7 @@ EXPORTS += [
'DisplayItemScrollClip.h',
'DisplayListClipState.h',
'FrameLayerBuilder.h',
- 'FramePropertyTable.h',
+ 'FrameProperties.h',
'LayerState.h',
'LayoutLogging.h',
'nsArenaMemoryStats.h',
@@ -126,7 +126,6 @@ UNIFIED_SOURCES += [
'DisplayListClipState.cpp',
'DottedCornerFinder.cpp',
'FrameLayerBuilder.cpp',
- 'FramePropertyTable.cpp',
'GeometryUtils.cpp',
'LayoutLogging.cpp',
'MaskLayerImageCache.cpp',
diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp
index b3c20aabb6..887563504f 100644
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -753,7 +753,6 @@ nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd)
nsIContent* content = nullptr;
int32_t contentTextLength = 0;
- FramePropertyTable* propTable = aBpd->mPresContext->PropertyTable();
nsLineBox* currentLine = nullptr;
#ifdef DEBUG
@@ -809,7 +808,7 @@ nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd)
}
precedingControl = kBidiLevelNone;
lastEmbedingLevel = embeddingLevel;
- propTable->Set(frame, nsIFrame::BidiDataProperty(), bidiData);
+ frame->SetProperty(nsIFrame::BidiDataProperty(), bidiData);
};
for (; ;) {
@@ -1787,7 +1786,7 @@ nsBidiPresUtils::RemoveBidiContinuation(BidiParagraphData *aBpd,
if (frame != NS_BIDI_CONTROL_FRAME) {
// Make the frame and its continuation ancestors fluid,
// so they can be reused or deleted by normal reflow code
- frame->Properties().Set(nsIFrame::BidiDataProperty(), bidiData);
+ frame->SetProperty(nsIFrame::BidiDataProperty(), bidiData);
frame->AddStateBits(NS_FRAME_IS_BIDI);
while (frame) {
nsIFrame* prev = frame->GetPrevContinuation();
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index 07a5b80e77..ec676ca921 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -492,9 +492,8 @@ static nsContainerFrame* GetIBSplitSibling(nsIFrame* aFrame)
// We only store the "ib-split sibling" annotation with the first
// frame in the continuation chain. Walk back to find that frame now.
- return static_cast<nsContainerFrame*>
- (aFrame->FirstContinuation()->
- Properties().Get(nsIFrame::IBSplitSibling()));
+ return aFrame->FirstContinuation()->
+ GetProperty(nsIFrame::IBSplitSibling());
}
static nsContainerFrame* GetIBSplitPrevSibling(nsIFrame* aFrame)
@@ -503,9 +502,8 @@ static nsContainerFrame* GetIBSplitPrevSibling(nsIFrame* aFrame)
// We only store the ib-split sibling annotation with the first
// frame in the continuation chain. Walk back to find that frame now.
- return static_cast<nsContainerFrame*>
- (aFrame->FirstContinuation()->
- Properties().Get(nsIFrame::IBSplitPrevSibling()));
+ return aFrame->FirstContinuation()->
+ GetProperty(nsIFrame::IBSplitPrevSibling());
}
static nsContainerFrame*
@@ -526,7 +524,7 @@ GetLastIBSplitSibling(nsIFrame* aFrame, bool aReturnEmptyTrailingInline)
}
static void
-SetFrameIsIBSplit(nsContainerFrame* aFrame, nsIFrame* aIBSplitSibling)
+SetFrameIsIBSplit(nsContainerFrame* aFrame, nsContainerFrame* aIBSplitSibling)
{
NS_PRECONDITION(aFrame, "bad args!");
@@ -547,9 +545,8 @@ SetFrameIsIBSplit(nsContainerFrame* aFrame, nsIFrame* aIBSplitSibling)
// Store the ib-split sibling (if we were given one) with the
// first frame in the flow.
- FramePropertyTable* props = aFrame->PresContext()->PropertyTable();
- props->Set(aFrame, nsIFrame::IBSplitSibling(), aIBSplitSibling);
- props->Set(aIBSplitSibling, nsIFrame::IBSplitPrevSibling(), aFrame);
+ aFrame->SetProperty(nsIFrame::IBSplitSibling(), aIBSplitSibling);
+ aIBSplitSibling->SetProperty(nsIFrame::IBSplitPrevSibling(), aFrame);
}
}
@@ -6075,11 +6072,11 @@ AddGenConPseudoToFrame(nsIFrame* aOwnerFrame, nsIContent* aContent)
NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aOwnerFrame),
"property should only be set on first continuation/ib-sibling");
- FrameProperties props = aOwnerFrame->Properties();
- nsIFrame::ContentArray* value = props.Get(nsIFrame::GenConProperty());
+ nsIFrame::ContentArray* value =
+ aOwnerFrame->GetProperty(nsIFrame::GenConProperty());
if (!value) {
value = new nsIFrame::ContentArray;
- props.Set(nsIFrame::GenConProperty(), value);
+ aOwnerFrame->SetProperty(nsIFrame::GenConProperty(), value);
}
value->AppendElement(aContent);
}
diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp
index ff9edf7420..119c6c8a2d 100644
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -293,13 +293,13 @@ protected:
if (!prevCont &&
(aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
nsIFrame* block =
- aFrame->Properties().Get(nsIFrame::IBSplitPrevSibling());
+ aFrame->GetProperty(nsIFrame::IBSplitPrevSibling());
if (block) {
// The {ib} properties are only stored on first continuations
NS_ASSERTION(!block->GetPrevContinuation(),
"Incorrect value for IBSplitPrevSibling");
prevCont =
- block->Properties().Get(nsIFrame::IBSplitPrevSibling());
+ block->GetProperty(nsIFrame::IBSplitPrevSibling());
NS_ASSERTION(prevCont, "How did that happen?");
}
}
@@ -313,9 +313,9 @@ protected:
(aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
// The {ib} properties are only stored on first continuations
aFrame = aFrame->FirstContinuation();
- nsIFrame* block = aFrame->Properties().Get(nsIFrame::IBSplitSibling());
+ nsIFrame* block = aFrame->GetProperty(nsIFrame::IBSplitSibling());
if (block) {
- nextCont = block->Properties().Get(nsIFrame::IBSplitSibling());
+ nextCont = block->GetProperty(nsIFrame::IBSplitSibling());
NS_ASSERTION(nextCont, "How did that happen?");
}
}
@@ -842,7 +842,7 @@ static nsRect
GetOutlineInnerRect(nsIFrame* aFrame)
{
nsRect* savedOutlineInnerRect =
- aFrame->Properties().Get(nsIFrame::OutlineInnerRectProperty());
+ aFrame->GetProperty(nsIFrame::OutlineInnerRectProperty());
if (savedOutlineInnerRect)
return *savedOutlineInnerRect;
NS_NOTREACHED("we should have saved a frame property");
diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp
index a55ec1e393..e35e027e30 100644
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -666,7 +666,7 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
// EffectCompositor needs to know that we refused to run this animation
// asynchronously so that it will not throttle the main thread
// animation.
- aFrame->Properties().Set(nsIFrame::RefusedAsyncAnimationProperty(), true);
+ aFrame->SetProperty(nsIFrame::RefusedAsyncAnimationProperty(), true);
// We need to schedule another refresh driver run so that EffectCompositor
// gets a chance to unthrottle the animation.
@@ -902,15 +902,13 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
const DisplayItemClip* oldClip = mClipState.GetClipForContainingBlockDescendants();
const DisplayItemScrollClip* sc = mClipState.GetCurrentInnermostScrollClip();
OutOfFlowDisplayData* data = new OutOfFlowDisplayData(oldClip, sc, dirty);
- aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data);
+ aFrame->SetProperty(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data);
MarkFrameForDisplay(aFrame, aDirtyFrame);
}
static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
- nsPresContext* presContext = aFrame->PresContext();
- presContext->PropertyTable()->
- Delete(aFrame, nsDisplayListBuilder::OutOfFlowDisplayDataProperty());
+ aFrame->DeleteProperty(nsDisplayListBuilder::OutOfFlowDisplayDataProperty());
for (nsIFrame* f = aFrame; f;
f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) {
diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h
index fcdc9e4fc0..c81d34fac2 100644
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -1003,7 +1003,7 @@ public:
static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame)
{
- return aFrame->Properties().Get(OutOfFlowDisplayDataProperty());
+ return aFrame->GetProperty(OutOfFlowDisplayDataProperty());
}
nsPresContext* CurrentPresContext() {
diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h
index 4016cc0a99..865f5534c6 100644
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -1533,11 +1533,12 @@ public:
bool aFlushOnHoverChange) = 0;
virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
- nsArenaMemoryStats *aArenaObjectsSize,
- size_t *aPresShellSize,
- size_t *aStyleSetsSize,
- size_t *aTextRunsSize,
- size_t *aPresContextSize) = 0;
+ nsArenaMemoryStats* aArenaObjectsSize,
+ size_t* aPresShellSize,
+ size_t* aStyleSetsSize,
+ size_t* aTextRunsSize,
+ size_t* aPresContextSize,
+ size_t* aFramePropertiesSize) = 0;
/**
* Methods that retrieve the cached font inflation preferences.
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
index 07befdc812..06690b208b 100644
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2057,13 +2057,13 @@ NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(ScrollbarThumbLayerized, bool)
/* static */ void
nsLayoutUtils::SetScrollbarThumbLayerization(nsIFrame* aThumbFrame, bool aLayerize)
{
- aThumbFrame->Properties().Set(ScrollbarThumbLayerized(), aLayerize);
+ aThumbFrame->SetProperty(ScrollbarThumbLayerized(), aLayerize);
}
bool
nsLayoutUtils::IsScrollbarThumbLayerized(nsIFrame* aThumbFrame)
{
- return aThumbFrame->Properties().Get(ScrollbarThumbLayerized());
+ return aThumbFrame->GetProperty(ScrollbarThumbLayerized());
}
// static
@@ -4427,7 +4427,7 @@ nsLayoutUtils::GetNextContinuationOrIBSplitSibling(nsIFrame *aFrame)
// frame in the continuation chain. Walk back to find that frame now.
aFrame = aFrame->FirstContinuation();
- return aFrame->Properties().Get(nsIFrame::IBSplitSibling());
+ return aFrame->GetProperty(nsIFrame::IBSplitSibling());
}
return nullptr;
@@ -4440,7 +4440,7 @@ nsLayoutUtils::FirstContinuationOrIBSplitSibling(nsIFrame *aFrame)
if (result->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) {
while (true) {
nsIFrame* f =
- result->Properties().Get(nsIFrame::IBSplitPrevSibling());
+ result->GetProperty(nsIFrame::IBSplitPrevSibling());
if (!f)
break;
result = f;
@@ -4456,10 +4456,10 @@ nsLayoutUtils::LastContinuationOrIBSplitSibling(nsIFrame *aFrame)
nsIFrame *result = aFrame->FirstContinuation();
if (result->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) {
while (true) {
- nsIFrame* f =
- result->Properties().Get(nsIFrame::IBSplitSibling());
- if (!f)
+ nsIFrame* f = result->GetProperty(nsIFrame::IBSplitSibling());
+ if (!f) {
break;
+ }
result = f;
}
}
@@ -4476,7 +4476,7 @@ nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(nsIFrame *aFrame)
return false;
}
if ((aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
- aFrame->Properties().Get(nsIFrame::IBSplitPrevSibling())) {
+ aFrame->GetProperty(nsIFrame::IBSplitPrevSibling())) {
return false;
}
diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp
index 3106ff3868..befb5deb2e 100644
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2741,8 +2741,7 @@ nsPresContext::GetPrimaryFrameFor(nsIContent* aContent)
size_t
nsPresContext::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
- return mPropertyTable.SizeOfExcludingThis(aMallocSizeOf) +
- mLangGroupFontPrefs.SizeOfExcludingThis(aMallocSizeOf);
+ return mLangGroupFontPrefs.SizeOfExcludingThis(aMallocSizeOf);
// Measurement of other members may be added later if DMD finds it is
// worthwhile.
diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h
index d8f876291c..a2b9bb5337 100644
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -22,7 +22,6 @@
#include "nsITimer.h"
#include "nsCRT.h"
#include "nsIWidgetListener.h"
-#include "FramePropertyTable.h"
#include "nsGkAtoms.h"
#include "nsCycleCollectionParticipant.h"
#include "nsChangeHint.h"
@@ -140,7 +139,6 @@ class nsRootPresContext;
class nsPresContext : public nsIObserver,
public mozilla::SupportsWeakPtr<nsPresContext> {
public:
- typedef mozilla::FramePropertyTable FramePropertyTable;
typedef mozilla::LangGroupFontPrefs LangGroupFontPrefs;
typedef mozilla::ScrollbarStyles ScrollbarStyles;
typedef mozilla::StaticPresData StaticPresData;
@@ -867,9 +865,6 @@ public:
nsIPrintSettings* GetPrintSettings() { return mPrintSettings; }
- /* Accessor for table of frame properties */
- FramePropertyTable* PropertyTable() { return &mPropertyTable; }
-
/* Helper function that ensures that this prescontext is shown in its
docshell if it's the most recent prescontext for the docshell. Returns
whether the prescontext is now being shown.
@@ -1064,11 +1059,6 @@ public:
*/
nsIFrame* GetPrimaryFrameFor(nsIContent* aContent);
- void NotifyDestroyingFrame(nsIFrame* aFrame)
- {
- PropertyTable()->DeleteAllFor(aFrame);
- }
-
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
@@ -1294,7 +1284,6 @@ protected:
nsCOMPtr<nsIPrintSettings> mPrintSettings;
nsCOMPtr<nsITimer> mPrefChangedTimer;
- FramePropertyTable mPropertyTable;
nsInvalidateRequestList mInvalidateRequestsSinceLastPaint;
nsInvalidateRequestList mUndeliveredInvalidateRequestsBeforeLastPaint;
diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp
index d4fbebbf2f..dacc6603b5 100644
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1306,19 +1306,6 @@ PresShell::Destroy()
// Destroy the frame manager. This will destroy the frame hierarchy
mFrameConstructor->WillDestroyFrameTree();
- // Destroy all frame properties (whose destruction was suppressed
- // while destroying the frame tree, but which might contain more
- // frames within the properties.
- if (mPresContext) {
- // Clear out the prescontext's property table -- since our frame tree is
- // now dead, we shouldn't be looking up any more properties in that table.
- // We want to do this before we call DetachShell() on the prescontext, so
- // property destructors can usefully call GetPresShell() on the
- // prescontext.
- mPresContext->PropertyTable()->DeleteAll();
- }
-
-
NS_WARNING_ASSERTION(!mWeakFrames,
"Weak frames alive after destroying FrameManager");
while (mWeakFrames) {
@@ -2047,7 +2034,7 @@ PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
}
// Remove frame properties
- mPresContext->NotifyDestroyingFrame(aFrame);
+ aFrame->DeleteAllProperties();
if (aFrame == mCurrentEventFrame) {
mCurrentEventContent = aFrame->GetContent();
@@ -2076,8 +2063,7 @@ PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
// frame from FrameLayerBuilder::DisplayItemData::mFrameList -- otherwise
// the DisplayItemData destructor will use the destroyed frame when it
// tries to remove it from the (array) value of this property.
- mPresContext->PropertyTable()->
- Delete(aFrame, FrameLayerBuilder::LayerManagerDataProperty());
+ aFrame->DeleteProperty( FrameLayerBuilder::LayerManagerDataProperty());
}
}
@@ -10929,11 +10915,12 @@ PresShell::GetRootPresShell()
void
PresShell::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
- nsArenaMemoryStats *aArenaObjectsSize,
- size_t *aPresShellSize,
- size_t *aStyleSetsSize,
- size_t *aTextRunsSize,
- size_t *aPresContextSize)
+ nsArenaMemoryStats* aArenaObjectsSize,
+ size_t* aPresShellSize,
+ size_t* aStyleSetsSize,
+ size_t* aTextRunsSize,
+ size_t* aPresContextSize,
+ size_t* aFramePropertiesSize)
{
mFrameArena.AddSizeOfExcludingThis(aMallocSizeOf, aArenaObjectsSize);
*aPresShellSize += aMallocSizeOf(this);
@@ -10953,6 +10940,12 @@ PresShell::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
*aTextRunsSize += SizeOfTextRuns(aMallocSizeOf);
*aPresContextSize += mPresContext->SizeOfIncludingThis(aMallocSizeOf);
+
+ nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
+ if (rootFrame) {
+ *aFramePropertiesSize +=
+ rootFrame->SizeOfFramePropertiesForTree(aMallocSizeOf);
+ }
}
size_t
diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h
index 1a8dd3fefa..10548880a9 100644
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -384,11 +384,12 @@ public:
virtual void LoadComplete() override;
void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
- nsArenaMemoryStats *aArenaObjectsSize,
- size_t *aPresShellSize,
- size_t *aStyleSetsSize,
- size_t *aTextRunsSize,
- size_t *aPresContextSize) override;
+ nsArenaMemoryStats* aArenaObjectsSize,
+ size_t* aPresShellSize,
+ size_t* aStyleSetsSize,
+ size_t* aTextRunsSize,
+ size_t* aPresContextSize,
+ size_t* aFramePropertiesSize) override;
size_t SizeOfTextRuns(mozilla::MallocSizeOf aMallocSizeOf) const;
virtual void AddInvalidateHiddenPresShellObserver(nsRefreshDriver *aDriver) override;