From 570cad82795beeb1eb7011c09be295afa11373ce Mon Sep 17 00:00:00 2001 From: win7-7 Date: Mon, 8 Jul 2019 19:19:56 +0300 Subject: Iterate the frame property list once to collect which child list properties we have Look into optimizing out the hashtable lookups from nsContainerFrame --- layout/generic/nsContainerFrame.cpp | 89 ++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 36 deletions(-) (limited to 'layout/generic/nsContainerFrame.cpp') diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index 2933ac4cf..abf687c9b 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -219,24 +219,49 @@ nsContainerFrame::DestroyFrom(nsIFrame* aDestructRoot) // Destroy frames on the principal child list. mFrames.DestroyFramesFrom(aDestructRoot); + + if (MOZ_UNLIKELY(!mProperties.IsEmpty())) { + using T = mozilla::FrameProperties::UntypedDescriptor; + bool hasO = false, hasOC = false, hasEOC = false, hasBackdrop = false; + mProperties.ForEach([&] (const T& aProp, void*) { + if (aProp == OverflowProperty()) { + hasO = true; + } else if (aProp == OverflowContainersProperty()) { + hasOC = true; + } else if (aProp == ExcessOverflowContainersProperty()) { + hasEOC = true; + } else if (aProp == BackdropProperty()) { + hasBackdrop = true; + } + return true; + }); + // Destroy frames on the auxiliary frame lists and delete the lists. nsPresContext* pc = PresContext(); nsIPresShell* shell = pc->PresShell(); - SafelyDestroyFrameListProp(aDestructRoot, shell, OverflowProperty()); + if (hasO) { + SafelyDestroyFrameListProp(aDestructRoot, shell, OverflowProperty()); + } - MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers) || - !(GetProperty(nsContainerFrame::OverflowContainersProperty()) || - GetProperty(nsContainerFrame::ExcessOverflowContainersProperty())), - "this type of frame should't have overflow containers"); - SafelyDestroyFrameListProp(aDestructRoot, shell, - OverflowContainersProperty()); - SafelyDestroyFrameListProp(aDestructRoot, shell, - ExcessOverflowContainersProperty()); + MOZ_ASSERT(IsFrameOfType(eCanContainOverflowContainers) || + !(hasOC || hasEOC), + "this type of frame shouldn't have overflow containers"); + if (hasOC) { + SafelyDestroyFrameListProp(aDestructRoot, shell, + OverflowContainersProperty()); + } + if (hasEOC) { + SafelyDestroyFrameListProp(aDestructRoot, shell, + ExcessOverflowContainersProperty()); + } MOZ_ASSERT(!GetProperty(BackdropProperty()) || StyleDisplay()->mTopLayer != NS_STYLE_TOP_LAYER_NONE, "only top layer frame may have backdrop"); - SafelyDestroyFrameListProp(aDestructRoot, shell, BackdropProperty()); + if (hasBackdrop) { + SafelyDestroyFrameListProp(aDestructRoot, shell, BackdropProperty()); + } +} nsSplittableFrame::DestroyFrom(aDestructRoot); } @@ -274,36 +299,28 @@ nsContainerFrame::GetChildList(ChildListID aListID) const } } -static void -AppendIfNonempty(const nsIFrame* aFrame, - nsContainerFrame::FrameListPropertyDescriptor aProperty, - nsTArray* aLists, - nsIFrame::ChildListID aListID) -{ - if (nsFrameList* list = aFrame->GetProperty(aProperty)) { - list->AppendIfNonempty(aLists, aListID); - } -} - void nsContainerFrame::GetChildLists(nsTArray* aLists) const { mFrames.AppendIfNonempty(aLists, kPrincipalList); - ::AppendIfNonempty(this, OverflowProperty(), - aLists, kOverflowList); - if (IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) { - ::AppendIfNonempty(this, OverflowContainersProperty(), - aLists, kOverflowContainersList); - ::AppendIfNonempty(this, ExcessOverflowContainersProperty(), - aLists, kExcessOverflowContainersList); - } - // Bypass BackdropProperty hashtable lookup for any in-flow frames - // since frames in the top layer (only which can have backdrop) are - // definitely out-of-flow. - if (GetStateBits() & NS_FRAME_OUT_OF_FLOW) { - ::AppendIfNonempty(this, BackdropProperty(), - aLists, kBackdropList); - } + using T = mozilla::FrameProperties::UntypedDescriptor; + mProperties.ForEach([this, aLists] (const T& aProp, void* aValue) { + typedef const nsFrameList* L; + if (aProp == OverflowProperty()) { + L(aValue)->AppendIfNonempty(aLists, kOverflowList); + } else if (aProp == OverflowContainersProperty()) { + MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers), + "found unexpected OverflowContainersProperty"); + L(aValue)->AppendIfNonempty(aLists, kOverflowContainersList); + } else if (aProp == ExcessOverflowContainersProperty()) { + MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers), + "found unexpected ExcessOverflowContainersProperty"); + L(aValue)->AppendIfNonempty(aLists, kExcessOverflowContainersList); + } else if (aProp == BackdropProperty()) { + L(aValue)->AppendIfNonempty(aLists, kBackdropList); + } + return true; + }); nsSplittableFrame::GetChildLists(aLists); } -- cgit v1.2.3