--- a/layout/base/GeckoRestyleManager.cpp
+++ b/layout/base/GeckoRestyleManager.cpp
@@ -7,26 +7,28 @@
* Code responsible for managing style changes: tracking what style
* changes need to happen, scheduling them, and doing them.
*/
#include "mozilla/GeckoRestyleManager.h"
#include <algorithm> // For std::max
#include "mozilla/EffectSet.h"
+#include "mozilla/GeckoStyleContext.h"
#include "mozilla/EventStates.h"
#include "mozilla/ViewportFrame.h"
#include "mozilla/css/StyleRule.h" // For nsCSSSelector
#include "nsLayoutUtils.h"
#include "AnimationCommon.h" // For GetLayerAnimationInfo
#include "FrameLayerBuilder.h"
#include "GeckoProfiler.h"
#include "nsAutoPtr.h"
#include "nsStyleChangeList.h"
#include "nsRuleProcessorData.h"
+#include "nsStyleContextInlines.h"
#include "nsStyleSet.h"
#include "nsStyleUtil.h"
#include "nsCSSFrameConstructor.h"
#include "nsSVGEffects.h"
#include "nsCSSPseudoElements.h"
#include "nsCSSRendering.h"
#include "nsAnimationManager.h"
#include "nsTransitionManager.h"
@@ -3446,17 +3448,17 @@ ElementRestyler::SendAccessibilityNotifi
static void
ClearCachedInheritedStyleDataOnDescendants(
nsTArray<ElementRestyler::ContextToClear>& aContextsToClear)
{
for (size_t i = 0; i < aContextsToClear.Length(); i++) {
auto& entry = aContextsToClear[i];
if (!entry.mStyleContext->HasSingleReference()) {
- entry.mStyleContext->ClearCachedInheritedStyleDataOnDescendants(
+ entry.mStyleContext->AsGecko()->ClearCachedInheritedStyleDataOnDescendants(
entry.mStructs);
}
entry.mStyleContext = nullptr;
}
}
void
GeckoRestyleManager::ComputeAndProcessStyleChange(
--- a/layout/style/GeckoStyleContext.cpp
+++ b/layout/style/GeckoStyleContext.cpp
@@ -4,26 +4,29 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/GeckoStyleContext.h"
#include "nsStyleConsts.h"
#include "nsStyleStruct.h"
#include "nsPresContext.h"
#include "nsRuleNode.h"
+#include "nsStyleContextInlines.h"
using namespace mozilla;
GeckoStyleContext::GeckoStyleContext(nsStyleContext* aParent,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
already_AddRefed<nsRuleNode> aRuleNode,
bool aSkipParentDisplayBasedStyleFixup)
: nsStyleContext(aParent, OwningStyleContextSource(Move(aRuleNode)),
aPseudoTag, aPseudoType)
+ , mChild(nullptr)
+ , mEmptyChild(nullptr)
{
mBits |= NS_STYLE_CONTEXT_IS_GECKO;
if (aParent) {
#ifdef DEBUG
nsRuleNode *r1 = mParent->RuleNode(), *r2 = mSource.AsGeckoRuleNode();
while (r1->GetParent())
r1 = r1->GetParent();
@@ -31,22 +34,204 @@ GeckoStyleContext::GeckoStyleContext(nsS
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() calls AddChild which needs these
+ // to be initialized!
+ mNextSibling = this;
+ mPrevSibling = this;
+
FinishConstruction();
ApplyStyleFixups(aSkipParentDisplayBasedStyleFixup);
}
// Overloaded new operator. Initializes the memory to 0 and relies on an arena
// (which comes from the presShell) to perform the allocation.
void*
GeckoStyleContext::operator new(size_t sz, nsPresContext* aPresContext)
{
MOZ_ASSERT(sz == sizeof(GeckoStyleContext));
// Check the recycle list first.
return aPresContext->PresShell()->
AllocateByObjectID(eArenaObjectID_GeckoStyleContext, sz);
}
+
+
+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;
+ // 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;
+ aChild->mPrevSibling = list->mPrevSibling;
+ list->mPrevSibling->mNextSibling = aChild;
+ list->mPrevSibling = aChild;
+ }
+ (*listPtr) = aChild;
+}
+
+void
+GeckoStyleContext::RemoveChild(GeckoStyleContext* aChild)
+{
+ NS_PRECONDITION(nullptr != aChild && this == aChild->mParent, "bad argument");
+
+ GeckoStyleContext **list = aChild->mSource.MatchesNoRules() ? &mEmptyChild : &mChild;
+
+ if (aChild->mPrevSibling != aChild) { // has siblings
+ if ((*list) == aChild) {
+ (*list) = (*list)->mNextSibling;
+ }
+ }
+ else {
+ NS_ASSERTION((*list) == aChild, "bad sibling pointers");
+ (*list) = nullptr;
+ }
+
+ aChild->mPrevSibling->mNextSibling = aChild->mNextSibling;
+ aChild->mNextSibling->mPrevSibling = aChild->mPrevSibling;
+ aChild->mNextSibling = aChild;
+ aChild->mPrevSibling = aChild;
+}
+
+
+void
+GeckoStyleContext::ListDescendants(FILE* out, int32_t aIndent)
+{
+ if (nullptr != mChild) {
+ GeckoStyleContext* child = mChild;
+ do {
+ child->List(out, aIndent + 1, true);
+ child = child->mNextSibling;
+ } while (mChild != child);
+ }
+ if (nullptr != mEmptyChild) {
+ GeckoStyleContext* child = mEmptyChild;
+ do {
+ child->List(out, aIndent + 1, true);
+ child = child->mNextSibling;
+ } while (mEmptyChild != child);
+ }
+}
+
+void
+GeckoStyleContext::ClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs)
+{
+ if (mChild) {
+ GeckoStyleContext* child = mChild;
+ do {
+ child->DoClearCachedInheritedStyleDataOnDescendants(aStructs);
+ child = child->mNextSibling;
+ } while (mChild != child);
+ }
+ if (mEmptyChild) {
+ GeckoStyleContext* child = mEmptyChild;
+ do {
+ child->DoClearCachedInheritedStyleDataOnDescendants(aStructs);
+ child = child->mNextSibling;
+ } while (mEmptyChild != child);
+ }
+}
+
+void
+GeckoStyleContext::DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs)
+{
+ NS_ASSERTION(mFrameRefCnt == 0, "frame still referencing style context");
+ for (nsStyleStructID i = nsStyleStructID_Inherited_Start;
+ i < nsStyleStructID_Inherited_Start + nsStyleStructID_Inherited_Count;
+ i = nsStyleStructID(i + 1)) {
+ uint32_t bit = nsCachedStyleData::GetBitForSID(i);
+ if (aStructs & bit) {
+ if (!(mBits & bit) && mCachedInheritedData.mStyleStructs[i]) {
+ aStructs &= ~bit;
+ } else {
+ mCachedInheritedData.mStyleStructs[i] = nullptr;
+ }
+ }
+ }
+
+ if (mCachedResetData) {
+ for (nsStyleStructID i = nsStyleStructID_Reset_Start;
+ i < nsStyleStructID_Reset_Start + nsStyleStructID_Reset_Count;
+ i = nsStyleStructID(i + 1)) {
+ uint32_t bit = nsCachedStyleData::GetBitForSID(i);
+ if (aStructs & bit) {
+ if (!(mBits & bit) && mCachedResetData->mStyleStructs[i]) {
+ aStructs &= ~bit;
+ } else {
+ mCachedResetData->mStyleStructs[i] = nullptr;
+ }
+ }
+ }
+ }
+
+ if (aStructs == 0) {
+ return;
+ }
+
+ ClearCachedInheritedStyleDataOnDescendants(aStructs);
+}
+
+
+already_AddRefed<GeckoStyleContext>
+GeckoStyleContext::FindChildWithRules(const nsIAtom* aPseudoTag,
+ NonOwningStyleContextSource aSource,
+ NonOwningStyleContextSource 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;
+
+ if (list) {
+ GeckoStyleContext *child = list;
+ do {
+ if (child->mSource.AsRaw() == aSource &&
+ child->mPseudoTag == aPseudoTag &&
+ !child->IsStyleIfVisited() &&
+ child->RelevantLinkVisited() == aRelevantLinkVisited) {
+ bool match = false;
+ if (!aSourceIfVisited.IsNull()) {
+ match = child->GetStyleIfVisited() &&
+ child->GetStyleIfVisited()->AsGecko()->mSource.AsRaw() == aSourceIfVisited;
+ } else {
+ match = !child->GetStyleIfVisited();
+ }
+ if (match && !(child->mBits & NS_STYLE_INELIGIBLE_FOR_SHARING)) {
+ result = child;
+ break;
+ }
+ }
+ child = child->mNextSibling;
+ threshold--;
+ if (threshold == 0)
+ break;
+ } while (child != list);
+ }
+
+ if (result) {
+ if (result != list) {
+ // Move result to the front of the list.
+ RemoveChild(result);
+ AddChild(result);
+ }
+ result->mBits |= NS_STYLE_IS_SHARED;
+ }
+
+ return result.forget();
+}
+
--- a/layout/style/GeckoStyleContext.h
+++ b/layout/style/GeckoStyleContext.h
@@ -19,13 +19,49 @@ public:
already_AddRefed<nsRuleNode> aRuleNode,
bool aSkipParentDisplayBasedStyleFixup);
void* operator new(size_t sz, nsPresContext* aPresContext);
nsPresContext* PresContext() const {
return mSource.AsGeckoRuleNode()->PresContext();
}
+
+ void AddChild(GeckoStyleContext* aChild);
+ void RemoveChild(GeckoStyleContext* aChild);
+ /**
+ * 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
+ // * !!GetStyleIfVisited() == !!aSourceIfVisited, and, if they're
+ // non-null, GetStyleIfVisited()->mSource == aSourceIfVisited
+ // * RelevantLinkVisited() == aRelevantLinkVisited
+ already_AddRefed<GeckoStyleContext>
+ FindChildWithRules(const nsIAtom* aPseudoTag,
+ mozilla::NonOwningStyleContextSource aSource,
+ mozilla::NonOwningStyleContextSource aSourceIfVisited,
+ bool aRelevantLinkVisited);
+
+private:
+ // Helper for ClearCachedInheritedStyleDataOnDescendants.
+ void DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
+public:
+ void ListDescendants(FILE* out, int32_t aIndent);
+ // 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;
};
}
#endif // mozilla_GeckoStyleContext_h
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -64,16 +64,17 @@ EXPORTS += [
'nsMediaList.h',
'nsRuleData.h',
'nsRuleNode.h',
'nsRuleProcessorData.h',
'nsRuleWalker.h',
'nsStyleAutoArray.h',
'nsStyleConsts.h',
'nsStyleContext.h',
+ 'nsStyleContextInlines.h',
'nsStyleCoord.h',
'nsStyleSet.h',
'nsStyleStruct.h',
'nsStyleStructFwd.h',
'nsStyleStructInlines.h',
'nsStyleTransformMatrix.h',
'nsStyleUtil.h',
]
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -1,18 +1,16 @@
/* -*- 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/. */
/* the interface (to internal code) for retrieving computed style data */
#include "nsStyleContext.h"
-#include "nsStyleContextInlines.h"
-
#include "CSSVariableImageTable.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Maybe.h"
#include "nsCSSAnonBoxes.h"
#include "nsCSSPseudoElements.h"
#include "nsFontMetrics.h"
#include "nsStyleConsts.h"
@@ -32,16 +30,17 @@
#include "nsPrintfCString.h"
#include "RubyUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/ArenaObjectID.h"
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSetHandleInlines.h"
#include "mozilla/GeckoStyleContext.h"
#include "mozilla/ServoStyleContext.h"
+#include "nsStyleContextInlines.h"
#include "mozilla/ReflowInput.h"
#include "nsLayoutUtils.h"
#include "nsCoord.h"
// Ensure the binding function declarations in nsStyleContext.h matches
// those in ServoBindings.h.
#include "mozilla/ServoBindings.h"
@@ -82,18 +81,16 @@ const uint32_t nsStyleContext::sDependen
static bool sExpensiveStyleStructAssertionsEnabled;
#endif
nsStyleContext::nsStyleContext(nsStyleContext* aParent,
OwningStyleContextSource&& aSource,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType)
: mParent(aParent)
- , mChild(nullptr)
- , mEmptyChild(nullptr)
, 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)
@@ -112,33 +109,34 @@ nsStyleContext::FinishConstruction()
MOZ_ASSERT(!mSource.IsNull());
#ifdef DEBUG
static_assert(MOZ_ARRAY_LENGTH(nsStyleContext::sDependencyTable)
== nsStyleStructID_Length,
"Number of items in dependency table doesn't match IDs");
#endif
- mNextSibling = this;
- mPrevSibling = this;
if (mParent) {
mParent->AddChild(this);
}
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()
{
- NS_ASSERTION((nullptr == mChild) && (nullptr == mEmptyChild), "destructing context with children");
+ if (const GeckoStyleContext* gecko = GetAsGecko()) {
+ NS_ASSERTION((nullptr == gecko->mChild) && (nullptr == gecko->mEmptyChild),
+ "destructing context with children");
+ }
MOZ_ASSERT(!mSource.IsServoComputedValues() || !mCachedResetData);
#ifdef DEBUG
if (mSource.IsServoComputedValues()) {
MOZ_ASSERT(!mCachedResetData,
"Servo shouldn't cache reset structs in nsStyleContext");
for (const auto* data : mCachedInheritedData.mStyleStructs) {
MOZ_ASSERT(!data,
@@ -250,76 +248,49 @@ nsStyleContext::AssertStructsNotUsedElse
#include "nsStyleStructList.h"
#undef STYLE_STRUCT_INHERITED
#undef STYLE_STRUCT_RESET
}
}
}
- if (mChild) {
- const nsStyleContext* child = mChild;
- do {
- child->AssertStructsNotUsedElsewhere(aDestroyingContext, aLevels - 1);
- child = child->mNextSibling;
- } while (child != mChild);
- }
+ if (const GeckoStyleContext* gecko = GetAsGecko()) {
+ if (gecko->mChild) {
+ const GeckoStyleContext* child = gecko->mChild;
+ do {
+ child->AssertStructsNotUsedElsewhere(aDestroyingContext, aLevels - 1);
+ child = child->mNextSibling;
+ } while (child != gecko->mChild);
+ }
- if (mEmptyChild) {
- const nsStyleContext* child = mEmptyChild;
- do {
- child->AssertStructsNotUsedElsewhere(aDestroyingContext, aLevels - 1);
- child = child->mNextSibling;
- } while (child != mEmptyChild);
+ if (gecko->mEmptyChild) {
+ const GeckoStyleContext* child = gecko->mEmptyChild;
+ do {
+ child->AssertStructsNotUsedElsewhere(aDestroyingContext, aLevels - 1);
+ child = child->mNextSibling;
+ } while (child != gecko->mEmptyChild);
+ }
}
}
#endif
+
void nsStyleContext::AddChild(nsStyleContext* aChild)
{
- NS_ASSERTION(aChild->mPrevSibling == aChild &&
- aChild->mNextSibling == aChild,
- "child already in a child list");
-
- nsStyleContext **listPtr = aChild->mSource.MatchesNoRules() ? &mEmptyChild : &mChild;
- // Explicitly dereference listPtr so that compiler doesn't have to know that mNextSibling
- // etc. don't alias with what ever listPtr points at.
- nsStyleContext *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;
- aChild->mPrevSibling = list->mPrevSibling;
- list->mPrevSibling->mNextSibling = aChild;
- list->mPrevSibling = aChild;
+ if (GeckoStyleContext* gecko = GetAsGecko()) {
+ gecko->AddChild(aChild->AsGecko());
}
- (*listPtr) = aChild;
}
void nsStyleContext::RemoveChild(nsStyleContext* aChild)
{
- NS_PRECONDITION(nullptr != aChild && this == aChild->mParent, "bad argument");
-
- nsStyleContext **list = aChild->mSource.MatchesNoRules() ? &mEmptyChild : &mChild;
-
- if (aChild->mPrevSibling != aChild) { // has siblings
- if ((*list) == aChild) {
- (*list) = (*list)->mNextSibling;
- }
+ if (GeckoStyleContext* gecko = GetAsGecko()) {
+ gecko->RemoveChild(aChild->AsGecko());
}
- else {
- NS_ASSERTION((*list) == aChild, "bad sibling pointers");
- (*list) = nullptr;
- }
-
- aChild->mPrevSibling->mNextSibling = aChild->mNextSibling;
- aChild->mNextSibling->mPrevSibling = aChild->mPrevSibling;
- aChild->mNextSibling = aChild;
- aChild->mPrevSibling = aChild;
}
void
nsStyleContext::MoveTo(nsStyleContext* aNewParent)
{
MOZ_ASSERT(aNewParent != mParent);
// This function shouldn't be getting called if the parents have different
@@ -358,66 +329,16 @@ nsStyleContext::MoveTo(nsStyleContext* a
if (mStyleIfVisited) {
mStyleIfVisited->mParent->RemoveChild(mStyleIfVisited);
mStyleIfVisited->mParent = aNewParent;
mStyleIfVisited->mParent->AddChild(mStyleIfVisited);
}
}
-already_AddRefed<nsStyleContext>
-nsStyleContext::FindChildWithRules(const nsIAtom* aPseudoTag,
- NonOwningStyleContextSource aSource,
- NonOwningStyleContextSource aSourceIfVisited,
- bool aRelevantLinkVisited)
-{
- uint32_t threshold = 10; // The # of siblings we're willing to examine
- // before just giving this whole thing up.
-
- RefPtr<nsStyleContext> result;
- nsStyleContext *list = aSource.MatchesNoRules() ? mEmptyChild : mChild;
-
- if (list) {
- nsStyleContext *child = list;
- do {
- if (child->mSource.AsRaw() == aSource &&
- child->mPseudoTag == aPseudoTag &&
- !child->IsStyleIfVisited() &&
- child->RelevantLinkVisited() == aRelevantLinkVisited) {
- bool match = false;
- if (!aSourceIfVisited.IsNull()) {
- match = child->GetStyleIfVisited() &&
- child->GetStyleIfVisited()->mSource.AsRaw() == aSourceIfVisited;
- } else {
- match = !child->GetStyleIfVisited();
- }
- if (match && !(child->mBits & NS_STYLE_INELIGIBLE_FOR_SHARING)) {
- result = child;
- break;
- }
- }
- child = child->mNextSibling;
- threshold--;
- if (threshold == 0)
- break;
- } while (child != list);
- }
-
- if (result) {
- if (result != list) {
- // Move result to the front of the list.
- RemoveChild(result);
- AddChild(result);
- }
- result->mBits |= NS_STYLE_IS_SHARED;
- }
-
- return result.forget();
-}
-
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()) {
@@ -471,17 +392,22 @@ nsStyleContext::GetUniqueStyleData(const
"Can't COW-mutate servo values from Gecko!");
// If we already own the struct and no kids could depend on it, then
// just return it. (We leak in this case if there are kids -- and this
// function really shouldn't be called for style contexts that could
// have kids depending on the data. ClearStyleData would be OK, but
// this test for no mChild or mEmptyChild doesn't catch that case.)
const void *current = StyleData(aSID);
- if (!mChild && !mEmptyChild &&
+ GeckoStyleContext *child = nullptr, *emptyChild = nullptr;
+ if (const GeckoStyleContext* gecko = GetAsGecko()) {
+ child = gecko->mChild;
+ emptyChild = gecko->mEmptyChild;
+ }
+ if (!child && !emptyChild &&
!(mBits & nsCachedStyleData::GetBitForSID(aSID)) &&
GetCachedStyleData(aSID))
return const_cast<void*>(current);
void* result;
nsPresContext *presContext = PresContext();
switch (aSID) {
@@ -510,18 +436,20 @@ nsStyleContext::GetUniqueStyleData(const
return result;
}
// This is an evil function, but less evil than GetUniqueStyleData. It
// creates an empty style struct for this nsStyleContext.
void*
nsStyleContext::CreateEmptyStyleData(const nsStyleStructID& aSID)
{
- MOZ_ASSERT(!mChild && !mEmptyChild &&
- !(mBits & nsCachedStyleData::GetBitForSID(aSID)) &&
+ if (const GeckoStyleContext* gecko = GetAsGecko()) {
+ MOZ_ASSERT(!gecko->mChild && !gecko->mEmptyChild, "This style should not have been computed");
+ }
+ MOZ_ASSERT(!(mBits & nsCachedStyleData::GetBitForSID(aSID)) &&
!GetCachedStyleData(aSID),
"This style should not have been computed");
void* result;
nsPresContext* presContext = PresContext();
switch (aSID) {
#define UNIQUE_CASE(c_) \
case eStyleStruct_##c_: \
@@ -1301,29 +1229,18 @@ void nsStyleContext::List(FILE* out, int
}
fprintf_stderr(out, "%s}\n", str.get());
}
else {
fprintf_stderr(out, "%s{}\n", str.get());
}
if (aListDescendants) {
- if (nullptr != mChild) {
- nsStyleContext* child = mChild;
- do {
- child->List(out, aIndent + 1, aListDescendants);
- child = child->mNextSibling;
- } while (mChild != child);
- }
- if (nullptr != mEmptyChild) {
- nsStyleContext* child = mEmptyChild;
- do {
- child->List(out, aIndent + 1, aListDescendants);
- child = child->mNextSibling;
- } while (mEmptyChild != child);
+ if (GeckoStyleContext* gecko = GetAsGecko()) {
+ gecko->ListDescendants(out, aIndent);
}
}
}
#endif
// 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
@@ -1532,93 +1449,37 @@ nsStyleContext::SwapStyleData(nsStyleCon
}
} else if (!(aNewContext->mBits & bit) && thisData && otherData) {
std::swap(thisData, otherData);
}
}
}
void
-nsStyleContext::ClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs)
-{
- if (mChild) {
- nsStyleContext* child = mChild;
- do {
- child->DoClearCachedInheritedStyleDataOnDescendants(aStructs);
- child = child->mNextSibling;
- } while (mChild != child);
- }
- if (mEmptyChild) {
- nsStyleContext* child = mEmptyChild;
- do {
- child->DoClearCachedInheritedStyleDataOnDescendants(aStructs);
- child = child->mNextSibling;
- } while (mEmptyChild != child);
- }
-}
-
-void
-nsStyleContext::DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs)
-{
- NS_ASSERTION(mFrameRefCnt == 0, "frame still referencing style context");
- for (nsStyleStructID i = nsStyleStructID_Inherited_Start;
- i < nsStyleStructID_Inherited_Start + nsStyleStructID_Inherited_Count;
- i = nsStyleStructID(i + 1)) {
- uint32_t bit = nsCachedStyleData::GetBitForSID(i);
- if (aStructs & bit) {
- if (!(mBits & bit) && mCachedInheritedData.mStyleStructs[i]) {
- aStructs &= ~bit;
- } else {
- mCachedInheritedData.mStyleStructs[i] = nullptr;
- }
- }
- }
-
- if (mCachedResetData) {
- for (nsStyleStructID i = nsStyleStructID_Reset_Start;
- i < nsStyleStructID_Reset_Start + nsStyleStructID_Reset_Count;
- i = nsStyleStructID(i + 1)) {
- uint32_t bit = nsCachedStyleData::GetBitForSID(i);
- if (aStructs & bit) {
- if (!(mBits & bit) && mCachedResetData->mStyleStructs[i]) {
- aStructs &= ~bit;
- } else {
- mCachedResetData->mStyleStructs[i] = nullptr;
- }
- }
- }
- }
-
- if (aStructs == 0) {
- return;
- }
-
- ClearCachedInheritedStyleDataOnDescendants(aStructs);
-}
-
-void
nsStyleContext::SetIneligibleForSharing()
{
if (mBits & NS_STYLE_INELIGIBLE_FOR_SHARING) {
return;
}
mBits |= NS_STYLE_INELIGIBLE_FOR_SHARING;
- if (mChild) {
- nsStyleContext* child = mChild;
- do {
- child->SetIneligibleForSharing();
- child = child->mNextSibling;
- } while (mChild != child);
- }
- if (mEmptyChild) {
- nsStyleContext* child = mEmptyChild;
- do {
- child->SetIneligibleForSharing();
- child = child->mNextSibling;
- } while (mEmptyChild != child);
+ if (const GeckoStyleContext* gecko = GetAsGecko()) {
+ if (gecko->mChild) {
+ GeckoStyleContext* child = gecko->mChild;
+ do {
+ child->SetIneligibleForSharing();
+ child = child->mNextSibling;
+ } while (gecko->mChild != child);
+ }
+ if (gecko->mEmptyChild) {
+ GeckoStyleContext* child = gecko->mEmptyChild;
+ do {
+ child->SetIneligibleForSharing();
+ child = child->mNextSibling;
+ } while (gecko->mEmptyChild != child);
+ }
}
}
#ifdef RESTYLE_LOGGING
nsCString
nsStyleContext::GetCachedStyleDataAsString(uint32_t aStructs)
{
nsCString structs;
@@ -1688,34 +1549,43 @@ nsStyleContext::LogStyleContextTree(bool
}
LOG_RESTYLE("%p(%d) %s%s%s%s",
this, mRefCnt,
structs.get(), pseudo.get(), flags.get(), parent.get());
LOG_RESTYLE_INDENT();
- if (nullptr != mChild) {
- nsStyleContext* child = mChild;
- do {
- child->LogStyleContextTree(false, aStructs);
- child = child->mNextSibling;
- } while (mChild != child);
- }
- if (nullptr != mEmptyChild) {
- nsStyleContext* child = mEmptyChild;
- do {
- child->LogStyleContextTree(false, aStructs);
- child = child->mNextSibling;
- } while (mEmptyChild != child);
+ if (const GeckoStyleContext* gecko = GetAsGecko()) {
+ if (nullptr != gecko->mChild) {
+ GeckoStyleContext* child = gecko->mChild;
+ do {
+ child->LogStyleContextTree(false, aStructs);
+ child = child->mNextSibling;
+ } while (gecko->mChild != child);
+ }
+ if (nullptr != gecko->mEmptyChild) {
+ GeckoStyleContext* child = gecko->mEmptyChild;
+ do {
+ child->LogStyleContextTree(false, aStructs);
+ child = child->mNextSibling;
+ } while (gecko->mEmptyChild != child);
+ }
}
}
#endif
#ifdef DEBUG
/* static */ void
nsStyleContext::Initialize()
{
Preferences::AddBoolVarCache(
&sExpensiveStyleStructAssertionsEnabled,
"layout.css.expensive-style-struct-assertions.enabled");
}
#endif
+
+nsPresContext*
+nsStyleContext::PresContext() const
+{
+ MOZ_STYLO_FORWARD(PresContext, ())
+}
+
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -149,29 +149,16 @@ public:
bool IsAnonBox() const {
return
GetPseudoType() == mozilla::CSSPseudoElementType::InheritingAnonBox ||
GetPseudoType() == mozilla::CSSPseudoElementType::NonInheritingAnonBox;
}
bool IsPseudoElement() const { return mPseudoTag && !IsAnonBox(); }
- // 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
- // * !!GetStyleIfVisited() == !!aSourceIfVisited, and, if they're
- // non-null, GetStyleIfVisited()->mSource == aSourceIfVisited
- // * RelevantLinkVisited() == aRelevantLinkVisited
- already_AddRefed<nsStyleContext>
- FindChildWithRules(const nsIAtom* aPseudoTag,
- mozilla::NonOwningStyleContextSource aSource,
- mozilla::NonOwningStyleContextSource aSourceIfVisited,
- bool aRelevantLinkVisited);
-
// Does this style context or any of its ancestors have text
// decoration lines?
// Differs from nsStyleTextReset::HasTextDecorationLines, which tests
// only the data for a single context.
bool HasTextDecorationLines() const
{ return !!(mBits & NS_STYLE_HAS_TEXT_DECORATION_LINES); }
// Whether any line break inside should be suppressed? If this returns
@@ -455,21 +442,16 @@ public:
* inheriting from the old ancestor. This is not normally a problem, as
* this style context will usually be destroyed by being released at the
* end of ElementRestyler::Restyle; but for style contexts held on to outside
* of the frame, we need to clear out the cached pointer so that if we need
* it again we'll re-fetch it from the new ancestor.
*/
void SwapStyleData(nsStyleContext* aNewContext, uint32_t aStructs);
- /**
- * On each descendant of this style context, clears out any cached inherited
- * structs indicated in aStructs.
- */
- void ClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
/**
* 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();
@@ -504,29 +486,30 @@ public:
} else {
cachedData = mCachedInheritedData.mStyleStructs[aSID];
}
return cachedData;
}
mozilla::NonOwningStyleContextSource StyleSource() const { return mSource.AsRaw(); }
-protected:
+public: // temporary
// Private destructor, to discourage deletion outside of Release():
~nsStyleContext();
// 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* GetUniqueStyleData(const nsStyleStructID& aSID);
void* CreateEmptyStyleData(const nsStyleStructID& aSID);
void SetStyleBits();
@@ -676,46 +659,32 @@ protected:
AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
} \
return data; \
}
#include "nsStyleStructList.h"
#undef STYLE_STRUCT_RESET
#undef STYLE_STRUCT_INHERITED
- // Helper for ClearCachedInheritedStyleDataOnDescendants.
- void DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
-
#ifdef DEBUG
void AssertStructsNotUsedElsewhere(nsStyleContext* aDestroyingContext,
int32_t aLevels) const;
#endif
#ifdef RESTYLE_LOGGING
void LogStyleContextTree(bool aFirst, uint32_t aStructs);
// This only gets called under call trees where we've already checked
// that PresContext()->RestyleManager()->ShouldLogRestyle() returned true.
// It exists here just to satisfy LOG_RESTYLE's expectations.
bool ShouldLogRestyle() { return true; }
#endif
RefPtr<nsStyleContext> mParent;
- // 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.
- nsStyleContext* mChild;
- nsStyleContext* mEmptyChild;
- nsStyleContext* mPrevSibling;
- nsStyleContext* mNextSibling;
-
// Style to be used instead for the R, G, and B components of color,
// 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;
--- a/layout/style/nsStyleContextInlines.h
+++ b/layout/style/nsStyleContextInlines.h
@@ -6,27 +6,21 @@
/*
* Inlined methods for nsStyleContext. Will just redirect to
* GeckoStyleContext methods when compiled without stylo, but will do
* virtual dispatch (by checking which kind of container it is)
* in stylo mode.
*/
-#ifndef mozilla_nsStyleContextInlines_h
-#define mozilla_nsStyleContextInlines_h
+#ifndef nsStyleContextInlines_h
+#define nsStyleContextInlines_h
#include "nsStyleContext.h"
#include "mozilla/ServoStyleContext.h"
#include "mozilla/GeckoStyleContext.h"
#include "mozilla/ServoUtils.h"
using namespace mozilla;
MOZ_DEFINE_STYLO_METHODS(nsStyleContext, GeckoStyleContext, ServoStyleContext);
-nsPresContext*
-nsStyleContext::PresContext() const
-{
- MOZ_STYLO_FORWARD(PresContext, ())
-}
-
-#endif // mozilla_nsStyleContextInlines_h
+#endif // nsStyleContextInlines_h
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -38,16 +38,17 @@
#include "nsHTMLCSSStyleSheet.h"
#include "nsHTMLStyleSheet.h"
#include "nsCSSRules.h"
#include "nsPrintfCString.h"
#include "nsIFrame.h"
#include "mozilla/RestyleManager.h"
#include "mozilla/RestyleManagerInlines.h"
#include "nsQueryObject.h"
+#include "nsStyleContextInlines.h"
#include <inttypes.h>
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_ISUPPORTS(nsEmptyStyleRule, nsIStyleRule)
@@ -921,17 +922,17 @@ nsStyleSet::GetContext(nsStyleContext* a
}
bool relevantLinkVisited = (aFlags & eIsLink) ?
(aFlags & eIsVisitedLink) :
(aParentContext && aParentContext->RelevantLinkVisited());
RefPtr<nsStyleContext> result;
if (aParentContext)
- result = aParentContext->FindChildWithRules(aPseudoTag, aRuleNode,
+ result = aParentContext->AsGecko()->FindChildWithRules(aPseudoTag, aRuleNode,
aVisitedRuleNode,
relevantLinkVisited);
if (!result) {
// |aVisitedRuleNode| may have a ref-count of zero since we are yet
// to create the style context that will hold an owning reference to it.
// As a result, we need to make sure it stays alive until that point
// in case something in the first call to NS_NewStyleContext triggers a