зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
e8f8394b4e
Коммит
70d011d12c
|
@ -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,15 +1809,12 @@ 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));
|
||||
if (item->mDisplayItemKey == aKey &&
|
||||
item->mLayer->Manager() == mRetainingManager) {
|
||||
return item;
|
||||
}
|
||||
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,15 +2035,13 @@ 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));
|
||||
if (item->mDisplayItemKey == aItem->GetPerFrameKey() &&
|
||||
item->mLayer->Manager() == aManager) {
|
||||
return item;
|
||||
}
|
||||
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;
|
||||
|
@ -2064,13 +2050,11 @@ FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem,
|
|||
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) {
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
|
@ -2079,14 +2063,10 @@ FrameLayerBuilder::HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey
|
|||
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,25 +5789,24 @@ 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));
|
||||
if (!element->mParent->mLayerManager->IsWidgetLayerManager()) {
|
||||
continue;
|
||||
}
|
||||
if (element->mDisplayItemKey == aDisplayItemKey) {
|
||||
if (element->mOptLayer) {
|
||||
return element->mOptLayer;
|
||||
}
|
||||
const SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();;
|
||||
|
||||
Layer* layer = element->mLayer;
|
||||
if (!layer->HasUserData(&gColorLayerUserData) &&
|
||||
!layer->HasUserData(&gImageLayerUserData) &&
|
||||
!layer->HasUserData(&gPaintedDisplayItemLayerUserData)) {
|
||||
return layer;
|
||||
}
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
DisplayItemData *element = DisplayItemData::AssertDisplayItemData(array.ElementAt(i));
|
||||
if (!element->mParent->mLayerManager->IsWidgetLayerManager()) {
|
||||
continue;
|
||||
}
|
||||
if (element->mDisplayItemKey == aDisplayItemKey) {
|
||||
if (element->mOptLayer) {
|
||||
return element->mOptLayer;
|
||||
}
|
||||
|
||||
|
||||
Layer* layer = element->mLayer;
|
||||
if (!layer->HasUserData(&gColorLayerUserData) &&
|
||||
!layer->HasUserData(&gImageLayerUserData) &&
|
||||
!layer->HasUserData(&gPaintedDisplayItemLayerUserData)) {
|
||||
return layer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче