Issue #2112 - Part 14: Remove style context source and use rule node directly

Based on reverting bug 1260310.
This commit is contained in:
FranklinDM 2024-03-26 01:48:18 +08:00 • committed by roytam1
commit 9279153af8
4 changed files with 54 additions and 185 deletions

View file

@ -1,99 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_StyleContextSource_h
#define mozilla_StyleContextSource_h
#include "nsRuleNode.h"
namespace mozilla {
// Temporary holder of Gecko Rule Nodes.
// TODO: This struct is marked for removal.
//
// The rule node is the node in the lexicographic tree of rule nodes
// (the "rule tree") that indicates which style rules are used to
// compute the style data, and in what cascading order. The least
// specific rule matched is the one whose rule node is a child of the
// root of the rule tree, and the most specific rule matched is the
// |mRule| member of the rule node.
// Underlying pointer without any strong ownership semantics.
struct NonOwningStyleContextSource
{
MOZ_IMPLICIT NonOwningStyleContextSource(nsRuleNode* aRuleNode)
: mBits(reinterpret_cast<uintptr_t>(aRuleNode)) {}
bool operator==(const NonOwningStyleContextSource& aOther) const {
return mBits == aOther.mBits;
}
bool operator!=(const NonOwningStyleContextSource& aOther) const {
return !(*this == aOther);
}
bool IsNull() const { return !mBits; }
nsRuleNode* AsGeckoRuleNode() const {
return reinterpret_cast<nsRuleNode*>(mBits);
}
bool MatchesNoRules() const {
return AsGeckoRuleNode()->IsRoot();
}
private:
uintptr_t mBits;
};
// Higher-level struct that owns a strong reference to the source. The source
// is never null.
struct OwningStyleContextSource
{
explicit OwningStyleContextSource(already_AddRefed<nsRuleNode> aRuleNode)
: mRaw(aRuleNode.take())
{
MOZ_COUNT_CTOR(OwningStyleContextSource);
MOZ_ASSERT(!mRaw.IsNull());
};
OwningStyleContextSource(OwningStyleContextSource&& aOther)
: mRaw(aOther.mRaw)
{
MOZ_COUNT_CTOR(OwningStyleContextSource);
aOther.mRaw = nullptr;
}
OwningStyleContextSource& operator=(OwningStyleContextSource&) = delete;
OwningStyleContextSource(OwningStyleContextSource&) = delete;
~OwningStyleContextSource() {
MOZ_COUNT_DTOR(OwningStyleContextSource);
if (mRaw.IsNull()) {
// We must have invoked the move constructor.
} else {
RefPtr<nsRuleNode> releaseme = dont_AddRef(AsGeckoRuleNode());
}
}
bool operator==(const OwningStyleContextSource& aOther) const {
return mRaw == aOther.mRaw;
}
bool operator!=(const OwningStyleContextSource& aOther) const {
return !(*this == aOther);
}
bool IsNull() const { return mRaw.IsNull(); }
NonOwningStyleContextSource AsRaw() const { return mRaw; }
nsRuleNode* AsGeckoRuleNode() const { return mRaw.AsGeckoRuleNode(); }
bool MatchesNoRules() const { return mRaw.MatchesNoRules(); }
private:
NonOwningStyleContextSource mRaw;
};
} // namespace mozilla
#endif // mozilla_StyleContextSource_h

View file

@ -90,7 +90,6 @@ EXPORTS.mozilla += [
'SheetType.h', 'SheetType.h',
'StyleAnimationValue.h', 'StyleAnimationValue.h',
'StyleComplexColor.h', 'StyleComplexColor.h',
'StyleContextSource.h',
'StyleSetHandle.h', 'StyleSetHandle.h',
'StyleSetHandleInlines.h', 'StyleSetHandleInlines.h',
'StyleSheet.h', 'StyleSheet.h',

View file

@ -76,14 +76,15 @@ static bool sExpensiveStyleStructAssertionsEnabled;
#endif #endif
nsStyleContext::nsStyleContext(nsStyleContext* aParent, nsStyleContext::nsStyleContext(nsStyleContext* aParent,
OwningStyleContextSource&& aSource,
nsIAtom* aPseudoTag, nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType) CSSPseudoElementType aPseudoType,
nsRuleNode* aRuleNode,
bool aSkipParentDisplayBasedStyleFixup)
: mParent(aParent) : mParent(aParent)
, mChild(nullptr) , mChild(nullptr)
, mEmptyChild(nullptr) , mEmptyChild(nullptr)
, mPseudoTag(aPseudoTag) , mPseudoTag(aPseudoTag)
, mSource(Move(aSource)) , mRuleNode(aRuleNode)
, mCachedResetData(nullptr) , mCachedResetData(nullptr)
, mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT) , mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT)
, mRefCnt(0) , mRefCnt(0)
@ -93,43 +94,14 @@ nsStyleContext::nsStyleContext(nsStyleContext* aParent,
#endif #endif
{ {
MOZ_COUNT_CTOR(nsStyleContext); MOZ_COUNT_CTOR(nsStyleContext);
}
nsStyleContext::nsStyleContext(nsStyleContext* aParent,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
already_AddRefed<nsRuleNode> aRuleNode,
bool aSkipParentDisplayBasedStyleFixup)
: nsStyleContext(aParent, OwningStyleContextSource(Move(aRuleNode)),
aPseudoTag, aPseudoType)
{
if (aParent) {
#ifdef DEBUG
nsRuleNode *r1 = mParent->RuleNode(), *r2 = mSource.AsGeckoRuleNode();
while (r1->GetParent())
r1 = r1->GetParent();
while (r2->GetParent())
r2 = r2->GetParent();
NS_ASSERTION(r1 == r2, "must be in the same rule tree as parent");
#endif
} else {
PresContext()->PresShell()->StyleSet()->RootStyleContextAdded();
}
mSource.AsGeckoRuleNode()->SetUsedDirectly(); // before ApplyStyleFixups()!
FinishConstruction(aSkipParentDisplayBasedStyleFixup);
}
void
nsStyleContext::FinishConstruction(bool aSkipParentDisplayBasedStyleFixup)
{
// This check has to be done "backward", because if it were written the // This check has to be done "backward", because if it were written the
// more natural way it wouldn't fail even when it needed to. // more natural way it wouldn't fail even when it needed to.
static_assert((UINT64_MAX >> NS_STYLE_CONTEXT_TYPE_SHIFT) >= static_assert((UINT64_MAX >> NS_STYLE_CONTEXT_TYPE_SHIFT) >=
static_cast<CSSPseudoElementTypeBase>( static_cast<CSSPseudoElementTypeBase>(
CSSPseudoElementType::MAX), CSSPseudoElementType::MAX),
"pseudo element bits no longer fit in a uint64_t"); "pseudo element bits no longer fit in a uint64_t");
MOZ_ASSERT(!mSource.IsNull()); MOZ_ASSERT(aRuleNode);
#ifdef DEBUG #ifdef DEBUG
static_assert(MOZ_ARRAY_LENGTH(nsStyleContext::sDependencyTable) static_assert(MOZ_ARRAY_LENGTH(nsStyleContext::sDependencyTable)
@ -141,8 +113,20 @@ nsStyleContext::FinishConstruction(bool aSkipParentDisplayBasedStyleFixup)
mPrevSibling = this; mPrevSibling = this;
if (mParent) { if (mParent) {
mParent->AddChild(this); mParent->AddChild(this);
#ifdef DEBUG
nsRuleNode *r1 = mParent->RuleNode(), *r2 = aRuleNode;
while (r1->GetParent())
r1 = r1->GetParent();
while (r2->GetParent())
r2 = r2->GetParent();
NS_ASSERTION(r1 == r2, "must be in the same rule tree as parent");
#endif
} else {
PresContext()->PresShell()->StyleSet()->RootStyleContextAdded();
} }
mRuleNode->SetUsedDirectly(); // before ApplyStyleFixups()!
SetStyleBits(); SetStyleBits();
ApplyStyleFixups(aSkipParentDisplayBasedStyleFixup); ApplyStyleFixups(aSkipParentDisplayBasedStyleFixup);
@ -291,7 +275,7 @@ void nsStyleContext::AddChild(nsStyleContext* aChild)
aChild->mNextSibling == aChild, aChild->mNextSibling == aChild,
"child already in a child list"); "child already in a child list");
nsStyleContext **listPtr = aChild->mSource.MatchesNoRules() ? &mEmptyChild : &mChild; nsStyleContext **listPtr = aChild->mRuleNode->IsRoot() ? &mEmptyChild : &mChild;
// Explicitly dereference listPtr so that compiler doesn't have to know that mNextSibling // Explicitly dereference listPtr so that compiler doesn't have to know that mNextSibling
// etc. don't alias with what ever listPtr points at. // etc. don't alias with what ever listPtr points at.
nsStyleContext *list = *listPtr; nsStyleContext *list = *listPtr;
@ -311,7 +295,7 @@ void nsStyleContext::RemoveChild(nsStyleContext* aChild)
{ {
NS_PRECONDITION(nullptr != aChild && this == aChild->mParent, "bad argument"); NS_PRECONDITION(nullptr != aChild && this == aChild->mParent, "bad argument");
nsStyleContext **list = aChild->mSource.MatchesNoRules() ? &mEmptyChild : &mChild; nsStyleContext **list = aChild->mRuleNode->IsRoot() ? &mEmptyChild : &mChild;
if (aChild->mPrevSibling != aChild) { // has siblings if (aChild->mPrevSibling != aChild) { // has siblings
if ((*list) == aChild) { if ((*list) == aChild) {
@ -377,27 +361,27 @@ nsStyleContext::MoveTo(nsStyleContext* aNewParent)
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
nsStyleContext::FindChildWithRules(const nsIAtom* aPseudoTag, nsStyleContext::FindChildWithRules(const nsIAtom* aPseudoTag,
NonOwningStyleContextSource aSource, nsRuleNode* aRuleNode,
NonOwningStyleContextSource aSourceIfVisited, nsRuleNode* aRulesIfVisited,
bool aRelevantLinkVisited) bool aRelevantLinkVisited)
{ {
uint32_t threshold = 10; // The # of siblings we're willing to examine uint32_t threshold = 10; // The # of siblings we're willing to examine
// before just giving this whole thing up. // before just giving this whole thing up.
RefPtr<nsStyleContext> result; RefPtr<nsStyleContext> result;
nsStyleContext *list = aSource.MatchesNoRules() ? mEmptyChild : mChild; nsStyleContext *list = aRuleNode->IsRoot() ? mEmptyChild : mChild;
if (list) { if (list) {
nsStyleContext *child = list; nsStyleContext *child = list;
do { do {
if (child->mSource.AsRaw() == aSource && if (child->mRuleNode == aRuleNode &&
child->mPseudoTag == aPseudoTag && child->mPseudoTag == aPseudoTag &&
!child->IsStyleIfVisited() && !child->IsStyleIfVisited() &&
child->RelevantLinkVisited() == aRelevantLinkVisited) { child->RelevantLinkVisited() == aRelevantLinkVisited) {
bool match = false; bool match = false;
if (!aSourceIfVisited.IsNull()) { if (aRulesIfVisited) {
match = child->GetStyleIfVisited() && match = child->GetStyleIfVisited() &&
child->GetStyleIfVisited()->mSource.AsRaw() == aSourceIfVisited; child->GetStyleIfVisited()->mRuleNode == aRulesIfVisited;
} else { } else {
match = !child->GetStyleIfVisited(); match = !child->GetStyleIfVisited();
} }
@ -430,9 +414,8 @@ const void* nsStyleContext::StyleData(nsStyleStructID aSID)
const void* cachedData = GetCachedStyleData(aSID); const void* cachedData = GetCachedStyleData(aSID);
if (cachedData) if (cachedData)
return cachedData; // We have computed data stored on this node in the context tree. return cachedData; // We have computed data stored on this node in the context tree.
// Our style source will take care of it for us. // Our rule node will take care of it for us.
const void* newData; const void* newData = mRuleNode->GetStyleData(aSID, this, true);
newData = mSource.AsGeckoRuleNode()->GetStyleData(aSID, this, true);
if (!nsCachedStyleData::IsReset(aSID)) { if (!nsCachedStyleData::IsReset(aSID)) {
// always cache inherited data on the style context; the rule // always cache inherited data on the style context; the rule
// node set the bit in mBits for us if needed. // node set the bit in mBits for us if needed.
@ -918,12 +901,12 @@ nsStyleContext::CalcStyleDifferenceInternal(StyleContextLike* aNewContext,
// we could later get a small change in one of those structs that we // we could later get a small change in one of those structs that we
// don't want to miss. // don't want to miss.
// If our sources are the same, then any differences in style data // If our rule nodes are the same, then any differences in style data
// are already accounted for by differences on ancestors. We know // are already accounted for by differences on ancestors. We know
// this because CalcStyleDifference is always called on two style // this because CalcStyleDifference is always called on two style
// contexts that point to the same element, so we know that our // contexts that point to the same element, so we know that our
// position in the style context tree is the same and our position in // position in the style context tree is the same and our position in
// the rule node tree (if applicable) is also the same. // the rule node tree is also the same.
// However, if there were noninherited style change hints on the // However, if there were noninherited style change hints on the
// parent, we might produce these same noninherited hints on this // parent, we might produce these same noninherited hints on this
// style context's frame due to 'inherit' values, so we do need to // style context's frame due to 'inherit' values, so we do need to
@ -931,13 +914,13 @@ nsStyleContext::CalcStyleDifferenceInternal(StyleContextLike* aNewContext,
// (Things like 'em' units are handled by the change hint produced // (Things like 'em' units are handled by the change hint produced
// by font-size changing, so we don't need to worry about them like // by font-size changing, so we don't need to worry about them like
// we worry about 'inherit' values.) // we worry about 'inherit' values.)
bool compare = StyleSource() != aNewContext->StyleSource(); bool compare = mRuleNode != aNewContext->mRuleNode;
DebugOnly<uint32_t> structsFound = 0; DebugOnly<uint32_t> structsFound = 0;
// If we had any change in variable values, then we'll need to examine // If we had any change in variable values, then we'll need to examine
// all of the other style structs too, even if the new style context has // all of the other style structs too, even if the new style context has
// the same source as the old one. // the same rule node as the old one.
const nsStyleVariables* thisVariables = PeekStyleVariables(); const nsStyleVariables* thisVariables = PeekStyleVariables();
if (thisVariables) { if (thisVariables) {
structsFound |= NS_STYLE_INHERIT_BIT(Variables); structsFound |= NS_STYLE_INHERIT_BIT(Variables);
@ -1249,10 +1232,10 @@ void nsStyleContext::List(FILE* out, int32_t aIndent, bool aListDescendants)
str.Append(' '); str.Append(' ');
} }
if (mSource.AsGeckoRuleNode()) { if (mRuleNode) {
fprintf_stderr(out, "%s{\n", str.get()); fprintf_stderr(out, "%s{\n", str.get());
str.Truncate(); str.Truncate();
nsRuleNode* ruleNode = mSource.AsGeckoRuleNode(); nsRuleNode* ruleNode = mRuleNode;
while (ruleNode) { while (ruleNode) {
nsIStyleRule *styleRule = ruleNode->GetRule(); nsIStyleRule *styleRule = ruleNode->GetRule();
if (styleRule) { if (styleRule) {
@ -1325,7 +1308,7 @@ NS_NewStyleContext(nsStyleContext* aParentContext,
RefPtr<nsRuleNode> node = aRuleNode; RefPtr<nsRuleNode> node = aRuleNode;
RefPtr<nsStyleContext> context = RefPtr<nsStyleContext> context =
new (aRuleNode->PresContext()) new (aRuleNode->PresContext())
nsStyleContext(aParentContext, aPseudoTag, aPseudoType, node.forget(), nsStyleContext(aParentContext, aPseudoTag, aPseudoType, aRuleNode,
aSkipParentDisplayBasedStyleFixup); aSkipParentDisplayBasedStyleFixup);
return context.forget(); return context.forget();
} }

View file

@ -10,9 +10,9 @@
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/RestyleLogging.h" #include "mozilla/RestyleLogging.h"
#include "mozilla/StyleContextSource.h"
#include "nsCSSAnonBoxes.h" #include "nsCSSAnonBoxes.h"
#include "nsStyleSet.h" #include "nsStyleSet.h"
#include "nsRuleNode.h"
class nsIAtom; class nsIAtom;
class nsPresContext; class nsPresContext;
@ -70,7 +70,7 @@ public:
*/ */
nsStyleContext(nsStyleContext* aParent, nsIAtom* aPseudoTag, nsStyleContext(nsStyleContext* aParent, nsIAtom* aPseudoTag,
mozilla::CSSPseudoElementType aPseudoType, mozilla::CSSPseudoElementType aPseudoType,
already_AddRefed<nsRuleNode> aRuleNode, nsRuleNode* aRuleNode,
bool aSkipParentDisplayBasedStyleFixup); bool aSkipParentDisplayBasedStyleFixup);
void* operator new(size_t sz, nsPresContext* aPresContext); void* operator new(size_t sz, nsPresContext* aPresContext);
@ -135,9 +135,7 @@ public:
return mRefCnt == 1; return mRefCnt == 1;
} }
nsPresContext* PresContext() const { nsPresContext* PresContext() const { return mRuleNode->PresContext(); }
return mSource.AsGeckoRuleNode()->PresContext();
}
nsStyleContext* GetParent() const { return mParent; } nsStyleContext* GetParent() const { return mParent; }
@ -156,14 +154,14 @@ public:
// Find, if it already exists *and is easily findable* (i.e., near the // Find, if it already exists *and is easily findable* (i.e., near the
// start of the child list), a style context whose: // start of the child list), a style context whose:
// * GetPseudo() matches aPseudoTag // * GetPseudo() matches aPseudoTag
// * mSource matches aSource // * RuleNode() matches aRules
// * !!GetStyleIfVisited() == !!aSourceIfVisited, and, if they're // * !GetStyleIfVisited() == !aRulesIfVisited, and, if they're
// non-null, GetStyleIfVisited()->mSource == aSourceIfVisited // non-null, GetStyleIfVisited()->RuleNode() == aRulesIfVisited
// * RelevantLinkVisited() == aRelevantLinkVisited // * RelevantLinkVisited() == aRelevantLinkVisited
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
FindChildWithRules(const nsIAtom* aPseudoTag, FindChildWithRules(const nsIAtom* aPseudoTag,
mozilla::NonOwningStyleContextSource aSource, nsRuleNode* aRules,
mozilla::NonOwningStyleContextSource aSourceIfVisited, nsRuleNode* aRulesIfVisited,
bool aRelevantLinkVisited); bool aRelevantLinkVisited);
// Does this style context or any of its ancestors have text // Does this style context or any of its ancestors have text
@ -289,9 +287,7 @@ public:
return mBits & nsCachedStyleData::GetBitForSID(aSID); return mBits & nsCachedStyleData::GetBitForSID(aSID);
} }
nsRuleNode* RuleNode() { nsRuleNode* RuleNode() { return mRuleNode; }
return mSource.AsGeckoRuleNode();
}
void AddStyleBit(const uint64_t& aBit) { mBits |= aBit; } void AddStyleBit(const uint64_t& aBit) { mBits |= aBit; }
@ -478,21 +474,10 @@ public:
return cachedData; return cachedData;
} }
mozilla::NonOwningStyleContextSource StyleSource() const { return mSource.AsRaw(); }
private: private:
// Private destructor, to discourage deletion outside of Release(): // Private destructor, to discourage deletion outside of Release():
~nsStyleContext(); ~nsStyleContext();
// Delegated Helper constructor.
nsStyleContext(nsStyleContext* aParent,
mozilla::OwningStyleContextSource&& aSource,
nsIAtom* aPseudoTag,
mozilla::CSSPseudoElementType aPseudoType);
// Helper post-contruct hook.
void FinishConstruction(bool aSkipParentDisplayBasedStyleFixup);
void AddChild(nsStyleContext* aChild); void AddChild(nsStyleContext* aChild);
void RemoveChild(nsStyleContext* aChild); void RemoveChild(nsStyleContext* aChild);
@ -547,9 +532,8 @@ private:
} \ } \
/* Have the rulenode deal */ \ /* Have the rulenode deal */ \
AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \ AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
const nsStyle##name_ * newData; \ const nsStyle##name_ * newData = \
newData = mSource.AsGeckoRuleNode()-> \ mRuleNode->GetStyle##name_<aComputeData>(this, mBits); \
GetStyle##name_<aComputeData>(this, mBits); \
/* always cache inherited data on the style context; the rule */ \ /* always cache inherited data on the style context; the rule */ \
/* node set the bit in mBits for us if needed. */ \ /* node set the bit in mBits for us if needed. */ \
mCachedInheritedData.mStyleStructs[eStyleStruct_##name_] = \ mCachedInheritedData.mStyleStructs[eStyleStruct_##name_] = \
@ -568,9 +552,8 @@ private:
} \ } \
/* Have the rulenode deal */ \ /* Have the rulenode deal */ \
AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \ AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
const nsStyle##name_ * newData; \ const nsStyle##name_ * newData = \
newData = mSource.AsGeckoRuleNode()-> \ mRuleNode->GetStyle##name_<aComputeData>(this); \
GetStyle##name_<aComputeData>(this); \
return newData; \ return newData; \
} }
#include "nsStyleStructList.h" #include "nsStyleStructList.h"
@ -616,10 +599,13 @@ private:
// the relevant atom. // the relevant atom.
nsCOMPtr<nsIAtom> mPseudoTag; nsCOMPtr<nsIAtom> mPseudoTag;
// The source for our style data, a nsRuleNode struct. // The rule node is the node in the lexicographic tree of rule nodes
// This never changes after construction, except // (the "rule tree") that indicates which style rules are used to
// when it's released and nulled out during teardown. // compute the style data, and in what cascading order. The least
const mozilla::OwningStyleContextSource mSource; // specific rule matched is the one whose rule node is a child of the
// root of the rule tree, and the most specific rule matched is the
// |mRule| member of |mRuleNode|.
const RefPtr<nsRuleNode> mRuleNode;
// mCachedInheritedData and mCachedResetData point to both structs that // mCachedInheritedData and mCachedResetData point to both structs that
// are owned by this style context and structs that are owned by one of // are owned by this style context and structs that are owned by one of