mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
Bug 1331718 - Part 3: Store pointers to DisplayItemData directly on nsIFrame. r=mattwoodrow r=dbaron
This patch aims to speed up the lookup and storage of DisplayItemData objects, by removing a level of indirection and preventing the previously required hashtable lookup in order to access these. Instead it stores an array of pointers on each frame that allows direct access to the DisplayItemData object by dereferencing the frame. Since most frames get either 1 or 2 DisplayItemData objects attached to them a specialized class is used that is of minimal size (2 * sizeof(void)) and that performs well for sizes 1 or 2. MozReview-Commit-ID: HONKAmpk5H8
This commit is contained in:
parent
5a025e5c1f
commit
dafd50f856
@ -2078,6 +2078,12 @@ PresShell::SetIgnoreFrameDestruction(bool aIgnore)
|
||||
void
|
||||
PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
|
||||
{
|
||||
// We must remove these from FrameLayerBuilder::DisplayItemData::mFrameList here,
|
||||
// otherwise the DisplayItemData destructor will use the destroyed frame when it
|
||||
// tries to remove it from the (array) value of this property.
|
||||
FrameLayerBuilder::RemoveFrameFromLayerManager(aFrame, aFrame->DisplayItemData());
|
||||
aFrame->DisplayItemData().Clear();
|
||||
|
||||
if (!mIgnoreFrameDestruction) {
|
||||
mDocument->StyleImageLoader()->DropRequestsForFrame(aFrame);
|
||||
|
||||
@ -2115,13 +2121,6 @@ PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
|
||||
}
|
||||
|
||||
mFramesToDirty.RemoveEntry(aFrame);
|
||||
} else {
|
||||
// We must delete this property in situ so that its destructor removes the
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "FramePropertyTable.h"
|
||||
#include "mozilla/layout/FrameChildList.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/SmallPointerArray.h"
|
||||
#include "mozilla/WritingModes.h"
|
||||
#include "nsDirection.h"
|
||||
#include "nsFrameList.h"
|
||||
@ -98,6 +99,7 @@ class EventStates;
|
||||
struct ReflowInput;
|
||||
class ReflowOutput;
|
||||
class ServoStyleSet;
|
||||
class DisplayItemData;
|
||||
|
||||
namespace layers {
|
||||
class Layer;
|
||||
@ -599,6 +601,7 @@ public:
|
||||
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
|
||||
typedef mozilla::Sides Sides;
|
||||
typedef mozilla::LogicalSides LogicalSides;
|
||||
typedef mozilla::SmallPointerArray<mozilla::DisplayItemData> DisplayItemArray;
|
||||
|
||||
NS_DECL_QUERYFRAME_TARGET(nsIFrame)
|
||||
|
||||
@ -3718,7 +3721,11 @@ public:
|
||||
nscoord aBoxSizingToMarginEdge,
|
||||
const nsStyleCoord& aCoord,
|
||||
ComputeSizeFlags aFlags = eDefault);
|
||||
|
||||
DisplayItemArray& DisplayItemData() { return mDisplayItemData; }
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Reparent this frame's view if it has one.
|
||||
*/
|
||||
@ -3734,6 +3741,7 @@ private:
|
||||
nsContainerFrame* mParent;
|
||||
nsIFrame* mNextSibling; // doubly-linked list of frames
|
||||
nsIFrame* mPrevSibling; // Do not touch outside SetNextSibling!
|
||||
DisplayItemArray mDisplayItemData;
|
||||
|
||||
void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect);
|
||||
|
||||
|
@ -167,13 +167,8 @@ DisplayItemData::AddFrame(nsIFrame* aFrame)
|
||||
MOZ_RELEASE_ASSERT(mLayer);
|
||||
mFrameList.AppendElement(aFrame);
|
||||
|
||||
nsTArray<DisplayItemData*>* array =
|
||||
aFrame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty());
|
||||
if (!array) {
|
||||
array = new nsTArray<DisplayItemData*>();
|
||||
aFrame->Properties().Set(FrameLayerBuilder::LayerManagerDataProperty(), array);
|
||||
}
|
||||
array->AppendElement(this);
|
||||
SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
|
||||
array.AppendElement(this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -183,10 +178,8 @@ DisplayItemData::RemoveFrame(nsIFrame* aFrame)
|
||||
bool result = mFrameList.RemoveElement(aFrame);
|
||||
MOZ_RELEASE_ASSERT(result, "Can't remove a frame that wasn't added!");
|
||||
|
||||
nsTArray<DisplayItemData*>* array =
|
||||
aFrame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty());
|
||||
MOZ_RELEASE_ASSERT(array, "Must be already stored on the frame!");
|
||||
array->RemoveElement(this);
|
||||
SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
|
||||
array.RemoveElement(this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -270,9 +263,8 @@ DisplayItemData::~DisplayItemData()
|
||||
if (frame == sDestroyedFrame) {
|
||||
continue;
|
||||
}
|
||||
nsTArray<DisplayItemData*> *array =
|
||||
reinterpret_cast<nsTArray<DisplayItemData*>*>(frame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty()));
|
||||
array->RemoveElement(this);
|
||||
SmallPointerArray<DisplayItemData>& array = frame->DisplayItemData();
|
||||
array.RemoveElement(this);
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas && sAliveDisplayItemDatas->Contains(this));
|
||||
@ -402,8 +394,8 @@ public:
|
||||
/* static */ void
|
||||
FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame)
|
||||
{
|
||||
FrameProperties props = aFrame->Properties();
|
||||
props.Delete(LayerManagerDataProperty());
|
||||
RemoveFrameFromLayerManager(aFrame, aFrame->DisplayItemData());
|
||||
aFrame->DisplayItemData().Clear();
|
||||
}
|
||||
|
||||
struct AssignedDisplayItem
|
||||
@ -1817,17 +1809,14 @@ FrameLayerBuilder::FlashPaint(gfxContext *aContext)
|
||||
DisplayItemData*
|
||||
FrameLayerBuilder::GetDisplayItemData(nsIFrame* aFrame, uint32_t aKey)
|
||||
{
|
||||
const nsTArray<DisplayItemData*>* array =
|
||||
aFrame->Properties().Get(LayerManagerDataProperty());
|
||||
if (array) {
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
DisplayItemData* item = DisplayItemData::AssertDisplayItemData(array->ElementAt(i));
|
||||
const SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
DisplayItemData* item = DisplayItemData::AssertDisplayItemData(array.ElementAt(i));
|
||||
if (item->mDisplayItemKey == aKey &&
|
||||
item->mLayer->Manager() == mRetainingManager) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1925,7 +1914,7 @@ GetTranslationForPaintedLayer(PaintedLayer* aLayer)
|
||||
|
||||
/* static */ void
|
||||
FrameLayerBuilder::RemoveFrameFromLayerManager(const nsIFrame* aFrame,
|
||||
nsTArray<DisplayItemData*>* aArray)
|
||||
SmallPointerArray<DisplayItemData>& aArray)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!sDestroyedFrame);
|
||||
sDestroyedFrame = aFrame;
|
||||
@ -1933,7 +1922,7 @@ FrameLayerBuilder::RemoveFrameFromLayerManager(const nsIFrame* aFrame,
|
||||
// Hold a reference to all the items so that they don't get
|
||||
// deleted from under us.
|
||||
nsTArray<RefPtr<DisplayItemData> > arrayCopy;
|
||||
for (DisplayItemData* data : *aArray) {
|
||||
for (DisplayItemData* data : aArray) {
|
||||
arrayCopy.AppendElement(data);
|
||||
}
|
||||
|
||||
@ -1948,7 +1937,7 @@ FrameLayerBuilder::RemoveFrameFromLayerManager(const nsIFrame* aFrame,
|
||||
}
|
||||
#endif
|
||||
|
||||
for (DisplayItemData* data : *aArray) {
|
||||
for (DisplayItemData* data : aArray) {
|
||||
PaintedLayer* t = data->mLayer->AsPaintedLayer();
|
||||
if (t) {
|
||||
PaintedDisplayItemLayerUserData* paintedData =
|
||||
@ -1966,7 +1955,6 @@ FrameLayerBuilder::RemoveFrameFromLayerManager(const nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
arrayCopy.Clear();
|
||||
delete aArray;
|
||||
sDestroyedFrame = nullptr;
|
||||
}
|
||||
|
||||
@ -2047,46 +2035,38 @@ FrameLayerBuilder::WillEndTransaction()
|
||||
FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
const nsTArray<DisplayItemData*>* array =
|
||||
aItem->Frame()->Properties().Get(LayerManagerDataProperty());
|
||||
if (array) {
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
DisplayItemData* item = DisplayItemData::AssertDisplayItemData(array->ElementAt(i));
|
||||
const SmallPointerArray<DisplayItemData>& array =
|
||||
aItem->Frame()->DisplayItemData();
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
DisplayItemData* item = DisplayItemData::AssertDisplayItemData(array.ElementAt(i));
|
||||
if (item->mDisplayItemKey == aItem->GetPerFrameKey() &&
|
||||
item->mLayer->Manager() == aManager) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
FrameLayerBuilder::HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
|
||||
{
|
||||
const nsTArray<DisplayItemData*>* array =
|
||||
aFrame->Properties().Get(LayerManagerDataProperty());
|
||||
if (array) {
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
if (DisplayItemData::AssertDisplayItemData(array->ElementAt(i))->mDisplayItemKey == aDisplayItemKey) {
|
||||
const SmallPointerArray<DisplayItemData>& array =
|
||||
aFrame->DisplayItemData();
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
if (DisplayItemData::AssertDisplayItemData(array.ElementAt(i))->mDisplayItemKey == aDisplayItemKey) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
FrameLayerBuilder::IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback)
|
||||
{
|
||||
const nsTArray<DisplayItemData*>* array =
|
||||
aFrame->Properties().Get(LayerManagerDataProperty());
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
const SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
|
||||
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
DisplayItemData* data = DisplayItemData::AssertDisplayItemData(array->ElementAt(i));
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
DisplayItemData* data = DisplayItemData::AssertDisplayItemData(array.ElementAt(i));
|
||||
if (data->mDisplayItemKey != nsDisplayItem::TYPE_ZERO) {
|
||||
aCallback(aFrame, data);
|
||||
}
|
||||
@ -2146,15 +2126,10 @@ FrameLayerBuilder::ClearCachedGeometry(nsDisplayItem* aItem)
|
||||
/* static */ Layer*
|
||||
FrameLayerBuilder::GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
|
||||
{
|
||||
const nsTArray<DisplayItemData*>* array =
|
||||
aFrame->Properties().Get(LayerManagerDataProperty());
|
||||
const SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
|
||||
|
||||
if (!array) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
DisplayItemData *data = DisplayItemData::AssertDisplayItemData(array->ElementAt(i));
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
DisplayItemData *data = DisplayItemData::AssertDisplayItemData(array.ElementAt(i));
|
||||
|
||||
if (data->mDisplayItemKey == aDisplayItemKey) {
|
||||
return data->mLayer;
|
||||
@ -5799,12 +5774,10 @@ FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
|
||||
/* static */ void
|
||||
FrameLayerBuilder::InvalidateAllLayersForFrame(nsIFrame *aFrame)
|
||||
{
|
||||
const nsTArray<DisplayItemData*>* array =
|
||||
aFrame->Properties().Get(LayerManagerDataProperty());
|
||||
if (array) {
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
DisplayItemData::AssertDisplayItemData(array->ElementAt(i))->mParent->mInvalidateAllLayers = true;
|
||||
}
|
||||
const SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
|
||||
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
DisplayItemData::AssertDisplayItemData(array.ElementAt(i))->mParent->mInvalidateAllLayers = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5816,11 +5789,10 @@ FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey)
|
||||
// in the normal widget manager, and as a different layer (or no layer)
|
||||
// in the secondary manager
|
||||
|
||||
const nsTArray<DisplayItemData*>* array =
|
||||
aFrame->Properties().Get(LayerManagerDataProperty());
|
||||
if (array) {
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
DisplayItemData *element = DisplayItemData::AssertDisplayItemData(array->ElementAt(i));
|
||||
const SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();;
|
||||
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
DisplayItemData *element = DisplayItemData::AssertDisplayItemData(array.ElementAt(i));
|
||||
if (!element->mParent->mLayerManager->IsWidgetLayerManager()) {
|
||||
continue;
|
||||
}
|
||||
@ -5829,6 +5801,7 @@ FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey)
|
||||
return element->mOptLayer;
|
||||
}
|
||||
|
||||
|
||||
Layer* layer = element->mLayer;
|
||||
if (!layer->HasUserData(&gColorLayerUserData) &&
|
||||
!layer->HasUserData(&gImageLayerUserData) &&
|
||||
@ -5837,7 +5810,6 @@ FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -5872,14 +5844,10 @@ FrameLayerBuilder::GetPaintedLayerScaleForFrame(nsIFrame* aFrame)
|
||||
break;
|
||||
}
|
||||
|
||||
const nsTArray<DisplayItemData*>* array =
|
||||
f->Properties().Get(LayerManagerDataProperty());
|
||||
if (!array) {
|
||||
continue;
|
||||
}
|
||||
const SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
|
||||
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
Layer* layer = DisplayItemData::AssertDisplayItemData(array->ElementAt(i))->mLayer;
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
Layer* layer = DisplayItemData::AssertDisplayItemData(array.ElementAt(i))->mLayer;
|
||||
ContainerLayer* container = layer->AsContainerLayer();
|
||||
if (!container ||
|
||||
!layer->Manager()->IsWidgetLayerManager()) {
|
||||
@ -6306,20 +6274,15 @@ FrameLayerBuilder::DumpRetainedLayerTree(LayerManager* aManager, std::stringstre
|
||||
nsDisplayItemGeometry*
|
||||
FrameLayerBuilder::GetMostRecentGeometry(nsDisplayItem* aItem)
|
||||
{
|
||||
typedef nsTArray<DisplayItemData*> DataArray;
|
||||
typedef SmallPointerArray<DisplayItemData> DataArray;
|
||||
|
||||
// Retrieve the array of DisplayItemData associated with our frame.
|
||||
FrameProperties properties = aItem->Frame()->Properties();
|
||||
const DataArray* dataArray =
|
||||
properties.Get(LayerManagerDataProperty());
|
||||
if (!dataArray) {
|
||||
return nullptr;
|
||||
}
|
||||
const DataArray& dataArray = aItem->Frame()->DisplayItemData();
|
||||
|
||||
// Find our display item data, if it exists, and return its geometry.
|
||||
uint32_t itemPerFrameKey = aItem->GetPerFrameKey();
|
||||
for (uint32_t i = 0; i < dataArray->Length(); i++) {
|
||||
DisplayItemData* data = DisplayItemData::AssertDisplayItemData(dataArray->ElementAt(i));
|
||||
for (uint32_t i = 0; i < dataArray.Length(); i++) {
|
||||
DisplayItemData* data = DisplayItemData::AssertDisplayItemData(dataArray.ElementAt(i));
|
||||
if (data->GetDisplayItemKey() == itemPerFrameKey) {
|
||||
return data->GetGeometry();
|
||||
}
|
||||
|
@ -518,15 +518,10 @@ public:
|
||||
static T*
|
||||
GetDebugSingleOldLayerForFrame(nsIFrame* aFrame)
|
||||
{
|
||||
const nsTArray<DisplayItemData*>* array =
|
||||
aFrame->Properties().Get(LayerManagerDataProperty());
|
||||
|
||||
if (!array) {
|
||||
return nullptr;
|
||||
}
|
||||
SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
|
||||
|
||||
Layer* layer = nullptr;
|
||||
for (DisplayItemData* data : *array) {
|
||||
for (DisplayItemData* data : array) {
|
||||
DisplayItemData::AssertDisplayItemData(data);
|
||||
if (data->mLayer->GetType() != T::Type()) {
|
||||
continue;
|
||||
@ -593,16 +588,13 @@ public:
|
||||
*/
|
||||
void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer);
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty,
|
||||
nsTArray<DisplayItemData*>,
|
||||
RemoveFrameFromLayerManager)
|
||||
static void RemoveFrameFromLayerManager(const nsIFrame* aFrame,
|
||||
SmallPointerArray<DisplayItemData>& aArray);
|
||||
|
||||
protected:
|
||||
|
||||
friend class LayerManagerData;
|
||||
|
||||
static void RemoveFrameFromLayerManager(const nsIFrame* aFrame,
|
||||
nsTArray<DisplayItemData*>* aArray);
|
||||
|
||||
/**
|
||||
* Given a frame and a display item key that uniquely identifies a
|
||||
* display item for the frame, find the layer that was last used to
|
||||
|
Loading…
Reference in New Issue
Block a user