--- a/layout/style/GeckoStyleContext.cpp
+++ b/layout/style/GeckoStyleContext.cpp
@@ -17,37 +17,37 @@
using namespace mozilla;
GeckoStyleContext::GeckoStyleContext(nsStyleContext* aParent,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
already_AddRefed<nsRuleNode> aRuleNode,
bool aSkipParentDisplayBasedStyleFixup)
- : nsStyleContext(aParent, OwningStyleContextSource(Move(aRuleNode)),
- aPseudoTag, aPseudoType)
+ : nsStyleContext(aParent, aPseudoTag, aPseudoType)
, mChild(nullptr)
, mEmptyChild(nullptr)
+ , mRuleNode(Move(aRuleNode))
{
mBits |= NS_STYLE_CONTEXT_IS_GECKO;
if (aParent) {
#ifdef DEBUG
- nsRuleNode *r1 = mParent->RuleNode(), *r2 = mSource.AsGeckoRuleNode();
+ nsRuleNode *r1 = mParent->RuleNode(), *r2 = mRuleNode;
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()!
+ mRuleNode->SetUsedDirectly(); // before ApplyStyleFixups()!
// FinishConstruction() calls AddChild which needs these
// to be initialized!
mNextSibling = this;
mPrevSibling = this;
FinishConstruction();
ApplyStyleFixups(aSkipParentDisplayBasedStyleFixup);
}
@@ -66,17 +66,23 @@ GeckoStyleContext::operator new(size_t s
void
GeckoStyleContext::AddChild(GeckoStyleContext* aChild)
{
NS_ASSERTION(aChild->mPrevSibling == aChild &&
aChild->mNextSibling == aChild,
"child already in a child list");
- GeckoStyleContext **listPtr = aChild->mSource.MatchesNoRules() ? &mEmptyChild : &mChild;
+ GeckoStyleContext **listPtr = aChild->mRuleNode->IsRoot() ? &mEmptyChild : &mChild;
+ if (const nsRuleNode* source = aChild->mRuleNode) {
+ if (source->IsRoot()) {
+ listPtr = &mEmptyChild;
+ }
+ }
+
// Explicitly dereference listPtr so that compiler doesn't have to know that mNextSibling
// etc. don't alias with what ever listPtr points at.
GeckoStyleContext *list = *listPtr;
// Insert at the beginning of the list. See also FindChildWithRules.
if (list) {
// Link into existing elements, if there are any.
aChild->mNextSibling = list;
@@ -87,17 +93,18 @@ GeckoStyleContext::AddChild(GeckoStyleCo
(*listPtr) = aChild;
}
void
GeckoStyleContext::RemoveChild(GeckoStyleContext* aChild)
{
NS_PRECONDITION(nullptr != aChild && this == aChild->mParent, "bad argument");
- GeckoStyleContext **list = aChild->mSource.MatchesNoRules() ? &mEmptyChild : &mChild;
+ MOZ_ASSERT(aChild->mRuleNode, "child context should have rule node");
+ GeckoStyleContext **list = aChild->mRuleNode->IsRoot() ? &mEmptyChild : &mChild;
if (aChild->mPrevSibling != aChild) { // has siblings
if ((*list) == aChild) {
(*list) = (*list)->mNextSibling;
}
}
else {
NS_ASSERTION((*list) == aChild, "bad sibling pointers");
@@ -184,40 +191,40 @@ GeckoStyleContext::DoClearCachedInherite
if (aStructs == 0) {
return;
}
ClearCachedInheritedStyleDataOnDescendants(aStructs);
}
-
already_AddRefed<GeckoStyleContext>
GeckoStyleContext::FindChildWithRules(const nsIAtom* aPseudoTag,
- NonOwningStyleContextSource aSource,
- NonOwningStyleContextSource aSourceIfVisited,
+ nsRuleNode* aSource,
+ nsRuleNode* aSourceIfVisited,
bool aRelevantLinkVisited)
{
uint32_t threshold = 10; // The # of siblings we're willing to examine
// before just giving this whole thing up.
RefPtr<GeckoStyleContext> result;
- GeckoStyleContext *list = aSource.MatchesNoRules() ? mEmptyChild : mChild;
+ MOZ_ASSERT(aSource);
+ GeckoStyleContext *list = aSource->IsRoot() ? mEmptyChild : mChild;
if (list) {
GeckoStyleContext *child = list;
do {
- if (child->mSource.AsRaw() == aSource &&
+ if (child->StyleSource() == aSource &&
child->mPseudoTag == aPseudoTag &&
!child->IsStyleIfVisited() &&
child->RelevantLinkVisited() == aRelevantLinkVisited) {
bool match = false;
- if (!aSourceIfVisited.IsNull()) {
+ if (aSourceIfVisited) {
match = child->GetStyleIfVisited() &&
- child->GetStyleIfVisited()->AsGecko()->mSource.AsRaw() == aSourceIfVisited;
+ child->GetStyleIfVisited()->RuleNode() == aSourceIfVisited;
} else {
match = !child->GetStyleIfVisited();
}
if (match && !(child->mBits & NS_STYLE_INELIGIBLE_FOR_SHARING)) {
result = child;
break;
}
}
@@ -343,16 +350,17 @@ GeckoStyleContext::SetIneligibleForShari
GeckoStyleContext* child = mEmptyChild;
do {
child->SetIneligibleForSharing();
child = child->mNextSibling;
} while (mEmptyChild != child);
}
}
+#ifdef RESTYLE_LOGGING
void
GeckoStyleContext::LogChildStyleContextTree(uint32_t aStructs) const
{
if (nullptr != mChild) {
GeckoStyleContext* child = mChild;
do {
child->LogStyleContextTree(false, aStructs);
child = child->mNextSibling;
@@ -361,16 +369,17 @@ GeckoStyleContext::LogChildStyleContextT
if (nullptr != mEmptyChild) {
GeckoStyleContext* child = mEmptyChild;
do {
child->LogStyleContextTree(false, aStructs);
child = child->mNextSibling;
} while (mEmptyChild != child);
}
}
+#endif
static bool
ShouldSuppressLineBreak(const nsStyleContext* aContext,
const nsStyleDisplay* aDisplay,
const nsStyleContext* aParentContext,
const nsStyleDisplay* aParentDisplay)
{
// The display change should only occur for "in-flow" children
@@ -506,19 +515,16 @@ GeckoStyleContext::AssertChildStructsNot
} while (child != mEmptyChild);
}
}
#endif
void
GeckoStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup)
{
- MOZ_ASSERT(!mSource.IsServoComputedValues(),
- "Can't do Gecko style fixups on Servo values");
-
#define GET_UNIQUE_STYLE_DATA(name_) \
static_cast<nsStyle##name_*>(GetUniqueStyleData(eStyleStruct_##name_))
// CSS Inline Layout Level 3 - 3.5 Sizing Initial Letters:
// For an N-line drop initial in a Western script, the cap-height of the
// letter needs to be (N – 1) times the line-height, plus the cap-height
// of the surrounding text.
if (mPseudoTag == nsCSSPseudoElements::firstLetter) {
@@ -732,19 +738,19 @@ GeckoStyleContext::ApplyStyleFixups(bool
* If a box has a different block flow direction than its containing block:
* * If the box has a specified display of inline, its display computes
* to inline-block. [CSS21]
* ...etc.
*/
if (disp->mDisplay == mozilla::StyleDisplay::Inline &&
!nsCSSAnonBoxes::IsNonElement(mPseudoTag) &&
mParent) {
- auto cbContext = mParent;
+ auto cbContext = GetParent();
while (cbContext->StyleDisplay()->mDisplay == mozilla::StyleDisplay::Contents) {
- cbContext = cbContext->mParent;
+ cbContext = cbContext->GetParent();
}
MOZ_ASSERT(cbContext, "the root context can't have display:contents");
// We don't need the full mozilla::WritingMode value (incorporating dir
// and text-orientation) here; just the writing-mode property is enough.
if (StyleVisibility()->mWritingMode !=
cbContext->StyleVisibility()->mWritingMode) {
nsStyleDisplay* mutable_display = GET_UNIQUE_STYLE_DATA(Display);
disp = mutable_display;
@@ -757,9 +763,9 @@ GeckoStyleContext::ApplyStyleFixups(bool
StyleUserInterface();
#undef GET_UNIQUE_STYLE_DATA
}
bool
GeckoStyleContext::HasNoChildren() const
{
return (nullptr == mChild) && (nullptr == mEmptyChild);
-}
\ No newline at end of file
+}
--- a/layout/style/GeckoStyleContext.h
+++ b/layout/style/GeckoStyleContext.h
@@ -17,73 +17,91 @@ public:
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
already_AddRefed<nsRuleNode> aRuleNode,
bool aSkipParentDisplayBasedStyleFixup);
void* operator new(size_t sz, nsPresContext* aPresContext);
nsPresContext* PresContext() const {
- return mSource.AsGeckoRuleNode()->PresContext();
+ return RuleNode()->PresContext();
}
void AddChild(GeckoStyleContext* aChild);
void RemoveChild(GeckoStyleContext* aChild);
void* GetUniqueStyleData(const nsStyleStructID& aSID);
void* CreateEmptyStyleData(const nsStyleStructID& aSID);
/**
* Sets the NS_STYLE_INELIGIBLE_FOR_SHARING bit on this style context
* and its descendants. If it finds a descendant that has the bit
* already set, assumes that it can skip that subtree.
*/
void SetIneligibleForSharing();
- void LogChildStyleContextTree(uint32_t aStructs) const;
/**
* On each descendant of this style context, clears out any cached inherited
* structs indicated in aStructs.
*/
void ClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
// Find, if it already exists *and is easily findable* (i.e., near the
// start of the child list), a style context whose:
// * GetPseudo() matches aPseudoTag
- // * mSource matches aSource
+ // * mRuleNode matches aSource
// * !!GetStyleIfVisited() == !!aSourceIfVisited, and, if they're
- // non-null, GetStyleIfVisited()->mSource == aSourceIfVisited
+ // non-null, GetStyleIfVisited()->mRuleNode == aSourceIfVisited
// * RelevantLinkVisited() == aRelevantLinkVisited
already_AddRefed<GeckoStyleContext>
FindChildWithRules(const nsIAtom* aPseudoTag,
- mozilla::NonOwningStyleContextSource aSource,
- mozilla::NonOwningStyleContextSource aSourceIfVisited,
+ nsRuleNode* aSource,
+ nsRuleNode* aSourceIfVisited,
bool aRelevantLinkVisited);
#ifdef DEBUG
void AssertChildStructsNotUsedElsewhere(nsStyleContext* aDestroyingContext,
int32_t aLevels) const;
void ListDescendants(FILE* out, int32_t aIndent);
+
+#endif
+
+#ifdef RESTYLE_LOGGING
+ void LogChildStyleContextTree(uint32_t aStructs) const;
#endif
// Only called for Gecko-backed nsStyleContexts.
void ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup);
bool HasNoChildren() const;
+ NonOwningStyleContextSource StyleSource() const {
+ return NonOwningStyleContextSource(mRuleNode);
+ }
+
+ nsRuleNode* RuleNode() const {
+ MOZ_ASSERT(mRuleNode);
+ return mRuleNode;
+ }
+
+ ~GeckoStyleContext() {
+ Destructor();
+ }
+
private:
// Helper for ClearCachedInheritedStyleDataOnDescendants.
void DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
// Children are kept in two circularly-linked lists. The list anchor
// is not part of the list (null for empty), and we point to the first
// child.
// mEmptyChild for children whose rule node is the root rule node, and
// mChild for other children. The order of children is not
// meaningful.
GeckoStyleContext* mChild;
GeckoStyleContext* mEmptyChild;
GeckoStyleContext* mPrevSibling;
GeckoStyleContext* mNextSibling;
+ RefPtr<nsRuleNode> mRuleNode;
};
}
#endif // mozilla_GeckoStyleContext_h
--- a/layout/style/ServoStyleContext.cpp
+++ b/layout/style/ServoStyleContext.cpp
@@ -13,18 +13,18 @@
using namespace mozilla;
ServoStyleContext::ServoStyleContext(nsStyleContext* aParent,
nsPresContext* aPresContext,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
already_AddRefed<ServoComputedValues> aComputedValues)
- : nsStyleContext(aParent, OwningStyleContextSource(Move(aComputedValues)),
- aPseudoTag, aPseudoType)
+ : nsStyleContext(aParent, aPseudoTag, aPseudoType),
+ mSource(Move(aComputedValues))
{
mPresContext = aPresContext;
FinishConstruction();
// No need to call ApplyStyleFixups here, since fixups are handled by Servo when
// producing the ServoComputedValues.
}
--- a/layout/style/ServoStyleContext.h
+++ b/layout/style/ServoStyleContext.h
@@ -18,15 +18,25 @@ public:
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
already_AddRefed<ServoComputedValues> aComputedValues);
nsPresContext* PresContext() const {
return mPresContext;
}
+ NonOwningStyleContextSource StyleSource() const {
+ return NonOwningStyleContextSource(mSource);
+ }
+ ServoComputedValues* ComputedValues() const {
+ return mSource;
+ }
+ ~ServoStyleContext() {
+ Destructor();
+ }
private:
nsPresContext* mPresContext;
+ RefPtr<ServoComputedValues> mSource;
};
}
#endif // mozilla_ServoStyleContext_h
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -33,16 +33,17 @@
#include "mozilla/KeyframeUtils.h" // KeyframeUtils::ParseProperty
#include "mozilla/Likely.h"
#include "mozilla/ServoBindings.h" // RawServoDeclarationBlock
#include "gfxMatrix.h"
#include "gfxQuaternion.h"
#include "nsIDocument.h"
#include "nsIFrame.h"
#include "gfx2DGlue.h"
+#include "nsStyleContextInlines.h"
using namespace mozilla;
using namespace mozilla::css;
using namespace mozilla::gfx;
using nsStyleTransformMatrix::Decompose2DMatrix;
using nsStyleTransformMatrix::Decompose3DMatrix;
using nsStyleTransformMatrix::ShearType;
--- a/layout/style/StyleContextSource.h
+++ b/layout/style/StyleContextSource.h
@@ -65,97 +65,15 @@ struct NonOwningStyleContextSource
return reinterpret_cast<nsRuleNode*>(mBits);
}
const ServoComputedValues* AsServoComputedValues() const {
MOZ_ASSERT(IsServoComputedValues());
return reinterpret_cast<ServoComputedValues*>(mBits & ~1);
}
- bool MatchesNoRules() const {
- if (IsGeckoRuleNodeOrNull()) {
- return AsGeckoRuleNode()->IsRoot();
- }
-
- // Just assume a Servo-backed StyleContextSource always matches some rules.
- //
- // MatchesNoRules is used to ensure style contexts that match no rules
- // go into a separate mEmptyChild list on their parent. This is only used
- // as an optimization so that calling FindChildWithRules for style context
- // sharing is faster for text nodes (which match no rules, and are common).
- // Since Servo will handle sharing for us, there's no need to split children
- // into two lists.
- return false;
- }
-
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());
- };
-
- explicit OwningStyleContextSource(already_AddRefed<ServoComputedValues> aComputedValues)
- : mRaw(aComputedValues.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 if (IsGeckoRuleNode()) {
- RefPtr<nsRuleNode> releaseme = dont_AddRef(AsGeckoRuleNode());
- } else {
- MOZ_ASSERT(IsServoComputedValues());
- RefPtr<ServoComputedValues> releaseme =
- dont_AddRef(AsServoComputedValues());
- }
- }
-
- 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(); }
- bool IsGeckoRuleNode() const {
- MOZ_ASSERT(!mRaw.IsNull());
- return mRaw.IsGeckoRuleNodeOrNull();
- }
- bool IsServoComputedValues() const { return mRaw.IsServoComputedValues(); }
-
- NonOwningStyleContextSource AsRaw() const { return mRaw; }
- nsRuleNode* AsGeckoRuleNode() const { return mRaw.AsGeckoRuleNode(); }
- ServoComputedValues* AsServoComputedValues() const {
- return const_cast<ServoComputedValues*>(mRaw.AsServoComputedValues());
- }
-
- bool MatchesNoRules() const { return mRaw.MatchesNoRules(); }
-
-private:
- NonOwningStyleContextSource mRaw;
-};
-
} // namespace mozilla
#endif // mozilla_StyleContextSource_h
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -46,16 +46,17 @@
#include "nsDisplayList.h"
#include "nsDOMCSSDeclaration.h"
#include "nsStyleTransformMatrix.h"
#include "mozilla/dom/Element.h"
#include "prtime.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/AppUnits.h"
#include <algorithm>
+#include "nsStyleContextInlines.h"
using namespace mozilla;
using namespace mozilla::dom;
#if defined(DEBUG_bzbarsky) || defined(DEBUG_caillon)
#define DEBUG_ComputedDOMStyle
#endif
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -77,22 +77,20 @@ const uint32_t nsStyleContext::sDependen
#undef STYLE_STRUCT_END
};
// Whether to perform expensive assertions in the nsStyleContext destructor.
static bool sExpensiveStyleStructAssertionsEnabled;
#endif
nsStyleContext::nsStyleContext(nsStyleContext* aParent,
- OwningStyleContextSource&& aSource,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType)
: mParent(aParent)
, mPseudoTag(aPseudoTag)
- , mSource(Move(aSource))
, mCachedResetData(nullptr)
, mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT)
, mRefCnt(0)
#ifdef DEBUG
, mFrameRefCnt(0)
, mComputingStruct(nsStyleStructID_None)
#endif
{}
@@ -101,17 +99,17 @@ void
nsStyleContext::FinishConstruction()
{
// 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.
static_assert((UINT64_MAX >> NS_STYLE_CONTEXT_TYPE_SHIFT) >=
static_cast<CSSPseudoElementTypeBase>(
CSSPseudoElementType::MAX),
"pseudo element bits no longer fit in a uint64_t");
- MOZ_ASSERT(!mSource.IsNull());
+ MOZ_ASSERT(!StyleSource().IsNull());
#ifdef DEBUG
static_assert(MOZ_ARRAY_LENGTH(nsStyleContext::sDependencyTable)
== nsStyleStructID_Length,
"Number of items in dependency table doesn't match IDs");
#endif
if (mParent) {
@@ -121,25 +119,26 @@ nsStyleContext::FinishConstruction()
SetStyleBits();
#define eStyleStruct_LastItem (nsStyleStructID_Length - 1)
static_assert(NS_STYLE_INHERIT_MASK & NS_STYLE_INHERIT_BIT(LastItem),
"NS_STYLE_INHERIT_MASK must be bigger, and other bits shifted");
#undef eStyleStruct_LastItem
}
-nsStyleContext::~nsStyleContext()
+void
+nsStyleContext::Destructor()
{
if (const GeckoStyleContext* gecko = GetAsGecko()) {
NS_ASSERTION(gecko->HasNoChildren(), "destructing context with children");
}
- MOZ_ASSERT(!mSource.IsServoComputedValues() || !mCachedResetData);
+ MOZ_ASSERT(!IsServo() || !mCachedResetData);
#ifdef DEBUG
- if (mSource.IsServoComputedValues()) {
+ if (IsServo()) {
MOZ_ASSERT(!mCachedResetData,
"Servo shouldn't cache reset structs in nsStyleContext");
for (const auto* data : mCachedInheritedData.mStyleStructs) {
MOZ_ASSERT(!data,
"Servo shouldn't cache inherit structs in nsStyleContext");
}
}
@@ -158,17 +157,17 @@ nsStyleContext::~nsStyleContext()
// check just of the children of this style context.
AssertStructsNotUsedElsewhere(this, 2);
}
#endif
nsPresContext *presContext = PresContext();
DebugOnly<nsStyleSet*> geckoStyleSet = presContext->PresShell()->StyleSet()->GetAsGecko();
NS_ASSERTION(!geckoStyleSet ||
- geckoStyleSet->GetRuleTree() == mSource.AsGeckoRuleNode()->RuleTree() ||
+ geckoStyleSet->GetRuleTree() == AsGecko()->RuleNode()->RuleTree() ||
geckoStyleSet->IsInRuleTreeReconstruct(),
"destroying style context from old rule tree too late");
if (mParent) {
mParent->RemoveChild(this);
} else {
presContext->StyleSet()->RootStyleContextRemoved();
}
@@ -321,18 +320,18 @@ nsStyleContext::MoveTo(nsStyleContext* a
const void* nsStyleContext::StyleData(nsStyleStructID aSID)
{
const void* cachedData = GetCachedStyleData(aSID);
if (cachedData)
return cachedData; // We have computed data stored on this node in the context tree.
// Our style source will take care of it for us.
const void* newData;
- if (mSource.IsGeckoRuleNode()) {
- newData = mSource.AsGeckoRuleNode()->GetStyleData(aSID, this, true);
+ if (IsGecko()) {
+ newData = AsGecko()->RuleNode()->GetStyleData(aSID, this, true);
if (!nsCachedStyleData::IsReset(aSID)) {
// always cache inherited data on the style context; the rule
// node set the bit in mBits for us if needed.
mCachedInheritedData.mStyleStructs[aSID] = const_cast<void*>(newData);
}
} else {
newData = StyleStructFromServoComputedValues(aSID);
@@ -365,17 +364,17 @@ const void* nsStyleContext::StyleData(ns
SetStyle(aSID, const_cast<void*>(newData));
}
return newData;
}
void
nsStyleContext::SetStyle(nsStyleStructID aSID, void* aStruct)
{
- MOZ_ASSERT(!mSource.IsServoComputedValues(),
+ MOZ_ASSERT(!IsServo(),
"Servo shouldn't cache style structs in the style context!");
// This method should only be called from nsRuleNode! It is not a public
// method!
NS_ASSERTION(aSID >= 0 && aSID < nsStyleStructID_Length, "out of bounds");
// NOTE: nsCachedStyleData::GetStyleData works roughly the same way.
// See the comments there (in nsRuleNode.h) for more details about
@@ -438,29 +437,29 @@ nsStyleContext::CalcStyleDifferenceInter
DebugOnly<int> styleStructCount = 1; // count Variables already
// Servo's optimization to stop the cascade when there are no style changes
// that children need to be recascade for relies on comparing all of the
// structs, not just those that are returned from PeekStyleData, although
// if PeekStyleData does return null we still don't want to accumulate
// any change hints for those structs.
- bool checkUnrequestedServoStructs = mSource.IsServoComputedValues();
+ bool checkUnrequestedServoStructs = IsServo();
#define EXPAND(...) __VA_ARGS__
#define DO_STRUCT_DIFFERENCE_WITH_ARGS(struct_, extra_args_) \
PR_BEGIN_MACRO \
const nsStyle##struct_* this##struct_ = PeekStyle##struct_(); \
bool unrequestedStruct; \
if (this##struct_) { \
unrequestedStruct = false; \
structsFound |= NS_STYLE_INHERIT_BIT(struct_); \
} else if (checkUnrequestedServoStructs) { \
this##struct_ = \
- Servo_GetStyle##struct_(mSource.AsServoComputedValues()); \
+ Servo_GetStyle##struct_(AsServo()->ComputedValues()); \
unrequestedStruct = true; \
} else { \
unrequestedStruct = false; \
} \
if (this##struct_) { \
const nsStyle##struct_* other##struct_ = aNewContext->Style##struct_(); \
if (this##struct_ == other##struct_) { \
/* The very same struct, so we know that there will be no */ \
@@ -703,17 +702,17 @@ nsStyleContext::EnsureSameStructsCached(
#define STYLE_STRUCT(name_, checkdata_cb_) \
if (aOldContext->PeekStyle##name_()) { \
Style##name_(); \
}
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
#ifdef DEBUG
- if (mSource.IsServoComputedValues()) {
+ if (IsServo()) {
auto oldMask = aOldContext->mBits & NS_STYLE_INHERIT_MASK;
auto newMask = mBits & NS_STYLE_INHERIT_MASK;
MOZ_ASSERT((oldMask & newMask) == oldMask,
"Should have at least as many structs computed as the "
"old context!");
}
#endif
}
@@ -731,22 +730,21 @@ void nsStyleContext::List(FILE* out, int
(void*)this, mRefCnt, (void *)mParent));
if (mPseudoTag) {
nsAutoString buffer;
mPseudoTag->ToString(buffer);
AppendUTF16toUTF8(buffer, str);
str.Append(' ');
}
- if (mSource.IsServoComputedValues()) {
+ if (IsServo()) {
fprintf_stderr(out, "%s{ServoComputedValues}\n", str.get());
- } else if (mSource.IsGeckoRuleNode()) {
+ } else if (nsRuleNode* ruleNode = AsGecko()->RuleNode()) {
fprintf_stderr(out, "%s{\n", str.get());
str.Truncate();
- nsRuleNode* ruleNode = mSource.AsGeckoRuleNode();
while (ruleNode) {
nsIStyleRule *styleRule = ruleNode->GetRule();
if (styleRule) {
styleRule->List(out, aIndent + 1);
}
ruleNode = ruleNode->GetParent();
}
for (ix = aIndent; --ix >= 0; ) {
@@ -761,16 +759,40 @@ void nsStyleContext::List(FILE* out, int
if (aListDescendants) {
if (GeckoStyleContext* gecko = GetAsGecko()) {
gecko->ListDescendants(out, aIndent);
}
}
}
#endif
+NonOwningStyleContextSource
+nsStyleContext::StyleSource() const
+{
+ MOZ_STYLO_FORWARD(StyleSource, ())
+}
+
+#define STYLE_STRUCT(name_, checkdata_cb_) \
+const nsStyle##name_ * \
+nsStyleContext::Style##name_() { \
+ return DoGetStyle##name_<true>(); \
+} \
+const nsStyle##name_ * \
+nsStyleContext::ThreadsafeStyle##name_() { \
+ if (mozilla::ServoStyleSet::IsInServoTraversal()) { \
+ return Servo_GetStyle##name_(AsServo()->ComputedValues()); \
+ } \
+ return Style##name_(); \
+} \
+const nsStyle##name_ * nsStyleContext::PeekStyle##name_() { \
+ return DoGetStyle##name_<false>(); \
+}
+#include "nsStyleStructList.h"
+#undef STYLE_STRUCT
+
// Overridden to prevent the global delete from being called, since the memory
// came out of an nsIArena instead of the global delete operator's heap.
void
nsStyleContext::Destroy()
{
if (IsGecko()) {
// Get the pres context.
RefPtr<nsPresContext> presContext = PresContext();
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -126,17 +126,17 @@ public:
"do not call HasSingleReference on a newly created "
"nsStyleContext with no references yet");
return mRefCnt == 1;
}
nsPresContext* PresContext() const;
nsStyleContext* GetParent() const {
- MOZ_ASSERT(mSource.IsGeckoRuleNode(),
+ MOZ_ASSERT(IsGecko(),
"This should be used only in Gecko-backed style system!");
return mParent;
}
nsStyleContext* GetParentAllowServo() const {
return mParent;
}
@@ -274,20 +274,17 @@ public:
* given style struct and it does NOT own that struct. This can
* happen because it was inherited from the parent style context, or
* because it was stored conditionally on the rule node.
*/
bool HasCachedDependentStyleData(nsStyleStructID aSID) {
return mBits & nsCachedStyleData::GetBitForSID(aSID);
}
- nsRuleNode* RuleNode() {
- MOZ_RELEASE_ASSERT(mSource.IsGeckoRuleNode());
- return mSource.AsGeckoRuleNode();
- }
+ inline nsRuleNode* RuleNode();
void AddStyleBit(const uint64_t& aBit) { mBits |= aBit; }
/*
* Get the style data for a style struct. This is the most important
* member function of nsStyleContext. It fills in a const pointer
* to a style data struct that is appropriate for the style context's
* frame. This struct may be shared with other contexts (either in
@@ -306,52 +303,43 @@ public:
/**
* Define typesafe getter functions for each style struct by
* preprocessing the list of style structs. These functions are the
* preferred way to get style data. The macro creates functions like:
* const nsStyleBorder* StyleBorder();
* const nsStyleColor* StyleColor();
*/
- #define STYLE_STRUCT(name_, checkdata_cb_) \
- const nsStyle##name_ * Style##name_() MOZ_NONNULL_RETURN { \
- return DoGetStyle##name_<true>(); \
- }
+ #define STYLE_STRUCT(name_, checkdata_cb_) \
+ const nsStyle##name_ * Style##name_() MOZ_NONNULL_RETURN;
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
/**
* Equivalent to StyleFoo(), except that we skip the cache write during the
* servo traversal. This can cause incorrect behavior if used improperly,
* since we won't record that layout potentially depends on the values in
* this style struct. Use with care.
*/
- #define STYLE_STRUCT(name_, checkdata_cb_) \
- const nsStyle##name_ * ThreadsafeStyle##name_() { \
- if (mozilla::ServoStyleSet::IsInServoTraversal()) { \
- return Servo_GetStyle##name_(mSource.AsServoComputedValues()); \
- } \
- return Style##name_(); \
- }
+ #define STYLE_STRUCT(name_, checkdata_cb_) \
+ const nsStyle##name_ * ThreadsafeStyle##name_();
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
/**
* PeekStyle* is like Style* but doesn't trigger style
* computation if the data is not cached on either the style context
* or the rule node.
*
* Perhaps this shouldn't be a public nsStyleContext API.
*/
- #define STYLE_STRUCT(name_, checkdata_cb_) \
- const nsStyle##name_ * PeekStyle##name_() { \
- return DoGetStyle##name_<false>(); \
- }
+ #define STYLE_STRUCT(name_, checkdata_cb_) \
+ const nsStyle##name_ * PeekStyle##name_();
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
/**
* Compute the style changes needed during restyling when this style
* context is being replaced by aNewContext. (This is nonsymmetric since
* we optimize by skipping comparison for styles that have never been
* requested.)
@@ -476,42 +464,45 @@ public:
cachedData = nullptr;
}
} else {
cachedData = mCachedInheritedData.mStyleStructs[aSID];
}
return cachedData;
}
- mozilla::NonOwningStyleContextSource StyleSource() const { return mSource.AsRaw(); }
+ mozilla::NonOwningStyleContextSource StyleSource() const;
-public: // temporary
- // Private destructor, to discourage deletion outside of Release():
- ~nsStyleContext();
-
+protected:
+ // protected destructor to discourage deletion outside of Release()
+ ~nsStyleContext() {}
+ // Where the actual destructor lives
+ // We use this instead of a real destructor because we need
+ // this to be called *before* the subclass fields are destroyed
+ // by the subclass destructor
+ void Destructor();
// Delegated Helper constructor.
nsStyleContext(nsStyleContext* aParent,
- mozilla::OwningStyleContextSource&& aSource,
nsIAtom* aPseudoTag,
mozilla::CSSPseudoElementType aPseudoType);
// Helper post-contruct hook.
void FinishConstruction();
// Only does stuff in Gecko mode
void AddChild(nsStyleContext* aChild);
void RemoveChild(nsStyleContext* aChild);
void SetStyleBits();
const void* StyleStructFromServoComputedValues(nsStyleStructID aSID) {
switch (aSID) {
#define STYLE_STRUCT(name_, checkdata_cb_) \
case eStyleStruct_##name_: \
- return Servo_GetStyle##name_(mSource.AsServoComputedValues());
+ return Servo_GetStyle##name_(StyleSource().AsServoComputedValues());
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
default:
MOZ_ASSERT_UNREACHABLE("unexpected nsStyleStructID value");
return nullptr;
}
}
@@ -543,31 +534,31 @@ public: // temporary
#else
#define AUTO_CHECK_DEPENDENCY(sid_)
#endif
// Helper functions for GetStyle* and PeekStyle*
#define STYLE_STRUCT_INHERITED(name_, checkdata_cb_) \
template<bool aComputeData> \
const nsStyle##name_ * DoGetStyle##name_() { \
- if (mSource.IsGeckoRuleNode()) { \
+ if (IsGecko()) { \
const nsStyle##name_ * cachedData = \
static_cast<nsStyle##name_*>( \
mCachedInheritedData.mStyleStructs[eStyleStruct_##name_]); \
if (cachedData) /* Have it cached already, yay */ \
return cachedData; \
if (!aComputeData) { \
/* We always cache inherited structs on the context when we */\
/* compute them. */ \
return nullptr; \
} \
/* Have the rulenode deal */ \
AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
const nsStyle##name_ * newData = \
- mSource.AsGeckoRuleNode()-> \
+ StyleSource().AsGeckoRuleNode()-> \
GetStyle##name_<aComputeData>(this, mBits); \
/* always cache inherited data on the style context; the rule */\
/* node set the bit in mBits for us if needed. */ \
mCachedInheritedData.mStyleStructs[eStyleStruct_##name_] = \
const_cast<nsStyle##name_ *>(newData); \
return newData; \
} \
/** \
@@ -599,50 +590,50 @@ public: // temporary
} \
\
const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));\
if (!aComputeData && needToCompute) { \
return nullptr; \
} \
\
const nsStyle##name_* data = \
- Servo_GetStyle##name_(mSource.AsServoComputedValues()); \
+ Servo_GetStyle##name_(StyleSource().AsServoComputedValues()); \
/* perform any remaining main thread work on the struct */ \
if (needToCompute) { \
MOZ_ASSERT(NS_IsMainThread()); \
MOZ_ASSERT(!mozilla::ServoStyleSet::IsInServoTraversal()); \
const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext()); \
/* the Servo-backed StyleContextSource owns the struct */ \
AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
} \
return data; \
}
#define STYLE_STRUCT_RESET(name_, checkdata_cb_) \
template<bool aComputeData> \
const nsStyle##name_ * DoGetStyle##name_() { \
- if (mSource.IsGeckoRuleNode()) { \
+ if (IsGecko()) { \
if (mCachedResetData) { \
const nsStyle##name_ * cachedData = \
static_cast<nsStyle##name_*>( \
mCachedResetData->mStyleStructs[eStyleStruct_##name_]); \
if (cachedData) /* Have it cached already, yay */ \
return cachedData; \
} \
/* Have the rulenode deal */ \
AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
- return mSource.AsGeckoRuleNode()-> \
+ return StyleSource().AsGeckoRuleNode()-> \
GetStyle##name_<aComputeData>(this); \
} \
const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));\
if (!aComputeData && needToCompute) { \
return nullptr; \
} \
const nsStyle##name_* data = \
- Servo_GetStyle##name_(mSource.AsServoComputedValues()); \
+ Servo_GetStyle##name_(StyleSource().AsServoComputedValues()); \
/* perform any remaining main thread work on the struct */ \
if (needToCompute) { \
const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext()); \
/* the Servo-backed StyleContextSource owns the struct */ \
AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
} \
return data; \
}
@@ -670,21 +661,16 @@ public: // temporary
// background-color, and border-*-color if the nearest ancestor link
// element is visited (see RelevantLinkVisited()).
RefPtr<nsStyleContext> mStyleIfVisited;
// If this style context is for a pseudo-element or anonymous box,
// the relevant atom.
nsCOMPtr<nsIAtom> mPseudoTag;
- // The source for our style data, either a Gecko nsRuleNode or a Servo
- // ComputedValues struct. This never changes after construction, except
- // when it's released and nulled out during teardown.
- const mozilla::OwningStyleContextSource mSource;
-
// mCachedInheritedData and mCachedResetData point to both structs that
// are owned by this style context and structs that are owned by one of
// this style context's ancestors (which are indirectly owned since this
// style context owns a reference to its parent). If the bit in |mBits|
// is set for a struct, that means that the pointer for that struct is
// owned by an ancestor or by the rule node rather than by this style context.
// Since style contexts typically have some inherited data but only sometimes
// have reset data, we always allocate the mCachedInheritedData, but only
--- a/layout/style/nsStyleContextInlines.h
+++ b/layout/style/nsStyleContextInlines.h
@@ -18,9 +18,17 @@
#include "mozilla/ServoStyleContext.h"
#include "mozilla/GeckoStyleContext.h"
#include "mozilla/ServoUtils.h"
using namespace mozilla;
MOZ_DEFINE_STYLO_METHODS(nsStyleContext, GeckoStyleContext, ServoStyleContext);
+nsRuleNode*
+nsStyleContext::RuleNode()
+{
+ MOZ_RELEASE_ASSERT(IsGecko());
+ return AsGecko()->RuleNode();
+}
+
+
#endif // nsStyleContextInlines_h