summaryrefslogtreecommitdiff
path: root/layout/base/nsCSSFrameConstructor.cpp
diff options
context:
space:
mode:
authorFranklinDM <mrmineshafter17@gmail.com>2023-03-04 13:59:36 +0800
committerFranklinDM <mrmineshafter17@gmail.com>2023-03-04 21:32:15 +0800
commit6a1b4a9e3a27709d3250ad69e8abbd2306982e63 (patch)
treefff052df1b4bd9601607754c28db3d717c38fb20 /layout/base/nsCSSFrameConstructor.cpp
parent7669ddb4b79c4c32db577a5a38b8c64c79488938 (diff)
downloaduxp-6a1b4a9e3a27709d3250ad69e8abbd2306982e63.tar.gz
Issue #2135 - Bug 1329877: Optimize AncestorFilter usage in lazy frame construction
Diffstat (limited to 'layout/base/nsCSSFrameConstructor.cpp')
-rw-r--r--layout/base/nsCSSFrameConstructor.cpp119
1 files changed, 89 insertions, 30 deletions
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index 1545e1d331..8293e5198c 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -788,21 +788,23 @@ public:
nsCOMArray<nsIContent> mGeneratedTextNodesWithInitializer;
- TreeMatchContext mTreeMatchContext;
+ TreeMatchContext& mTreeMatchContext;
// Constructor
// Use the passed-in history state.
nsFrameConstructorState(
nsIPresShell* aPresShell,
+ TreeMatchContext& aTreeMatchContext,
nsContainerFrame* aFixedContainingBlock,
nsContainerFrame* aAbsoluteContainingBlock,
nsContainerFrame* aFloatContainingBlock,
already_AddRefed<nsILayoutHistoryState> aHistoryState);
// Get the history state from the pres context's pres shell.
- nsFrameConstructorState(nsIPresShell* aPresShell,
- nsContainerFrame* aFixedContainingBlock,
- nsContainerFrame* aAbsoluteContainingBlock,
- nsContainerFrame* aFloatContainingBlock);
+ nsFrameConstructorState(nsIPresShell* aPresShell,
+ TreeMatchContext& aTreeMatchContext,
+ nsContainerFrame* aFixedContainingBlock,
+ nsContainerFrame* aAbsoluteContainingBlock,
+ nsContainerFrame* aFloatContainingBlock);
~nsFrameConstructorState();
@@ -955,6 +957,7 @@ protected:
nsFrameConstructorState::nsFrameConstructorState(
nsIPresShell* aPresShell,
+ TreeMatchContext& aTreeMatchContext,
nsContainerFrame* aFixedContainingBlock,
nsContainerFrame* aAbsoluteContainingBlock,
nsContainerFrame* aFloatContainingBlock,
@@ -979,8 +982,7 @@ nsFrameConstructorState::nsFrameConstructorState(
mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
mHavePendingPopupgroup(false),
mCreatingExtraFrames(false),
- mTreeMatchContext(true, nsRuleWalker::eRelevantLinkUnvisited,
- aPresShell->GetDocument()),
+ mTreeMatchContext(aTreeMatchContext),
mCurrentPendingBindingInsertionPoint(nullptr)
{
nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
@@ -991,10 +993,13 @@ nsFrameConstructorState::nsFrameConstructorState(
}
nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
+ TreeMatchContext& aTreeMatchContext,
nsContainerFrame* aFixedContainingBlock,
nsContainerFrame* aAbsoluteContainingBlock,
nsContainerFrame* aFloatContainingBlock)
- : nsFrameConstructorState(aPresShell, aFixedContainingBlock,
+ : nsFrameConstructorState(aPresShell,
+ aTreeMatchContext,
+ aFixedContainingBlock,
aAbsoluteContainingBlock,
aFloatContainingBlock,
aPresShell->GetDocument()->GetLayoutHistoryState())
@@ -2396,13 +2401,15 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle
NS_ASSERTION(mDocElementContainingBlock, "Should have parent by now");
+ TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction);
+ // Initialize the ancestor filter with null for now; we'll push
+ // aDocElement once we finish resolving style for it.
+ matchContext.InitAncestors(nullptr);
nsFrameConstructorState state(mPresShell,
+ matchContext,
GetAbsoluteContainingBlock(mDocElementContainingBlock, FIXED_POS),
nullptr,
nullptr, do_AddRef(aFrameState));
- // Initialize the ancestor filter with null for now; we'll push
- // aDocElement once we finish resolving style for it.
- state.mTreeMatchContext.InitAncestors(nullptr);
// XXXbz why, exactly?
if (!mTempFrameTreeState)
@@ -2831,7 +2838,8 @@ nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
RefPtr<nsStyleContext> rootPseudoStyle;
// we must create a state because if the scrollbars are GFX it needs the
// state to build the scrollbar frames.
- nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr);
+ TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction);
+ nsFrameConstructorState state(mPresShell, matchContext, nullptr, nullptr, nullptr);
// Start off with the viewport as parent; we'll adjust it as needed.
nsContainerFrame* parentFrame = viewportFrame;
@@ -6978,12 +6986,16 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
}
void
-nsCSSFrameConstructor::CreateNeededFrames(nsIContent* aContent)
+nsCSSFrameConstructor::CreateNeededFrames(nsIContent* aContent,
+ TreeMatchContext& aTreeMatchContext)
{
NS_ASSERTION(!aContent->HasFlag(NODE_NEEDS_FRAME),
"shouldn't get here with a content node that has needs frame bit set");
NS_ASSERTION(aContent->HasFlag(NODE_DESCENDANTS_NEED_FRAMES),
"should only get here with a content node that has descendants needing frames");
+ NS_ASSERTION(aTreeMatchContext.mAncestorFilter.HasFilter(),
+ "The whole point of having the tree match context is optimizing "
+ "the ancestor filter usage!");
aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
@@ -7019,19 +7031,31 @@ nsCSSFrameConstructor::CreateNeededFrames(nsIContent* aContent)
inRun = false;
// generate a ContentRangeInserted for [startOfRun,i)
ContentRangeInserted(aContent, firstChildInRun, child, nullptr,
- false);
+ false, &aTreeMatchContext);
}
}
}
if (inRun) {
- ContentAppended(aContent, firstChildInRun, false);
+ ContentAppended(aContent, firstChildInRun, false, &aTreeMatchContext);
}
// Now descend.
FlattenedChildIterator iter(aContent);
for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
if (child->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
- CreateNeededFrames(child);
+ TreeMatchContext::AutoAncestorPusher insertionPointPusher(
+ aTreeMatchContext);
+
+ // Handle stuff like xbl:children.
+ if (child->GetParent() != aContent && child->GetParent()->IsElement()) {
+ insertionPointPusher.PushAncestorAndStyleScope(
+ child->GetParent()->AsElement());
+ }
+
+ TreeMatchContext::AutoAncestorPusher pusher(aTreeMatchContext);
+ pusher.PushAncestorAndStyleScope(child);
+
+ CreateNeededFrames(child, aTreeMatchContext);
}
}
}
@@ -7046,7 +7070,9 @@ void nsCSSFrameConstructor::CreateNeededFrames()
"root element should not have frame created lazily");
if (rootElement && rootElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
BeginUpdate();
- CreateNeededFrames(rootElement);
+ TreeMatchContext treeMatchContext(mDocument, TreeMatchContext::ForFrameConstruction);
+ treeMatchContext.InitAncestors(rootElement);
+ CreateNeededFrames(rootElement, treeMatchContext);
EndUpdate();
}
}
@@ -7160,10 +7186,13 @@ nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame,
}
void
-nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
- nsIContent* aFirstNewContent,
- bool aAllowLazyConstruction)
+nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
+ nsIContent* aFirstNewContent,
+ bool aAllowLazyConstruction,
+ TreeMatchContext* aProvidedTreeMatchContext)
{
+ MOZ_ASSERT_IF(aProvidedTreeMatchContext, !aAllowLazyConstruction);
+
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
NS_PRECONDITION(mUpdateCount != 0,
"Should be in an update while creating frames");
@@ -7341,13 +7370,23 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
}
// Create some new frames
+ //
+ // We use the provided tree match context, or create a new one on the fly
+ // otherwise.
+ Maybe<TreeMatchContext> matchContext;
+ if (!aProvidedTreeMatchContext) {
+ matchContext.emplace(mDocument, TreeMatchContext::ForFrameConstruction);
+ // We use GetParentElementCrossingShadowRoot to handle the case where
+ // aContainer is a ShadowRoot.
+ matchContext->InitAncestors(aFirstNewContent->GetParentElementCrossingShadowRoot());
+ }
nsFrameConstructorState state(mPresShell,
+ aProvidedTreeMatchContext
+ ? *aProvidedTreeMatchContext
+ : *matchContext,
GetAbsoluteContainingBlock(parentFrame, FIXED_POS),
GetAbsoluteContainingBlock(parentFrame, ABS_POS),
containingBlock);
- // We use GetParentElementCrossingShadowRoot to handle the case where
- // aContainer is a ShadowRoot.
- state.mTreeMatchContext.InitAncestors(aFirstNewContent->GetParentElementCrossingShadowRoot());
nsIAtom* frameType = parentFrame->GetType();
@@ -7553,7 +7592,8 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
nsIContent* aStartChild,
nsIContent* aEndChild,
nsILayoutHistoryState* aFrameState,
- bool aAllowLazyConstruction)
+ bool aAllowLazyConstruction,
+ TreeMatchContext* aProvidedTreeMatchContext)
{
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
NS_PRECONDITION(mUpdateCount != 0,
@@ -7784,14 +7824,21 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
return;
}
+ Maybe<TreeMatchContext> matchContext;
+ if (!aProvidedTreeMatchContext) {
+ matchContext.emplace(mDocument, TreeMatchContext::ForFrameConstruction);
+ // We use GetParentElementCrossingShadowRoot to handle the case where
+ // aContainer is a ShadowRoot.
+ matchContext->InitAncestors(aStartChild->GetParentElementCrossingShadowRoot());
+ }
nsFrameConstructorState state(mPresShell,
+ aProvidedTreeMatchContext
+ ? *aProvidedTreeMatchContext
+ : *matchContext,
GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS),
GetAbsoluteContainingBlock(insertion.mParentFrame, ABS_POS),
GetFloatContainingBlock(insertion.mParentFrame),
do_AddRef(aFrameState));
- // We use GetParentElementCrossingShadowRoot to handle the case where
- // aContainer is a ShadowRoot.
- state.mTreeMatchContext.InitAncestors(aStartChild->GetParentElementCrossingShadowRoot());
// Recover state for the containing block - we need to know if
// it has :first-letter or :first-line style applied to it. The
@@ -8637,7 +8684,9 @@ nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell* aPresShell,
// Replicate the header/footer frame.
nsTableRowGroupFrame* headerFooterFrame;
nsFrameItems childItems;
+ TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction);
nsFrameConstructorState state(mPresShell,
+ matchContext,
GetAbsoluteContainingBlock(newFrame, FIXED_POS),
GetAbsoluteContainingBlock(newFrame, ABS_POS),
nullptr);
@@ -8909,7 +8958,10 @@ nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
// This should not normally be possible (because fixed-pos elements should
// be absolute containers) but fixed-pos tables currently aren't abs-pos
// containers.
- nsFrameConstructorState state(mPresShell, aParentFrame,
+ TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction);
+ nsFrameConstructorState state(mPresShell,
+ matchContext,
+ aParentFrame,
nullptr,
mRootElementFrame);
state.mCreatingExtraFrames = true;
@@ -11047,7 +11099,10 @@ nsCSSFrameConstructor::CreateLetterFrame(nsContainerFrame* aBlockFrame,
NS_ASSERTION(aBlockContinuation == GetFloatContainingBlock(aParentFrame),
"Containing block is confused");
+ TreeMatchContext matchContext(mDocument,
+ TreeMatchContext::ForFrameConstruction);
nsFrameConstructorState state(mPresShell,
+ matchContext,
GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
GetAbsoluteContainingBlock(aParentFrame, ABS_POS),
aBlockContinuation);
@@ -11422,7 +11477,10 @@ nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame* aParentFrame,
// Construct a new frame
if (nullptr != aParentFrame) {
nsFrameItems frameItems;
- nsFrameConstructorState state(mPresShell, GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
+ TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction);
+ nsFrameConstructorState state(mPresShell,
+ matchContext,
+ GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
GetAbsoluteContainingBlock(aParentFrame, ABS_POS),
GetFloatContainingBlock(aParentFrame),
do_AddRef(mTempFrameTreeState.get()));
@@ -12312,7 +12370,8 @@ nsCSSFrameConstructor::GenerateChildFrames(nsContainerFrame* aFrame)
BeginUpdate();
nsFrameItems childItems;
- nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr);
+ TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction);
+ nsFrameConstructorState state(mPresShell, matchContext, nullptr, nullptr, nullptr);
// We don't have a parent frame with a pending binding constructor here,
// so no need to worry about ordering of the kids' constructors with it.
// Pass null for the PendingBinding.