mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-20 03:13:09 +09:00
Issue #2135 - Bug 1329877: Optimize AncestorFilter usage in lazy frame construction
This commit is contained in:
parent
7b395189ac
commit
7924a2f60d
3 changed files with 112 additions and 33 deletions
|
|
@ -796,21 +796,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();
|
||||
|
||||
|
|
@ -963,6 +965,7 @@ protected:
|
|||
|
||||
nsFrameConstructorState::nsFrameConstructorState(
|
||||
nsIPresShell* aPresShell,
|
||||
TreeMatchContext& aTreeMatchContext,
|
||||
nsContainerFrame* aFixedContainingBlock,
|
||||
nsContainerFrame* aAbsoluteContainingBlock,
|
||||
nsContainerFrame* aFloatContainingBlock,
|
||||
|
|
@ -989,8 +992,7 @@ nsFrameConstructorState::nsFrameConstructorState(
|
|||
mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
|
||||
mHavePendingPopupgroup(false),
|
||||
mCreatingExtraFrames(false),
|
||||
mTreeMatchContext(true, nsRuleWalker::eRelevantLinkUnvisited,
|
||||
aPresShell->GetDocument()),
|
||||
mTreeMatchContext(aTreeMatchContext),
|
||||
mCurrentPendingBindingInsertionPoint(nullptr)
|
||||
{
|
||||
#ifdef MOZ_XUL
|
||||
|
|
@ -1003,10 +1005,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())
|
||||
|
|
@ -2417,13 +2422,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)
|
||||
|
|
@ -2856,7 +2863,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;
|
||||
|
|
@ -7023,12 +7031,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);
|
||||
|
||||
|
|
@ -7064,19 +7076,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7091,7 +7115,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();
|
||||
}
|
||||
}
|
||||
|
|
@ -7208,10 +7234,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");
|
||||
|
|
@ -7391,13 +7420,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();
|
||||
|
||||
|
|
@ -7606,7 +7645,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,
|
||||
|
|
@ -7839,14 +7879,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
|
||||
|
|
@ -8695,7 +8742,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);
|
||||
|
|
@ -8969,7 +9018,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;
|
||||
|
|
@ -11109,7 +11161,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);
|
||||
|
|
@ -11485,7 +11540,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()));
|
||||
|
|
@ -12376,7 +12434,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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue