Bug 1422057 - Deduplicate DisplayItemClipChain instances on creation. r?mstange
MozReview-Commit-ID: Fdr0m0uKxKR
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -1432,16 +1432,17 @@ nsDisplayListBuilder::FreeClipChains()
// iteration), so that we destroy descendants first which
// will drop the ref count on their ancestors.
auto it = mClipChainsToDestroy.begin();
while(it != mClipChainsToDestroy.end()) {
DisplayItemClipChain* clip = *it;
if (!clip->mRefCount) {
+ mClipDeduplicator.erase(clip);
it = mClipChainsToDestroy.erase(it);
clip->DisplayItemClipChain::~DisplayItemClipChain();
Destroy(DisplayItemType::TYPE_ZERO, clip);
} else {
++it;
}
}
}
@@ -1591,16 +1592,27 @@ nsDisplayListBuilder::AllocateActiveScro
const DisplayItemClipChain*
nsDisplayListBuilder::AllocateDisplayItemClipChain(const DisplayItemClip& aClip,
const ActiveScrolledRoot* aASR,
const DisplayItemClipChain* aParent)
{
void* p = Allocate(sizeof(DisplayItemClipChain), DisplayItemType::TYPE_ZERO);
DisplayItemClipChain* c = new (KnownNotNull, p) DisplayItemClipChain(aClip, aASR, aParent);
+ auto result = mClipDeduplicator.insert(c);
+ if (!result.second) {
+ // An equivalent clip chain item was already created, so let's return that
+ // instead. Destroy the one we just created.
+ // Note that this can cause clip chains from different coordinate systems to
+ // collapse into the same clip chain object, because clip chains do not keep
+ // track of the reference frame that they were created in.
+ c->DisplayItemClipChain::~DisplayItemClipChain();
+ Destroy(DisplayItemType::TYPE_ZERO, c);
+ return *(result.first);
+ }
mClipChainsToDestroy.emplace_front(c);
return c;
}
struct ClipChainItem {
DisplayItemClip clip;
const ActiveScrolledRoot* asr;
};
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -24,16 +24,17 @@
#include "mozilla/Maybe.h"
#include "mozilla/TemplateLib.h" // mozilla::tl::Max
#include "nsCOMPtr.h"
#include "nsContainerFrame.h"
#include "nsPoint.h"
#include "nsRect.h"
#include "nsRegion.h"
#include "nsDisplayListInvalidation.h"
+#include "DisplayItemClipChain.h"
#include "DisplayListClipState.h"
#include "LayerState.h"
#include "FrameMetrics.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/gfx/UserData.h"
@@ -413,16 +414,18 @@ class nsDisplayListBuilder {
* to AGR_YES without restyling is possible.
*/
enum AGRState { AGR_NO, AGR_YES, AGR_MAYBE };
public:
typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
typedef mozilla::DisplayItemClip DisplayItemClip;
typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
+ typedef mozilla::DisplayItemClipChainHasher DisplayItemClipChainHasher;
+ typedef mozilla::DisplayItemClipChainEqualer DisplayItemClipChainEqualer;
typedef mozilla::DisplayListClipState DisplayListClipState;
typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
typedef nsIWidget::ThemeGeometry ThemeGeometry;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::FrameMetrics::ViewID ViewID;
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
@@ -1843,16 +1846,20 @@ private:
nsDisplayItem* mGlassDisplayItem;
// A temporary list that we append scroll info items to while building
// display items for the contents of frames with SVG effects.
// Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
// This is a pointer and not a real nsDisplayList value because the
// nsDisplayList class is defined below this class, so we can't use it here.
nsDisplayList* mScrollInfoItemsForHoisting;
nsTArray<RefPtr<ActiveScrolledRoot>> mActiveScrolledRoots;
+ std::unordered_set<
+ const DisplayItemClipChain*,
+ DisplayItemClipChainHasher,
+ DisplayItemClipChainEqualer> mClipDeduplicator;
std::list<DisplayItemClipChain*> mClipChainsToDestroy;
nsTArray<nsDisplayItem*> mTemporaryItems;
const ActiveScrolledRoot* mActiveScrolledRootForRootScrollframe;
nsDisplayListBuilderMode mMode;
ViewID mCurrentScrollParentId;
ViewID mCurrentScrollbarTarget;
nsDisplayOwnLayerFlags mCurrentScrollbarFlags;
Preserves3DContext mPreserves3DCtx;