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

This commit is contained in:
Boris Zbarsky
2011-03-29 13:29:21 -04:00
parent c36bf20ce0
commit c3a5087e5b
4 changed files with 75 additions and 21 deletions

View File

@@ -150,6 +150,7 @@
#include "nsSVGOuterSVGFrame.h" #include "nsSVGOuterSVGFrame.h"
#include "nsRefreshDriver.h" #include "nsRefreshDriver.h"
#include "nsRuleProcessorData.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
@@ -744,6 +745,8 @@ public:
nsCOMArray<nsIContent> mGeneratedTextNodesWithInitializer; nsCOMArray<nsIContent> mGeneratedTextNodesWithInitializer;
TreeMatchContext mTreeMatchContext;
// Constructor // Constructor
// Use the passed-in history state. // Use the passed-in history state.
nsFrameConstructorState(nsIPresShell* aPresShell, nsFrameConstructorState(nsIPresShell* aPresShell,
@@ -906,6 +909,8 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShe
HasTransform()), HasTransform()),
mHavePendingPopupgroup(PR_FALSE), mHavePendingPopupgroup(PR_FALSE),
mCreatingExtraFrames(PR_FALSE), mCreatingExtraFrames(PR_FALSE),
mTreeMatchContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited,
aPresShell->GetDocument()),
mCurrentPendingBindingInsertionPoint(&mPendingBindings) mCurrentPendingBindingInsertionPoint(&mPendingBindings)
{ {
#ifdef MOZ_XUL #ifdef MOZ_XUL
@@ -938,6 +943,8 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
HasTransform()), HasTransform()),
mHavePendingPopupgroup(PR_FALSE), mHavePendingPopupgroup(PR_FALSE),
mCreatingExtraFrames(PR_FALSE), mCreatingExtraFrames(PR_FALSE),
mTreeMatchContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited,
aPresShell->GetDocument()),
mCurrentPendingBindingInsertionPoint(&mPendingBindings) mCurrentPendingBindingInsertionPoint(&mPendingBindings)
{ {
#ifdef MOZ_XUL #ifdef MOZ_XUL
@@ -1688,7 +1695,8 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat
pseudoStyleContext = pseudoStyleContext =
styleSet->ProbePseudoElementStyle(aParentContent->AsElement(), styleSet->ProbePseudoElementStyle(aParentContent->AsElement(),
aPseudoElement, aPseudoElement,
aStyleContext); aStyleContext,
aState.mTreeMatchContext);
if (!pseudoStyleContext) if (!pseudoStyleContext)
return; return;
// |ProbePseudoStyleFor| checked the 'display' property and the // |ProbePseudoStyleFor| checked the 'display' property and the
@@ -4546,7 +4554,8 @@ nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
nsCSSFrameConstructor::ResolveStyleContext(nsIFrame* aParentFrame, nsCSSFrameConstructor::ResolveStyleContext(nsIFrame* aParentFrame,
nsIContent* aContent) nsIContent* aContent,
nsFrameConstructorState* aState)
{ {
nsStyleContext* parentStyleContext = nsnull; nsStyleContext* parentStyleContext = nsnull;
NS_ASSERTION(aContent->GetParent(), "Must have parent here"); NS_ASSERTION(aContent->GetParent(), "Must have parent here");
@@ -4565,17 +4574,24 @@ nsCSSFrameConstructor::ResolveStyleContext(nsIFrame* aParentFrame,
// previous page's fixed-pos frame? // previous page's fixed-pos frame?
} }
return ResolveStyleContext(parentStyleContext, aContent); return ResolveStyleContext(parentStyleContext, aContent, aState);
} }
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext, nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
nsIContent* aContent) nsIContent* aContent,
nsFrameConstructorState* aState)
{ {
nsStyleSet *styleSet = mPresShell->StyleSet(); nsStyleSet *styleSet = mPresShell->StyleSet();
if (aContent->IsElement()) { if (aContent->IsElement()) {
if (aState) {
return styleSet->ResolveStyleFor(aContent->AsElement(),
aParentStyleContext,
aState->mTreeMatchContext);
}
return styleSet->ResolveStyleFor(aContent->AsElement(), aParentStyleContext); return styleSet->ResolveStyleFor(aContent->AsElement(), aParentStyleContext);
} }
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT), NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
@@ -5031,7 +5047,7 @@ nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState& aState
return; return;
nsRefPtr<nsStyleContext> styleContext; nsRefPtr<nsStyleContext> styleContext;
styleContext = ResolveStyleContext(aParentFrame, aContent); styleContext = ResolveStyleContext(aParentFrame, aContent, &aState);
AddFrameConstructionItemsInternal(aState, aContent, aParentFrame, AddFrameConstructionItemsInternal(aState, aContent, aParentFrame,
aContent->Tag(), aContent->GetNameSpaceID(), aContent->Tag(), aContent->GetNameSpaceID(),
@@ -5113,7 +5129,8 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
} }
if (resolveStyle) { if (resolveStyle) {
styleContext = ResolveStyleContext(styleContext->GetParent(), aContent); styleContext =
ResolveStyleContext(styleContext->GetParent(), aContent, &aState);
display = styleContext->GetStyleDisplay(); display = styleContext->GetStyleDisplay();
aStyleContext = styleContext; aStyleContext = styleContext;
} }
@@ -5829,7 +5846,9 @@ nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
NS_NOTREACHED("Shouldn't happen"); NS_NOTREACHED("Shouldn't happen");
return PR_FALSE; 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; if (!styleContext) return PR_FALSE;
const nsStyleDisplay* display = styleContext->GetStyleDisplay(); const nsStyleDisplay* display = styleContext->GetStyleDisplay();
aDisplay = display->mDisplay; aDisplay = display->mDisplay;
@@ -10558,7 +10577,7 @@ nsCSSFrameConstructor::CreateListBoxContent(nsPresContext* aPresContext,
mTempFrameTreeState); mTempFrameTreeState);
nsRefPtr<nsStyleContext> styleContext; nsRefPtr<nsStyleContext> styleContext;
styleContext = ResolveStyleContext(aParentFrame, aChild); styleContext = ResolveStyleContext(aParentFrame, aChild, &state);
// Pre-check for display "none" - only if we find that, do we create // Pre-check for display "none" - only if we find that, do we create
// any frame at all // any frame at all
@@ -10941,7 +10960,7 @@ nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
} }
nsRefPtr<nsStyleContext> childContext = nsRefPtr<nsStyleContext> childContext =
ResolveStyleContext(parentStyleContext, content); ResolveStyleContext(parentStyleContext, content, &aState);
AddFrameConstructionItemsInternal(aState, content, nsnull, content->Tag(), AddFrameConstructionItemsInternal(aState, content, nsnull, content->Tag(),
content->GetNameSpaceID(), content->GetNameSpaceID(),

View File

@@ -429,12 +429,16 @@ private:
nsIFrame* aNewFrame, nsIFrame* aNewFrame,
PRBool aAllowCounters = PR_TRUE); 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<nsStyleContext> already_AddRefed<nsStyleContext>
ResolveStyleContext(nsIFrame* aParentFrame, ResolveStyleContext(nsIFrame* aParentFrame,
nsIContent* aContent); nsIContent* aContent,
nsFrameConstructorState* aState);
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
ResolveStyleContext(nsStyleContext* aParentStyleContext, ResolveStyleContext(nsStyleContext* aParentStyleContext,
nsIContent* aContent); nsIContent* aContent,
nsFrameConstructorState* aState);
// Construct a frame for aContent and put it in aFrameItems. This should // 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 // only be used in cases when it's known that the frame won't need table

View File

@@ -761,23 +761,32 @@ PRBool nsStyleSet::BuildDefaultStyleData(nsPresContext* aPresContext)
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
nsStyleSet::ResolveStyleFor(Element* aElement, nsStyleSet::ResolveStyleFor(Element* aElement,
nsStyleContext* aParentContext) nsStyleContext* aParentContext)
{
TreeMatchContext treeContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited,
aElement->GetOwnerDoc());
return ResolveStyleFor(aElement, aParentContext, treeContext);
}
already_AddRefed<nsStyleContext>
nsStyleSet::ResolveStyleFor(Element* aElement,
nsStyleContext* aParentContext,
TreeMatchContext& aTreeMatchContext)
{ {
NS_ENSURE_FALSE(mInShutdown, nsnull); NS_ENSURE_FALSE(mInShutdown, nsnull);
NS_ASSERTION(aElement, "aElement must not be null"); NS_ASSERTION(aElement, "aElement must not be null");
nsRuleWalker ruleWalker(mRuleTree); nsRuleWalker ruleWalker(mRuleTree);
TreeMatchContext treeContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited, aTreeMatchContext.ResetForUnvisitedMatching();
aElement->GetOwnerDoc());
ElementRuleProcessorData data(PresContext(), aElement, &ruleWalker, ElementRuleProcessorData data(PresContext(), aElement, &ruleWalker,
treeContext); aTreeMatchContext);
FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement, FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement,
&ruleWalker); &ruleWalker);
nsRuleNode *ruleNode = ruleWalker.CurrentNode(); nsRuleNode *ruleNode = ruleWalker.CurrentNode();
nsRuleNode *visitedRuleNode = nsnull; nsRuleNode *visitedRuleNode = nsnull;
if (treeContext.HaveRelevantLink()) { if (aTreeMatchContext.HaveRelevantLink()) {
treeContext.ResetForVisitedMatching(); aTreeMatchContext.ResetForVisitedMatching();
ruleWalker.Reset(); ruleWalker.Reset();
FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement, FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement,
&ruleWalker); &ruleWalker);
@@ -906,6 +915,18 @@ already_AddRefed<nsStyleContext>
nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
nsCSSPseudoElements::Type aType, nsCSSPseudoElements::Type aType,
nsStyleContext* aParentContext) nsStyleContext* aParentContext)
{
TreeMatchContext treeContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited,
aParentElement->GetOwnerDoc());
return ProbePseudoElementStyle(aParentElement, aType, aParentContext,
treeContext);
}
already_AddRefed<nsStyleContext>
nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
nsCSSPseudoElements::Type aType,
nsStyleContext* aParentContext,
TreeMatchContext& aTreeMatchContext)
{ {
NS_ENSURE_FALSE(mInShutdown, nsnull); NS_ENSURE_FALSE(mInShutdown, nsnull);
@@ -915,10 +936,9 @@ nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType); nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
nsRuleWalker ruleWalker(mRuleTree); nsRuleWalker ruleWalker(mRuleTree);
TreeMatchContext treeContext(PR_TRUE, nsRuleWalker::eRelevantLinkUnvisited, aTreeMatchContext.ResetForUnvisitedMatching();
aParentElement->GetOwnerDoc());
PseudoElementRuleProcessorData data(PresContext(), aParentElement, PseudoElementRuleProcessorData data(PresContext(), aParentElement,
&ruleWalker, aType, treeContext); &ruleWalker, aType, aTreeMatchContext);
WalkRestrictionRule(aType, &ruleWalker); WalkRestrictionRule(aType, &ruleWalker);
// not the root if there was a restriction rule // not the root if there was a restriction rule
nsRuleNode *adjustedRoot = ruleWalker.CurrentNode(); nsRuleNode *adjustedRoot = ruleWalker.CurrentNode();
@@ -932,8 +952,8 @@ nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
nsRuleNode *visitedRuleNode = nsnull; nsRuleNode *visitedRuleNode = nsnull;
if (treeContext.HaveRelevantLink()) { if (aTreeMatchContext.HaveRelevantLink()) {
treeContext.ResetForVisitedMatching(); aTreeMatchContext.ResetForVisitedMatching();
ruleWalker.Reset(); ruleWalker.Reset();
FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data, FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
aParentElement, &ruleWalker); aParentElement, &ruleWalker);

View File

@@ -62,6 +62,7 @@ class nsIURI;
class nsCSSFontFaceRule; class nsCSSFontFaceRule;
class nsRuleWalker; class nsRuleWalker;
struct RuleProcessorData; struct RuleProcessorData;
struct TreeMatchContext;
class nsEmptyStyleRule : public nsIStyleRule class nsEmptyStyleRule : public nsIStyleRule
{ {
@@ -100,6 +101,11 @@ class nsStyleSet
ResolveStyleFor(mozilla::dom::Element* aElement, ResolveStyleFor(mozilla::dom::Element* aElement,
nsStyleContext* aParentContext); nsStyleContext* aParentContext);
already_AddRefed<nsStyleContext>
ResolveStyleFor(mozilla::dom::Element* aElement,
nsStyleContext* aParentContext,
TreeMatchContext& aTreeMatchContext);
// Get a style context (with the given parent) for the // Get a style context (with the given parent) for the
// sequence of style rules in the |aRules| array. // sequence of style rules in the |aRules| array.
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
@@ -138,6 +144,11 @@ class nsStyleSet
ProbePseudoElementStyle(mozilla::dom::Element* aParentElement, ProbePseudoElementStyle(mozilla::dom::Element* aParentElement,
nsCSSPseudoElements::Type aType, nsCSSPseudoElements::Type aType,
nsStyleContext* aParentContext); nsStyleContext* aParentContext);
already_AddRefed<nsStyleContext>
ProbePseudoElementStyle(mozilla::dom::Element* aParentElement,
nsCSSPseudoElements::Type aType,
nsStyleContext* aParentContext,
TreeMatchContext& aTreeMatchContext);
// Get a style context for an anonymous box. aPseudoTag is the // Get a style context for an anonymous box. aPseudoTag is the
// pseudo-tag to use and must be non-null. // pseudo-tag to use and must be non-null.