From af7837cf56eafbf764d988398f05171299f666fc Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 29 Mar 2011 13:29:21 -0400 Subject: [PATCH] Bug 598832 part 16. Use a single TreeMatchContext for all the style resolution that the frame constructor does as part of a single frame construction batch. r=dbaron --- layout/base/nsCSSFrameConstructor.cpp | 37 +++++++++++++++++++------ layout/base/nsCSSFrameConstructor.h | 8 ++++-- layout/style/nsStyleSet.cpp | 40 ++++++++++++++++++++------- layout/style/nsStyleSet.h | 11 ++++++++ 4 files changed, 75 insertions(+), 21 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 02e5d6681b33..d12d1ed69889 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -150,6 +150,7 @@ #include "nsSVGOuterSVGFrame.h" #include "nsRefreshDriver.h" +#include "nsRuleProcessorData.h" using namespace mozilla; using namespace mozilla::dom; @@ -744,6 +745,8 @@ public: nsCOMArray mGeneratedTextNodesWithInitializer; + TreeMatchContext mTreeMatchContext; + // Constructor // Use the passed-in history state. nsFrameConstructorState(nsIPresShell* aPresShell, @@ -906,6 +909,8 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShe HasTransform()), mHavePendingPopupgroup(PR_FALSE), mCreatingExtraFrames(PR_FALSE), + mTreeMatchContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited, + aPresShell->GetDocument()), mCurrentPendingBindingInsertionPoint(&mPendingBindings) { #ifdef MOZ_XUL @@ -938,6 +943,8 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell, HasTransform()), mHavePendingPopupgroup(PR_FALSE), mCreatingExtraFrames(PR_FALSE), + mTreeMatchContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited, + aPresShell->GetDocument()), mCurrentPendingBindingInsertionPoint(&mPendingBindings) { #ifdef MOZ_XUL @@ -1688,7 +1695,8 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat pseudoStyleContext = styleSet->ProbePseudoElementStyle(aParentContent->AsElement(), aPseudoElement, - aStyleContext); + aStyleContext, + aState.mTreeMatchContext); if (!pseudoStyleContext) return; // |ProbePseudoStyleFor| checked the 'display' property and the @@ -4546,7 +4554,8 @@ nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState already_AddRefed nsCSSFrameConstructor::ResolveStyleContext(nsIFrame* aParentFrame, - nsIContent* aContent) + nsIContent* aContent, + nsFrameConstructorState* aState) { nsStyleContext* parentStyleContext = nsnull; NS_ASSERTION(aContent->GetParent(), "Must have parent here"); @@ -4565,17 +4574,24 @@ nsCSSFrameConstructor::ResolveStyleContext(nsIFrame* aParentFrame, // previous page's fixed-pos frame? } - return ResolveStyleContext(parentStyleContext, aContent); + return ResolveStyleContext(parentStyleContext, aContent, aState); } already_AddRefed nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext, - nsIContent* aContent) + nsIContent* aContent, + nsFrameConstructorState* aState) { nsStyleSet *styleSet = mPresShell->StyleSet(); if (aContent->IsElement()) { + if (aState) { + return styleSet->ResolveStyleFor(aContent->AsElement(), + aParentStyleContext, + aState->mTreeMatchContext); + } return styleSet->ResolveStyleFor(aContent->AsElement(), aParentStyleContext); + } NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT), @@ -5031,7 +5047,7 @@ nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState& aState return; nsRefPtr styleContext; - styleContext = ResolveStyleContext(aParentFrame, aContent); + styleContext = ResolveStyleContext(aParentFrame, aContent, &aState); AddFrameConstructionItemsInternal(aState, aContent, aParentFrame, aContent->Tag(), aContent->GetNameSpaceID(), @@ -5113,7 +5129,8 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState } if (resolveStyle) { - styleContext = ResolveStyleContext(styleContext->GetParent(), aContent); + styleContext = + ResolveStyleContext(styleContext->GetParent(), aContent, &aState); display = styleContext->GetStyleDisplay(); aStyleContext = styleContext; } @@ -5829,7 +5846,9 @@ nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling, NS_NOTREACHED("Shouldn't happen"); return PR_FALSE; } - styleContext = ResolveStyleContext(styleParent, aContent); + // XXXbz when this code is killed, the state argument to + // ResolveStyleContext can be made non-optional. + styleContext = ResolveStyleContext(styleParent, aContent, nsnull); if (!styleContext) return PR_FALSE; const nsStyleDisplay* display = styleContext->GetStyleDisplay(); aDisplay = display->mDisplay; @@ -10558,7 +10577,7 @@ nsCSSFrameConstructor::CreateListBoxContent(nsPresContext* aPresContext, mTempFrameTreeState); nsRefPtr styleContext; - styleContext = ResolveStyleContext(aParentFrame, aChild); + styleContext = ResolveStyleContext(aParentFrame, aChild, &state); // Pre-check for display "none" - only if we find that, do we create // any frame at all @@ -10941,7 +10960,7 @@ nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState, } nsRefPtr childContext = - ResolveStyleContext(parentStyleContext, content); + ResolveStyleContext(parentStyleContext, content, &aState); AddFrameConstructionItemsInternal(aState, content, nsnull, content->Tag(), content->GetNameSpaceID(), diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index d6f52a7dfbfb..3b3124e50b9e 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -429,12 +429,16 @@ private: nsIFrame* aNewFrame, PRBool aAllowCounters = PR_TRUE); + // aState can be null if not available; it's used as an optimization. + // XXXbz IsValidSibling is the only caller that doesn't pass a state here! already_AddRefed ResolveStyleContext(nsIFrame* aParentFrame, - nsIContent* aContent); + nsIContent* aContent, + nsFrameConstructorState* aState); already_AddRefed ResolveStyleContext(nsStyleContext* aParentStyleContext, - nsIContent* aContent); + nsIContent* aContent, + nsFrameConstructorState* aState); // Construct a frame for aContent and put it in aFrameItems. This should // only be used in cases when it's known that the frame won't need table diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 3e33f2e9156d..86de3505f7fb 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -761,23 +761,32 @@ PRBool nsStyleSet::BuildDefaultStyleData(nsPresContext* aPresContext) already_AddRefed nsStyleSet::ResolveStyleFor(Element* aElement, nsStyleContext* aParentContext) +{ + TreeMatchContext treeContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited, + aElement->GetOwnerDoc()); + return ResolveStyleFor(aElement, aParentContext, treeContext); +} + +already_AddRefed +nsStyleSet::ResolveStyleFor(Element* aElement, + nsStyleContext* aParentContext, + TreeMatchContext& aTreeMatchContext) { NS_ENSURE_FALSE(mInShutdown, nsnull); NS_ASSERTION(aElement, "aElement must not be null"); nsRuleWalker ruleWalker(mRuleTree); - TreeMatchContext treeContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited, - aElement->GetOwnerDoc()); + aTreeMatchContext.ResetForUnvisitedMatching(); ElementRuleProcessorData data(PresContext(), aElement, &ruleWalker, - treeContext); + aTreeMatchContext); FileRules(EnumRulesMatching, &data, aElement, &ruleWalker); nsRuleNode *ruleNode = ruleWalker.CurrentNode(); nsRuleNode *visitedRuleNode = nsnull; - if (treeContext.HaveRelevantLink()) { - treeContext.ResetForVisitedMatching(); + if (aTreeMatchContext.HaveRelevantLink()) { + aTreeMatchContext.ResetForVisitedMatching(); ruleWalker.Reset(); FileRules(EnumRulesMatching, &data, aElement, &ruleWalker); @@ -906,6 +915,18 @@ already_AddRefed nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, nsCSSPseudoElements::Type aType, nsStyleContext* aParentContext) +{ + TreeMatchContext treeContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited, + aParentElement->GetOwnerDoc()); + return ProbePseudoElementStyle(aParentElement, aType, aParentContext, + treeContext); +} + +already_AddRefed +nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, + nsCSSPseudoElements::Type aType, + nsStyleContext* aParentContext, + TreeMatchContext& aTreeMatchContext) { NS_ENSURE_FALSE(mInShutdown, nsnull); @@ -915,10 +936,9 @@ nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType); nsRuleWalker ruleWalker(mRuleTree); - TreeMatchContext treeContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited, - aParentElement->GetOwnerDoc()); + aTreeMatchContext.ResetForUnvisitedMatching(); PseudoElementRuleProcessorData data(PresContext(), aParentElement, - &ruleWalker, aType, treeContext); + &ruleWalker, aType, aTreeMatchContext); WalkRestrictionRule(aType, &ruleWalker); // not the root if there was a restriction rule nsRuleNode *adjustedRoot = ruleWalker.CurrentNode(); @@ -932,8 +952,8 @@ nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, nsRuleNode *visitedRuleNode = nsnull; - if (treeContext.HaveRelevantLink()) { - treeContext.ResetForVisitedMatching(); + if (aTreeMatchContext.HaveRelevantLink()) { + aTreeMatchContext.ResetForVisitedMatching(); ruleWalker.Reset(); FileRules(EnumRulesMatching, &data, aParentElement, &ruleWalker); diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index 1f8c6f98c7b3..d490a3b5aede 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -62,6 +62,7 @@ class nsIURI; class nsCSSFontFaceRule; class nsRuleWalker; struct RuleProcessorData; +struct TreeMatchContext; class nsEmptyStyleRule : public nsIStyleRule { @@ -100,6 +101,11 @@ class nsStyleSet ResolveStyleFor(mozilla::dom::Element* aElement, nsStyleContext* aParentContext); + already_AddRefed + ResolveStyleFor(mozilla::dom::Element* aElement, + nsStyleContext* aParentContext, + TreeMatchContext& aTreeMatchContext); + // Get a style context (with the given parent) for the // sequence of style rules in the |aRules| array. already_AddRefed @@ -138,6 +144,11 @@ class nsStyleSet ProbePseudoElementStyle(mozilla::dom::Element* aParentElement, nsCSSPseudoElements::Type aType, nsStyleContext* aParentContext); + already_AddRefed + ProbePseudoElementStyle(mozilla::dom::Element* aParentElement, + nsCSSPseudoElements::Type aType, + nsStyleContext* aParentContext, + TreeMatchContext& aTreeMatchContext); // Get a style context for an anonymous box. aPseudoTag is the // pseudo-tag to use and must be non-null.