Bug 1464060: Make the general setup for computed style bits nicer. r=xidorn

This patch:

 * Makes StyleStructID an enum class, and moves it to the mozilla namespaces.

 * Introduces StyleStructConstants with some constants scattered through the
   codebase.

 * Makes the computed style bits an enum class, and splits mPseudoType and mBits
   into their own members, since we were using a uint64_t when we have only a
   couple flags and CSSPseudoElementType is a byte. We statically assert that
   the number of style structs is less or equal to 32.

 * Makes mPseudoTag, mPseudoType and mBits const, since we don't want them to be
   mutated from C++, and we still need a few more refactorings (mostly getting
   rid of FinishStyle) to avoid mutating ComputedStyle instead.

MozReview-Commit-ID: 7qsTtASGcYB
This commit is contained in:
Emilio Cobos Álvarez 2018-05-24 17:49:24 +02:00
parent de6fa5fd09
commit 3f97dd5cab
9 changed files with 140 additions and 173 deletions

View file

@ -43,27 +43,6 @@ namespace mozilla {
//---------------------------------------------------------------------- //----------------------------------------------------------------------
#ifdef DEBUG
// Check that the style struct IDs are in the same order as they are
// in nsStyleStructList.h, since when we set up the IDs, we include
// the inherited and reset structs spearately from nsStyleStructList.h
enum DebugStyleStruct {
#define STYLE_STRUCT(name) eDebugStyleStruct_##name,
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
};
#define STYLE_STRUCT(name) \
static_assert(static_cast<int>(eDebugStyleStruct_##name) == \
static_cast<int>(eStyleStruct_##name), \
"Style struct IDs are not declared in order?");
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
#endif
ComputedStyle::ComputedStyle(nsPresContext* aPresContext, ComputedStyle::ComputedStyle(nsPresContext* aPresContext,
nsAtom* aPseudoTag, nsAtom* aPseudoTag,
CSSPseudoElementType aPseudoType, CSSPseudoElementType aPseudoType,
@ -71,22 +50,10 @@ ComputedStyle::ComputedStyle(nsPresContext* aPresContext,
: mPresContext(aPresContext) : mPresContext(aPresContext)
, mSource(aComputedValues) , mSource(aComputedValues)
, mPseudoTag(aPseudoTag) , mPseudoTag(aPseudoTag)
, mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT) , mBits(static_cast<Bit>(Servo_ComputedValues_GetStyleBits(this)))
, mPseudoType(aPseudoType)
{ {
AddStyleBit(Servo_ComputedValues_GetStyleBits(this));
MOZ_ASSERT(ComputedData()); MOZ_ASSERT(ComputedData());
// 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");
#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
} }
nsChangeHint nsChangeHint
@ -95,8 +62,7 @@ ComputedStyle::CalcStyleDifference(ComputedStyle* aNewContext,
{ {
MOZ_ASSERT(aNewContext); MOZ_ASSERT(aNewContext);
AUTO_PROFILER_LABEL("ComputedStyle::CalcStyleDifference", CSS); AUTO_PROFILER_LABEL("ComputedStyle::CalcStyleDifference", CSS);
static_assert(StyleStructConstants::kStyleStructCount <= 32,
static_assert(nsStyleStructID_Length <= 32,
"aEqualStructs is not big enough"); "aEqualStructs is not big enough");
*aEqualStructs = 0; *aEqualStructs = 0;
@ -124,6 +90,8 @@ ComputedStyle::CalcStyleDifference(ComputedStyle* aNewContext,
// FIXME(emilio): Reintroduce that optimization either for all kind of structs // FIXME(emilio): Reintroduce that optimization either for all kind of structs
// after bug 1368290 with a weak parent pointer from text, or just for reset // after bug 1368290 with a weak parent pointer from text, or just for reset
// structs. // structs.
#define STYLE_STRUCT_BIT(name_) \
StyleStructConstants::BitFor(StyleStructID::name_)
#define PEEK(struct_) \ #define PEEK(struct_) \
ComputedData()->GetStyle##struct_() ComputedData()->GetStyle##struct_()
@ -132,24 +100,24 @@ ComputedStyle::CalcStyleDifference(ComputedStyle* aNewContext,
PR_BEGIN_MACRO \ PR_BEGIN_MACRO \
const nsStyle##struct_* this##struct_ = PEEK(struct_); \ const nsStyle##struct_* this##struct_ = PEEK(struct_); \
if (this##struct_) { \ if (this##struct_) { \
structsFound |= NS_STYLE_INHERIT_BIT(struct_); \ structsFound |= STYLE_STRUCT_BIT(struct_); \
\ \
const nsStyle##struct_* other##struct_ = \ const nsStyle##struct_* other##struct_ = \
aNewContext->ThreadsafeStyle##struct_(); \ aNewContext->ThreadsafeStyle##struct_(); \
if (this##struct_ == other##struct_) { \ if (this##struct_ == other##struct_) { \
/* The very same struct, so we know that there will be no */ \ /* The very same struct, so we know that there will be no */ \
/* differences. */ \ /* differences. */ \
*aEqualStructs |= NS_STYLE_INHERIT_BIT(struct_); \ *aEqualStructs |= STYLE_STRUCT_BIT(struct_); \
} else { \ } else { \
nsChangeHint difference = \ nsChangeHint difference = \
this##struct_->CalcDifference(*other##struct_ EXPAND extra_args_); \ this##struct_->CalcDifference(*other##struct_ EXPAND extra_args_); \
hint |= difference; \ hint |= difference; \
if (!difference) { \ if (!difference) { \
*aEqualStructs |= NS_STYLE_INHERIT_BIT(struct_); \ *aEqualStructs |= STYLE_STRUCT_BIT(struct_); \
} \ } \
} \ } \
} else { \ } else { \
*aEqualStructs |= NS_STYLE_INHERIT_BIT(struct_); \ *aEqualStructs |= STYLE_STRUCT_BIT(struct_); \
} \ } \
styleStructCount++; \ styleStructCount++; \
PR_END_MACRO PR_END_MACRO
@ -187,12 +155,12 @@ ComputedStyle::CalcStyleDifference(ComputedStyle* aNewContext,
#undef DO_STRUCT_DIFFERENCE_WITH_ARGS #undef DO_STRUCT_DIFFERENCE_WITH_ARGS
#undef EXPAND #undef EXPAND
MOZ_ASSERT(styleStructCount == nsStyleStructID_Length, MOZ_ASSERT(styleStructCount == StyleStructConstants::kStyleStructCount,
"missing a call to DO_STRUCT_DIFFERENCE"); "missing a call to DO_STRUCT_DIFFERENCE");
#ifdef DEBUG #ifdef DEBUG
#define STYLE_STRUCT(name_) \ #define STYLE_STRUCT(name_) \
MOZ_ASSERT(!!(structsFound & NS_STYLE_INHERIT_BIT(name_)) == \ MOZ_ASSERT(!!(structsFound & STYLE_STRUCT_BIT(name_)) == \
(PEEK(name_) != nullptr), \ (PEEK(name_) != nullptr), \
"PeekStyleData results must not change in the middle of " \ "PeekStyleData results must not change in the middle of " \
"difference calculation."); "difference calculation.");
@ -222,7 +190,7 @@ ComputedStyle::CalcStyleDifference(ComputedStyle* aNewContext,
// One style has a style-if-visited and the other doesn't. // One style has a style-if-visited and the other doesn't.
// Presume a difference. // Presume a difference.
#define STYLE_STRUCT(name_, fields_) \ #define STYLE_STRUCT(name_, fields_) \
*aEqualStructs &= ~NS_STYLE_INHERIT_BIT(name_); *aEqualStructs &= ~STYLE_STRUCT_BIT(name_);
#include "nsCSSVisitedDependentPropList.h" #include "nsCSSVisitedDependentPropList.h"
#undef STYLE_STRUCT #undef STYLE_STRUCT
hint |= nsChangeHint_RepaintFrame; hint |= nsChangeHint_RepaintFrame;
@ -243,13 +211,14 @@ ComputedStyle::CalcStyleDifference(ComputedStyle* aNewContext,
const nsStyle##name_* otherVisStruct = \ const nsStyle##name_* otherVisStruct = \
otherVis->ThreadsafeStyle##name_(); \ otherVis->ThreadsafeStyle##name_(); \
if (MOZ_FOR_EACH_SEPARATED(STYLE_FIELD, (||), (), fields_)) { \ if (MOZ_FOR_EACH_SEPARATED(STYLE_FIELD, (||), (), fields_)) { \
*aEqualStructs &= ~NS_STYLE_INHERIT_BIT(name_); \ *aEqualStructs &= ~STYLE_STRUCT_BIT(name_); \
change = true; \ change = true; \
} \ } \
} }
#include "nsCSSVisitedDependentPropList.h" #include "nsCSSVisitedDependentPropList.h"
#undef STYLE_STRUCT #undef STYLE_STRUCT
#undef STYLE_FIELD #undef STYLE_FIELD
#undef STYLE_STRUCT_BIT
if (change) { if (change) {
hint |= nsChangeHint_RepaintFrame; hint |= nsChangeHint_RepaintFrame;
@ -399,11 +368,11 @@ ComputedStyle::CombineVisitedColors(nscolor *aColors, bool aLinkIsVisited)
#ifdef DEBUG #ifdef DEBUG
/* static */ const char* /* static */ const char*
ComputedStyle::StructName(nsStyleStructID aSID) ComputedStyle::StructName(StyleStructID aSID)
{ {
switch (aSID) { switch (aSID) {
#define STYLE_STRUCT(name_) \ #define STYLE_STRUCT(name_) \
case eStyleStruct_##name_: \ case StyleStructID::name_: \
return #name_; return #name_;
#include "nsStyleStructList.h" #include "nsStyleStructList.h"
#undef STYLE_STRUCT #undef STYLE_STRUCT
@ -412,19 +381,15 @@ ComputedStyle::StructName(nsStyleStructID aSID)
} }
} }
/* static */ bool /* static */ Maybe<StyleStructID>
ComputedStyle::LookupStruct(const nsACString& aName, nsStyleStructID& aResult) ComputedStyle::LookupStruct(const nsACString& aName)
{ {
if (false)
;
#define STYLE_STRUCT(name_) \ #define STYLE_STRUCT(name_) \
else if (aName.EqualsLiteral(#name_)) \ if (aName.EqualsLiteral(#name_)) \
aResult = eStyleStruct_##name_; return Some(StyleStructID::name_);
#include "nsStyleStructList.h" #include "nsStyleStructList.h"
#undef STYLE_STRUCT #undef STYLE_STRUCT
else return Nothing();
return false;
return true;
} }
#endif // DEBUG #endif // DEBUG

View file

@ -21,36 +21,8 @@
#include "nsCSSAnonBoxes.h" #include "nsCSSAnonBoxes.h"
#include "nsCSSPseudoElements.h" #include "nsCSSPseudoElements.h"
// Includes nsStyleStructID.
#include "nsStyleStructFwd.h" #include "nsStyleStructFwd.h"
// Bits for each struct.
// NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h
#define NS_STYLE_INHERIT_MASK 0x0007fffff
// Bits for inherited structs.
#define NS_STYLE_INHERITED_STRUCT_MASK \
((nsStyleStructID_size_t(1) << nsStyleStructID_Inherited_Count) - 1)
// Bits for reset structs.
#define NS_STYLE_RESET_STRUCT_MASK \
(((nsStyleStructID_size_t(1) << nsStyleStructID_Reset_Count) - 1) \
<< nsStyleStructID_Inherited_Count)
// Additional bits for ComputedStyle's mBits:
// (free bit) 0x000800000
// See ComputedStyle::HasTextDecorationLines
#define NS_STYLE_HAS_TEXT_DECORATION_LINES 0x001000000
// See ComputedStyle::HasPseudoElementData.
#define NS_STYLE_HAS_PSEUDO_ELEMENT_DATA 0x002000000
// See ComputedStyle::RelevantLinkIsVisited
#define NS_STYLE_RELEVANT_LINK_VISITED 0x004000000
// See ComputedStyle::ShouldSuppressLineBreak
#define NS_STYLE_SUPPRESS_LINEBREAK 0x080000000
// See ComputedStyle::IsTextCombined
#define NS_STYLE_IS_TEXT_COMBINED 0x800000000
// See ComputedStyle::GetPseudoEnum
#define NS_STYLE_CONTEXT_TYPE_SHIFT 37
class nsAtom; class nsAtom;
enum nsChangeHint : uint32_t; enum nsChangeHint : uint32_t;
class nsIPresShell; class nsIPresShell;
@ -91,8 +63,20 @@ class ComputedStyle;
* FIXME(emilio): This comment is somewhat outdated now. * FIXME(emilio): This comment is somewhat outdated now.
*/ */
enum class ComputedStyleBit : uint8_t
{
HasTextDecorationLines = 1 << 0,
HasPseudoElementData = 1 << 1,
SuppressLineBreak = 1 << 2,
IsTextCombined = 1 << 3,
RelevantLinkVisited = 1 << 4,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ComputedStyleBit)
class ComputedStyle class ComputedStyle
{ {
using Bit = ComputedStyleBit;
public: public:
ComputedStyle(nsPresContext* aPresContext, ComputedStyle(nsPresContext* aPresContext,
nsAtom* aPseudoTag, nsAtom* aPseudoTag,
@ -142,9 +126,9 @@ public:
} }
nsAtom* GetPseudo() const { return mPseudoTag; } nsAtom* GetPseudo() const { return mPseudoTag; }
mozilla::CSSPseudoElementType GetPseudoType() const { mozilla::CSSPseudoElementType GetPseudoType() const
return static_cast<mozilla::CSSPseudoElementType>( {
mBits >> NS_STYLE_CONTEXT_TYPE_SHIFT); return mPseudoType;
} }
bool IsInheritingAnonBox() const { bool IsInheritingAnonBox() const {
@ -174,7 +158,9 @@ public:
// Differs from nsStyleTextReset::HasTextDecorationLines, which tests // Differs from nsStyleTextReset::HasTextDecorationLines, which tests
// only the data for a single context. // only the data for a single context.
bool HasTextDecorationLines() const bool HasTextDecorationLines() const
{ return !!(mBits & NS_STYLE_HAS_TEXT_DECORATION_LINES); } {
return bool(mBits & Bit::HasTextDecorationLines);
}
// Whether any line break inside should be suppressed? If this returns // Whether any line break inside should be suppressed? If this returns
// true, the line should not be broken inside, which means inlines act // true, the line should not be broken inside, which means inlines act
@ -184,25 +170,33 @@ public:
// NOTE: for nsTextFrame, use nsTextFrame::ShouldSuppressLineBreak() // NOTE: for nsTextFrame, use nsTextFrame::ShouldSuppressLineBreak()
// instead of this method. // instead of this method.
bool ShouldSuppressLineBreak() const bool ShouldSuppressLineBreak() const
{ return !!(mBits & NS_STYLE_SUPPRESS_LINEBREAK); } {
return bool(mBits & Bit::SuppressLineBreak);
}
// Is this horizontal-in-vertical (tate-chu-yoko) text? This flag is // Is this horizontal-in-vertical (tate-chu-yoko) text? This flag is
// only set on ComputedStyles whose pseudo is nsCSSAnonBoxes::mozText. // only set on ComputedStyles whose pseudo is nsCSSAnonBoxes::mozText.
bool IsTextCombined() const bool IsTextCombined() const
{ return !!(mBits & NS_STYLE_IS_TEXT_COMBINED); } {
return bool(mBits & Bit::IsTextCombined);
}
// Does this ComputedStyle represent the style for a pseudo-element or // Does this ComputedStyle represent the style for a pseudo-element or
// inherit data from such a ComputedStyle? Whether this returns true // inherit data from such a ComputedStyle? Whether this returns true
// is equivalent to whether it or any of its ancestors returns // is equivalent to whether it or any of its ancestors returns
// non-null for IsPseudoElement(). // non-null for IsPseudoElement().
bool HasPseudoElementData() const bool HasPseudoElementData() const
{ return !!(mBits & NS_STYLE_HAS_PSEUDO_ELEMENT_DATA); } {
return bool(mBits & Bit::HasPseudoElementData);
}
// Is the only link whose visitedness is allowed to influence the // Is the only link whose visitedness is allowed to influence the
// style of the node this ComputedStyle is for (which is that element // style of the node this ComputedStyle is for (which is that element
// or its nearest ancestor that is a link) visited? // or its nearest ancestor that is a link) visited?
bool RelevantLinkVisited() const bool RelevantLinkVisited() const
{ return !!(mBits & NS_STYLE_RELEVANT_LINK_VISITED); } {
return bool(mBits & Bit::RelevantLinkVisited);
}
ComputedStyle* GetCachedInheritingAnonBoxStyle(nsAtom* aAnonBox) const ComputedStyle* GetCachedInheritingAnonBoxStyle(nsAtom* aAnonBox) const
{ {
@ -241,8 +235,6 @@ public:
mCachedInheritingStyles.Insert(aStyle); mCachedInheritingStyles.Insert(aStyle);
} }
void AddStyleBit(const uint64_t& aBit) { mBits |= aBit; }
/** /**
* Define typesafe getter functions for each style struct by * Define typesafe getter functions for each style struct by
* preprocessing the list of style structs. These functions are the * preprocessing the list of style structs. These functions are the
@ -319,20 +311,17 @@ public:
* Combine the R, G, and B components of whichever of aColors should * Combine the R, G, and B components of whichever of aColors should
* be used based on aLinkIsVisited with the A component of aColors[0]. * be used based on aLinkIsVisited with the A component of aColors[0].
*/ */
static nscolor CombineVisitedColors(nscolor *aColors, static nscolor CombineVisitedColors(nscolor* aColors, bool aLinkIsVisited);
bool aLinkIsVisited);
/** /**
* Start the background image loads for this ComputedStyle. * Start the background image loads for this ComputedStyle.
*/ */
inline void StartBackgroundImageLoads(); inline void StartBackgroundImageLoads();
static uint32_t GetBitForSID(const nsStyleStructID aSID) { return 1 << aSID; }
#ifdef DEBUG #ifdef DEBUG
void List(FILE* out, int32_t aIndent); void List(FILE* out, int32_t aIndent);
static const char* StructName(nsStyleStructID aSID); static const char* StructName(StyleStructID aSID);
static bool LookupStruct(const nsACString& aName, nsStyleStructID& aResult); static Maybe<StyleStructID> LookupStruct(const nsACString& aName);
#endif #endif
/** /**
@ -347,13 +336,23 @@ public:
void AddSizeOfIncludingThis(nsWindowSizes& aSizes, size_t* aCVsSize) const; void AddSizeOfIncludingThis(nsWindowSizes& aSizes, size_t* aCVsSize) const;
protected: protected:
bool HasRequestedStruct(StyleStructID aID) const
{
return mRequestedStructs & StyleStructConstants::BitFor(aID);
}
void SetRequestedStruct(StyleStructID aID)
{
mRequestedStructs |= StyleStructConstants::BitFor(aID);
}
// Needs to be friend so that it can call the destructor without making it // Needs to be friend so that it can call the destructor without making it
// public. // public.
friend void ::Gecko_ComputedStyle_Destroy(ComputedStyle*); friend void ::Gecko_ComputedStyle_Destroy(ComputedStyle*);
~ComputedStyle() = default; ~ComputedStyle() = default;
nsPresContext* mPresContext; nsPresContext* const mPresContext;
ServoComputedData mSource; ServoComputedData mSource;
@ -374,14 +373,12 @@ protected:
// If this ComputedStyle is for a pseudo-element or anonymous box, // If this ComputedStyle is for a pseudo-element or anonymous box,
// the relevant atom. // the relevant atom.
RefPtr<nsAtom> mPseudoTag; const RefPtr<nsAtom> mPseudoTag;
// mBits stores a number of things: // A bitfield with the structs that have been requested so far.
// - It records (using the style struct bits) which structs have uint32_t mRequestedStructs = 0;
// been requested on this ComputedStyle. const Bit mBits;
// - It also stores the additional bits listed at the top of const CSSPseudoElementType mPseudoType;
// nsStyleStruct.h.
uint64_t mBits;
}; };
} // namespace mozilla } // namespace mozilla

View file

@ -41,21 +41,20 @@ const nsStyle##name_ * ComputedStyle::PeekStyle##name_() { \
// Helper functions for GetStyle* and PeekStyle* // Helper functions for GetStyle* and PeekStyle*
#define STYLE_STRUCT_INHERITED(name_) \ #define STYLE_STRUCT_INHERITED(name_) \
template<bool aComputeData> \ template<bool aComputeData> \
const nsStyle##name_ * ComputedStyle::DoGetStyle##name_() { \ const nsStyle##name_* ComputedStyle::DoGetStyle##name_() { \
const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_)); \ const auto kStructID = StyleStructID::name_; \
const bool needToCompute = !HasRequestedStruct(kStructID); \
if (!aComputeData && needToCompute) { \ if (!aComputeData && needToCompute) { \
return nullptr; \ return nullptr; \
} \ } \
\
const nsStyle##name_* data = ComputedData()->GetStyle##name_(); \ const nsStyle##name_* data = ComputedData()->GetStyle##name_(); \
\
/* perform any remaining main thread work on the struct */ \ /* perform any remaining main thread work on the struct */ \
if (needToCompute) { \ if (needToCompute) { \
MOZ_ASSERT(NS_IsMainThread()); \ MOZ_ASSERT(NS_IsMainThread()); \
MOZ_ASSERT(!mozilla::IsInServoTraversal()); \ MOZ_ASSERT(!mozilla::IsInServoTraversal()); \
const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, nullptr); \ const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, nullptr); \
/* the ComputedStyle owns the struct */ \ /* the ComputedStyle owns the struct */ \
AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \ SetRequestedStruct(kStructID); \
} \ } \
return data; \ return data; \
} }
@ -63,7 +62,8 @@ const nsStyle##name_ * ComputedStyle::DoGetStyle##name_() { \
#define STYLE_STRUCT_RESET(name_) \ #define STYLE_STRUCT_RESET(name_) \
template<bool aComputeData> \ template<bool aComputeData> \
const nsStyle##name_ * ComputedStyle::DoGetStyle##name_() { \ const nsStyle##name_ * ComputedStyle::DoGetStyle##name_() { \
const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_)); \ const auto kStructID = StyleStructID::name_; \
const bool needToCompute = !HasRequestedStruct(kStructID); \
if (!aComputeData && needToCompute) { \ if (!aComputeData && needToCompute) { \
return nullptr; \ return nullptr; \
} \ } \
@ -72,7 +72,7 @@ const nsStyle##name_ * ComputedStyle::DoGetStyle##name_() { \
if (needToCompute) { \ if (needToCompute) { \
const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, nullptr); \ const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, nullptr); \
/* the ComputedStyle owns the struct */ \ /* the ComputedStyle owns the struct */ \
AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \ SetRequestedStruct(kStructID); \
} \ } \
return data; \ return data; \
} }
@ -91,13 +91,11 @@ void
ComputedStyle::ResolveSameStructsAs(const ComputedStyle* aOther) ComputedStyle::ResolveSameStructsAs(const ComputedStyle* aOther)
{ {
// Only resolve structs that are not already resolved in this struct. // Only resolve structs that are not already resolved in this struct.
uint64_t ourBits = mBits & NS_STYLE_INHERIT_MASK; auto newBits = aOther->mRequestedStructs & ~mRequestedStructs;
uint64_t otherBits = aOther->mBits & NS_STYLE_INHERIT_MASK;
uint64_t newBits = otherBits & ~ourBits & NS_STYLE_INHERIT_MASK;
#define STYLE_STRUCT(name_) \ #define STYLE_STRUCT(name_) \
if (nsStyle##name_::kHasFinishStyle && \ if (nsStyle##name_::kHasFinishStyle && \
(newBits & NS_STYLE_INHERIT_BIT(name_))) { \ (newBits & StyleStructConstants::BitFor(StyleStructID::name_))) { \
const nsStyle##name_* data = ComputedData()->GetStyle##name_(); \ const nsStyle##name_* data = ComputedData()->GetStyle##name_(); \
const nsStyle##name_* oldData = aOther->ComputedData()->GetStyle##name_(); \ const nsStyle##name_* oldData = aOther->ComputedData()->GetStyle##name_(); \
const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, oldData); \ const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, oldData); \
@ -105,7 +103,7 @@ ComputedStyle::ResolveSameStructsAs(const ComputedStyle* aOther)
#include "nsStyleStructList.h" #include "nsStyleStructList.h"
#undef STYLE_STRUCT #undef STYLE_STRUCT
mBits |= newBits; mRequestedStructs |= newBits;
} }
} // namespace mozilla } // namespace mozilla

View file

@ -693,7 +693,7 @@ SERVO_BINDING_FUNC(Servo_ComputedValues_Inherit, ComputedStyleStrong,
nsAtom* pseudo_tag, nsAtom* pseudo_tag,
ComputedStyleBorrowedOrNull parent_style, ComputedStyleBorrowedOrNull parent_style,
mozilla::InheritTarget target) mozilla::InheritTarget target)
SERVO_BINDING_FUNC(Servo_ComputedValues_GetStyleBits, uint64_t, SERVO_BINDING_FUNC(Servo_ComputedValues_GetStyleBits, uint8_t,
ComputedStyleBorrowed values) ComputedStyleBorrowed values)
SERVO_BINDING_FUNC(Servo_ComputedValues_EqualCustomProperties, bool, SERVO_BINDING_FUNC(Servo_ComputedValues_EqualCustomProperties, bool,
ServoComputedDataBorrowed first, ServoComputedDataBorrowed first,

View file

@ -350,18 +350,15 @@ Gecko_CalcStyleDifference(ComputedStyleBorrowed aOldStyle,
MOZ_ASSERT(aNewStyle); MOZ_ASSERT(aNewStyle);
uint32_t equalStructs; uint32_t equalStructs;
nsChangeHint result = const_cast<mozilla::ComputedStyle*>(aOldStyle)-> nsChangeHint result = const_cast<ComputedStyle*>(aOldStyle)->
CalcStyleDifference( CalcStyleDifference(const_cast<ComputedStyle*>(aNewStyle), &equalStructs);
const_cast<mozilla::ComputedStyle*>(aNewStyle),
&equalStructs);
*aAnyStyleStructChanged = equalStructs != NS_STYLE_INHERIT_MASK; *aAnyStyleStructChanged =
equalStructs != StyleStructConstants::kAllStructsMask;
const uint32_t kInheritStructsMask =
NS_STYLE_INHERIT_MASK & ~NS_STYLE_RESET_STRUCT_MASK;
const auto kInheritedStructsMask = StyleStructConstants::kInheritedStructsMask;
*aOnlyResetStructsChanged = *aOnlyResetStructsChanged =
(equalStructs & kInheritStructsMask) == kInheritStructsMask; (equalStructs & kInheritedStructsMask) == kInheritedStructsMask;
return result; return result;
} }

View file

@ -45,10 +45,6 @@
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
static_assert((((1 << nsStyleStructID_Length) - 1) &
~(NS_STYLE_INHERIT_MASK)) == 0,
"Not enough bits in NS_STYLE_INHERIT_MASK");
/* static */ const int32_t nsStyleGridLine::kMinLine; /* static */ const int32_t nsStyleGridLine::kMinLine;
/* static */ const int32_t nsStyleGridLine::kMaxLine; /* static */ const int32_t nsStyleGridLine::kMaxLine;

View file

@ -11,53 +11,69 @@
#ifndef nsStyleStructFwd_h_ #ifndef nsStyleStructFwd_h_
#define nsStyleStructFwd_h_ #define nsStyleStructFwd_h_
enum nsStyleStructID { namespace mozilla {
enum class StyleStructID : uint32_t {
/* /*
* Define the constants eStyleStruct_Font, etc. * Define the constants eStyleStruct_Font, etc.
* *
* The C++ standard, section 7.2, guarantees that enums begin with 0 and * The C++ standard, section 7.2, guarantees that enums begin with 0 and
* increase by 1. * increase by 1.
* *
* We separate the IDs of Reset and Inherited structs so that we can use * Note that we rely on the inherited structs being before the rest in
* the IDs as indices (offset by nsStyleStructID_*_Start) into arrays of * ComputedStyle.
* one type or the other.
*/ */
#define STYLE_STRUCT_INHERITED(name) name,
nsStyleStructID_None = -1,
nsStyleStructID_Inherited_Start = 0,
// a dummy value so the value after it is the same as ..._Inherited_Start
nsStyleStructID_DUMMY1 = nsStyleStructID_Inherited_Start - 1,
#define STYLE_STRUCT_INHERITED(name) eStyleStruct_##name,
#define STYLE_STRUCT_RESET(name) #define STYLE_STRUCT_RESET(name)
#include "nsStyleStructList.h" #include "nsStyleStructList.h"
#undef STYLE_STRUCT_INHERITED #undef STYLE_STRUCT_INHERITED
#undef STYLE_STRUCT_RESET #undef STYLE_STRUCT_RESET
nsStyleStructID_Reset_Start, #define STYLE_STRUCT_RESET(name) name,
// a dummy value so the value after it is the same as ..._Reset_Start
nsStyleStructID_DUMMY2 = nsStyleStructID_Reset_Start - 1,
#define STYLE_STRUCT_RESET(name) eStyleStruct_##name,
#define STYLE_STRUCT_INHERITED(name) #define STYLE_STRUCT_INHERITED(name)
#include "nsStyleStructList.h" #include "nsStyleStructList.h"
#undef STYLE_STRUCT_INHERITED #undef STYLE_STRUCT_INHERITED
#undef STYLE_STRUCT_RESET #undef STYLE_STRUCT_RESET
// one past the end; length of 0-based list
nsStyleStructID_Length,
nsStyleStructID_Inherited_Count =
nsStyleStructID_Reset_Start - nsStyleStructID_Inherited_Start,
nsStyleStructID_Reset_Count =
nsStyleStructID_Length - nsStyleStructID_Reset_Start,
}; };
// A bit corresponding to each struct ID struct StyleStructConstants
#define NS_STYLE_INHERIT_BIT(sid_) (1 << uint64_t(eStyleStruct_##sid_)) {
static const uint32_t kStyleStructCount =
#define STYLE_STRUCT_RESET(name) 1 +
#define STYLE_STRUCT_INHERITED(name) 1 +
#include "nsStyleStructList.h"
#undef STYLE_STRUCT_INHERITED
#undef STYLE_STRUCT_RESET
0;
typedef decltype(nsStyleStructID(0) + nsStyleStructID(0)) nsStyleStructID_size_t; static const uint32_t kInheritedStyleStructCount =
#define STYLE_STRUCT_RESET(name)
#define STYLE_STRUCT_INHERITED(name) 1 +
#include "nsStyleStructList.h"
#undef STYLE_STRUCT_INHERITED
#undef STYLE_STRUCT_RESET
0;
static const uint32_t kResetStyleStructCount =
#define STYLE_STRUCT_RESET(name) 1 +
#define STYLE_STRUCT_INHERITED(name)
#include "nsStyleStructList.h"
#undef STYLE_STRUCT_INHERITED
#undef STYLE_STRUCT_RESET
0;
static_assert(kStyleStructCount <= 32, "Bitmasks must be bigger!");
static const uint32_t kAllStructsMask = (1 << kStyleStructCount) - 1;
static const uint32_t kInheritedStructsMask = (1 << kInheritedStyleStructCount) - 1;
static const uint32_t kResetStructsMask = kAllStructsMask & (~kInheritedStructsMask);
static uint32_t BitFor(StyleStructID aID)
{
return 1 << static_cast<uint32_t>(aID);
}
};
} // namespace mozilla
#endif /* nsStyleStructFwd_h_ */ #endif /* nsStyleStructFwd_h_ */

View file

@ -41,7 +41,6 @@ use gecko_bindings::structs;
use gecko_bindings::structs::nsCSSPropertyID; use gecko_bindings::structs::nsCSSPropertyID;
use gecko_bindings::structs::mozilla::CSSPseudoElementType; use gecko_bindings::structs::mozilla::CSSPseudoElementType;
use gecko_bindings::structs::mozilla::CSSPseudoElementType_InheritingAnonBox; use gecko_bindings::structs::mozilla::CSSPseudoElementType_InheritingAnonBox;
use gecko_bindings::structs::root::NS_STYLE_CONTEXT_TYPE_SHIFT;
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut}; use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
use gecko_bindings::sugar::refptr::RefPtr; use gecko_bindings::sugar::refptr::RefPtr;
use gecko::values::convert_nscolor_to_rgba; use gecko::values::convert_nscolor_to_rgba;
@ -137,12 +136,12 @@ impl ComputedValues {
PseudoElement::from_atom(&atom) PseudoElement::from_atom(&atom)
} }
#[inline]
fn get_pseudo_type(&self) -> CSSPseudoElementType { fn get_pseudo_type(&self) -> CSSPseudoElementType {
let bits = (self.0).mBits; self.0.mPseudoType
let our_type = bits >> NS_STYLE_CONTEXT_TYPE_SHIFT;
unsafe { transmute(our_type as u8) }
} }
#[inline]
pub fn is_anon_box(&self) -> bool { pub fn is_anon_box(&self) -> bool {
let our_type = self.get_pseudo_type(); let our_type = self.get_pseudo_type();
return our_type == CSSPseudoElementType_InheritingAnonBox || return our_type == CSSPseudoElementType_InheritingAnonBox ||
@ -2985,7 +2984,6 @@ fn static_assert() {
I::IntoIter: ExactSizeIterator + Clone I::IntoIter: ExactSizeIterator + Clone
{ {
use properties::longhands::animation_${ident}::single_value::computed_value::T as Keyword; use properties::longhands::animation_${ident}::single_value::computed_value::T as Keyword;
use gecko_bindings::structs;
let v = v.into_iter(); let v = v.into_iter();

View file

@ -3097,25 +3097,25 @@ pub unsafe extern "C" fn Servo_ComputedValues_Inherit(
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_ComputedValues_GetStyleBits(values: ComputedStyleBorrowed) -> u64 { pub extern "C" fn Servo_ComputedValues_GetStyleBits(values: ComputedStyleBorrowed) -> u8 {
use style::properties::computed_value_flags::ComputedValueFlags; use style::properties::computed_value_flags::ComputedValueFlags;
// FIXME(emilio): We could do this more efficiently I'm quite sure. // FIXME(emilio): We could do this more efficiently I'm quite sure.
let flags = values.flags; let flags = values.flags;
let mut result = 0; let mut result = 0;
if flags.contains(ComputedValueFlags::IS_RELEVANT_LINK_VISITED) { if flags.contains(ComputedValueFlags::IS_RELEVANT_LINK_VISITED) {
result |= structs::NS_STYLE_RELEVANT_LINK_VISITED as u64; result |= structs::ComputedStyleBit_RelevantLinkVisited;
} }
if flags.contains(ComputedValueFlags::HAS_TEXT_DECORATION_LINES) { if flags.contains(ComputedValueFlags::HAS_TEXT_DECORATION_LINES) {
result |= structs::NS_STYLE_HAS_TEXT_DECORATION_LINES as u64; result |= structs::ComputedStyleBit_HasTextDecorationLines;
} }
if flags.contains(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK) { if flags.contains(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK) {
result |= structs::NS_STYLE_SUPPRESS_LINEBREAK as u64; result |= structs::ComputedStyleBit_SuppressLineBreak;
} }
if flags.contains(ComputedValueFlags::IS_TEXT_COMBINED) { if flags.contains(ComputedValueFlags::IS_TEXT_COMBINED) {
result |= structs::NS_STYLE_IS_TEXT_COMBINED as u64; result |= structs::ComputedStyleBit_IsTextCombined;
} }
if flags.contains(ComputedValueFlags::IS_IN_PSEUDO_ELEMENT_SUBTREE) { if flags.contains(ComputedValueFlags::IS_IN_PSEUDO_ELEMENT_SUBTREE) {
result |= structs::NS_STYLE_HAS_PSEUDO_ELEMENT_DATA as u64; result |= structs::ComputedStyleBit_HasPseudoElementData;
} }
result result
} }