Bug 1464060: Make the general setup for computed style bits nicer. r?xidorn draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 24 May 2018 17:49:24 +0200
changeset 799435 d998df0c5e5589852ee2c33c44177217416c2dc8
parent 799434 3882039f68098244ea174962998f3ab4294fc3a9
child 799436 babbb016b7e78c207405a07e8cdc95941205aeff
push id111048
push userbmo:emilio@crisal.io
push dateThu, 24 May 2018 16:51:09 +0000
reviewersxidorn
bugs1464060
milestone62.0a1
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 explicitly shifted, instead of manually declared, and also an enum class under ComputedStyle. MozReview-Commit-ID: AEbhsIOvdar
layout/style/ComputedStyle.cpp
layout/style/ComputedStyle.h
layout/style/ComputedStyleInlines.h
layout/style/ServoBindings.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStructFwd.h
servo/components/style/properties/gecko.mako.rs
servo/ports/geckolib/glue.rs
--- a/layout/style/ComputedStyle.cpp
+++ b/layout/style/ComputedStyle.cpp
@@ -38,70 +38,42 @@
 // Ensure the binding function declarations in ComputedStyle.h matches
 // those in ServoBindings.h.
 #include "mozilla/ServoBindings.h"
 
 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,
                              nsAtom* aPseudoTag,
                              CSSPseudoElementType aPseudoType,
                              ServoComputedDataForgotten aComputedValues)
   : mPresContext(aPresContext)
   , mSource(aComputedValues)
   , mPseudoTag(aPseudoTag)
-  , mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT)
+  , mBits(((uint64_t)aPseudoType) << kTypeShift)
 {
   AddStyleBit(Servo_ComputedValues_GetStyleBits(this));
   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),
+  static_assert((UINT64_MAX >> kTypeShift) >=
+                 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
 ComputedStyle::CalcStyleDifference(ComputedStyle* aNewContext,
                                    uint32_t* aEqualStructs)
 {
   MOZ_ASSERT(aNewContext);
   AUTO_PROFILER_LABEL("ComputedStyle::CalcStyleDifference", CSS);
-
-  static_assert(nsStyleStructID_Length <= 32,
+  static_assert(StyleStructConstants::kStyleStructCount <= 32,
                 "aEqualStructs is not big enough");
 
   *aEqualStructs = 0;
 
   nsChangeHint hint = nsChangeHint(0);
   // We must always ensure that we populate the structs on the new style
   // context that are filled in on the old context, so that if we get
   // two style changes in succession, the second of which causes a real
@@ -127,34 +99,34 @@ ComputedStyle::CalcStyleDifference(Compu
 #define PEEK(struct_) \
    ComputedData()->GetStyle##struct_()
 
 #define EXPAND(...) __VA_ARGS__
 #define DO_STRUCT_DIFFERENCE_WITH_ARGS(struct_, extra_args_)                  \
   PR_BEGIN_MACRO                                                              \
     const nsStyle##struct_* this##struct_ = PEEK(struct_);                    \
     if (this##struct_) {                                                      \
-      structsFound |= NS_STYLE_INHERIT_BIT(struct_);                          \
+      structsFound |= STYLE_STRUCT_BIT(struct_);                              \
                                                                               \
       const nsStyle##struct_* other##struct_ =                                \
         aNewContext->ThreadsafeStyle##struct_();                              \
       if (this##struct_ == other##struct_) {                                  \
         /* The very same struct, so we know that there will be no */          \
         /* differences.                                           */          \
-        *aEqualStructs |= NS_STYLE_INHERIT_BIT(struct_);                      \
+        *aEqualStructs |= STYLE_STRUCT_BIT(struct_);                          \
       } else {                                                                \
         nsChangeHint difference =                                             \
           this##struct_->CalcDifference(*other##struct_ EXPAND extra_args_);  \
         hint |= difference;                                                   \
         if (!difference) {                                                    \
-          *aEqualStructs |= NS_STYLE_INHERIT_BIT(struct_);                    \
+          *aEqualStructs |= STYLE_STRUCT_BIT(struct_);                        \
         }                                                                     \
       }                                                                       \
     } else {                                                                  \
-      *aEqualStructs |= NS_STYLE_INHERIT_BIT(struct_);                        \
+      *aEqualStructs |= STYLE_STRUCT_BIT(struct_);                            \
     }                                                                         \
     styleStructCount++;                                                       \
   PR_END_MACRO
 #define DO_STRUCT_DIFFERENCE(struct_) \
   DO_STRUCT_DIFFERENCE_WITH_ARGS(struct_, ())
 
   // FIXME: The order of these DO_STRUCT_DIFFERENCE calls is no longer
   // significant.  With a small amount of effort, we could replace them with a
@@ -182,22 +154,22 @@ ComputedStyle::CalcStyleDifference(Compu
   DO_STRUCT_DIFFERENCE(Effects);
   DO_STRUCT_DIFFERENCE(Background);
   DO_STRUCT_DIFFERENCE(Color);
 
 #undef DO_STRUCT_DIFFERENCE
 #undef DO_STRUCT_DIFFERENCE_WITH_ARGS
 #undef EXPAND
 
-  MOZ_ASSERT(styleStructCount == nsStyleStructID_Length,
+  MOZ_ASSERT(styleStructCount == StyleStructConstants::kStyleStructCount,
              "missing a call to DO_STRUCT_DIFFERENCE");
 
 #ifdef DEBUG
   #define STYLE_STRUCT(name_)                                             \
-    MOZ_ASSERT(!!(structsFound & NS_STYLE_INHERIT_BIT(name_)) ==          \
+    MOZ_ASSERT(!!(structsFound & STYLE_STRUCT_BIT(name_)) ==              \
                (PEEK(name_) != nullptr),                                  \
                "PeekStyleData results must not change in the middle of "  \
                "difference calculation.");
   #include "nsStyleStructList.h"
   #undef STYLE_STRUCT
 #endif
 
   // Note that we do not check whether this->RelevantLinkVisited() !=
@@ -217,17 +189,17 @@ ComputedStyle::CalcStyleDifference(Compu
   // things that can depend on :visited) for the properties on which we
   // call GetVisitedDependentColor.
   ComputedStyle* thisVis = GetStyleIfVisited();
   ComputedStyle* otherVis = aNewContext->GetStyleIfVisited();
   if (!thisVis != !otherVis) {
     // One style has a style-if-visited and the other doesn't.
     // Presume a difference.
 #define STYLE_STRUCT(name_, fields_) \
-    *aEqualStructs &= ~NS_STYLE_INHERIT_BIT(name_);
+    *aEqualStructs &= ~STYLE_STRUCT_BIT(name_);
 #include "nsCSSVisitedDependentPropList.h"
 #undef STYLE_STRUCT
     hint |= nsChangeHint_RepaintFrame;
   } else if (thisVis) {
     // Both styles have a style-if-visited.
     bool change = false;
 
     // NB: Calling Peek on |this|, not |thisVis|, since callers may look
@@ -238,17 +210,17 @@ ComputedStyle::CalcStyleDifference(Compu
 #define STYLE_FIELD(name_) thisVisStruct->name_ != otherVisStruct->name_
 #define STYLE_STRUCT(name_, fields_)                                    \
     if (PEEK(name_)) {                                                  \
       const nsStyle##name_* thisVisStruct =                             \
         thisVis->ThreadsafeStyle##name_();                              \
       const nsStyle##name_* otherVisStruct =                            \
         otherVis->ThreadsafeStyle##name_();                             \
       if (MOZ_FOR_EACH_SEPARATED(STYLE_FIELD, (||), (), fields_)) {     \
-        *aEqualStructs &= ~NS_STYLE_INHERIT_BIT(name_);                 \
+        *aEqualStructs &= ~STYLE_STRUCT_BIT(name_);                     \
         change = true;                                                  \
       }                                                                 \
     }
 #include "nsCSSVisitedDependentPropList.h"
 #undef STYLE_STRUCT
 #undef STYLE_FIELD
 
     if (change) {
@@ -394,42 +366,38 @@ ComputedStyle::CombineVisitedColors(nsco
   nscolor colorColor = aColors[set.colorIndex];
   nscolor alphaColor = aColors[set.alphaIndex];
   return NS_RGBA(NS_GET_R(colorColor), NS_GET_G(colorColor),
                  NS_GET_B(colorColor), NS_GET_A(alphaColor));
 }
 
 #ifdef DEBUG
 /* static */ const char*
-ComputedStyle::StructName(nsStyleStructID aSID)
+ComputedStyle::StructName(StyleStructID aSID)
 {
   switch (aSID) {
 #define STYLE_STRUCT(name_)     \
-    case eStyleStruct_##name_:  \
+    case StyleStructID::name_:  \
       return #name_;
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
     default:
       return "Unknown";
   }
 }
 
-/* static */ bool
-ComputedStyle::LookupStruct(const nsACString& aName, nsStyleStructID& aResult)
+/* static */ Maybe<StyleStructID>
+ComputedStyle::LookupStruct(const nsACString& aName)
 {
-  if (false)
-    ;
 #define STYLE_STRUCT(name_)             \
-  else if (aName.EqualsLiteral(#name_)) \
-    aResult = eStyleStruct_##name_;
+  if (aName.EqualsLiteral(#name_)) \
+    return Some(StyleStructID::name_);
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
-  else
-    return false;
-  return true;
+  return Nothing();
 }
 #endif // DEBUG
 
 ComputedStyle*
 ComputedStyle::GetCachedLazyPseudoStyle(CSSPseudoElementType aPseudo) const
 {
   MOZ_ASSERT(aPseudo != CSSPseudoElementType::NotPseudo &&
              aPseudo != CSSPseudoElementType::InheritingAnonBox &&
--- a/layout/style/ComputedStyle.h
+++ b/layout/style/ComputedStyle.h
@@ -16,48 +16,18 @@
 #include "mozilla/ServoComputedData.h"
 #include "mozilla/ServoTypes.h"
 #include "mozilla/ServoUtils.h"
 #include "mozilla/StyleComplexColor.h"
 #include "mozilla/CachedInheritingStyles.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSPseudoElements.h"
 
-// Includes nsStyleStructID.
 #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::IsStyleIfVisited
-#define NS_STYLE_IS_STYLE_IF_VISITED       0x008000000
-// 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;
 enum nsChangeHint : uint32_t;
 class nsIPresShell;
 class nsPresContext;
 class nsWindowSizes;
 
 #define STYLE_STRUCT(name_) struct nsStyle##name_;
 #include "nsStyleStructList.h"
@@ -90,16 +60,35 @@ class ComputedStyle;
  *  2. any *child* ComputedStyle (this might be the reverse of
  *     expectation, but it makes sense in this case)
  *
  * FIXME(emilio): This comment is somewhat outdated now.
  */
 
 class ComputedStyle
 {
+private:
+  enum class Bit : uint32_t
+  {
+    HasTextDecorationLines = 1 << 0,
+    HasPseudoElementData = 1 << 1,
+    SuppressLineBreak = 1 << 2,
+    IsTextCombined = 1 << 3,
+    RelevantLinkVisited = 1 << 4,
+  };
+
+  static const uint64_t kBitCount = 5;
+  static const uint64_t kBitsShift = StyleStructConstants::kStyleStructCount;
+  static const uint64_t kTypeShift = kBitsShift + kBitCount;
+
+  bool HasStyleBit(Bit aBit) const
+  {
+    return mBits & (static_cast<uint64_t>(aBit) << kBitsShift);
+  }
+
 public:
   ComputedStyle(nsPresContext* aPresContext,
                 nsAtom* aPseudoTag,
                 CSSPseudoElementType aPseudoType,
                 ServoComputedDataForgotten aComputedValues);
 
   // FIXME(emilio, bug 548397): This will need to go away. Don't add new callers
   // of this methed.
@@ -139,19 +128,19 @@ public:
 
   bool IsLazilyCascadedPseudoElement() const
   {
     return IsPseudoElement() &&
            !nsCSSPseudoElements::IsEagerlyCascadedInServo(GetPseudoType());
   }
 
   nsAtom* GetPseudo() const { return mPseudoTag; }
-  mozilla::CSSPseudoElementType GetPseudoType() const {
-    return static_cast<mozilla::CSSPseudoElementType>(
-             mBits >> NS_STYLE_CONTEXT_TYPE_SHIFT);
+  mozilla::CSSPseudoElementType GetPseudoType() const
+  {
+    return static_cast<mozilla::CSSPseudoElementType>(mBits >> kTypeShift);
   }
 
   bool IsInheritingAnonBox() const {
     return GetPseudoType() == mozilla::CSSPseudoElementType::InheritingAnonBox;
   }
 
   bool IsNonInheritingAnonBox() const {
     return GetPseudoType() == mozilla::CSSPseudoElementType::NonInheritingAnonBox;
@@ -171,50 +160,55 @@ public:
 
   bool IsPseudoElement() const { return mPseudoTag && !IsAnonBox(); }
 
   // Does this ComputedStyle 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); }
+  {
+    return HasStyleBit(Bit::HasTextDecorationLines);
+  }
 
   // Whether any line break inside should be suppressed? If this returns
   // true, the line should not be broken inside, which means inlines act
   // as if nowrap is set, <br> is suppressed, and blocks are inlinized.
   // This bit is propogated to all children of line partitipants. It is
   // currently used by ruby to make its content frames unbreakable.
   // NOTE: for nsTextFrame, use nsTextFrame::ShouldSuppressLineBreak()
   // instead of this method.
   bool ShouldSuppressLineBreak() const
-    { return !!(mBits & NS_STYLE_SUPPRESS_LINEBREAK); }
+  {
+    return HasStyleBit(Bit::SuppressLineBreak);
+  }
 
   // Is this horizontal-in-vertical (tate-chu-yoko) text? This flag is
   // only set on ComputedStyles whose pseudo is nsCSSAnonBoxes::mozText.
   bool IsTextCombined() const
-    { return !!(mBits & NS_STYLE_IS_TEXT_COMBINED); }
+  {
+    return HasStyleBit(Bit::IsTextCombined);
+  }
 
   // Does this ComputedStyle represent the style for a pseudo-element or
   // inherit data from such a ComputedStyle?  Whether this returns true
   // is equivalent to whether it or any of its ancestors returns
   // non-null for IsPseudoElement().
   bool HasPseudoElementData() const
-    { return !!(mBits & NS_STYLE_HAS_PSEUDO_ELEMENT_DATA); }
+  {
+    return HasStyleBit(Bit::HasPseudoElementData);
+  }
 
   // Is the only link whose visitedness is allowed to influence the
   // style of the node this ComputedStyle is for (which is that element
   // or its nearest ancestor that is a link) visited?
   bool RelevantLinkVisited() const
-    { return !!(mBits & NS_STYLE_RELEVANT_LINK_VISITED); }
-
-  // Is this ComputedStyle the GetStyleIfVisited() for some other style
-  // context?
-  bool IsStyleIfVisited() const
-    { return !!(mBits & NS_STYLE_IS_STYLE_IF_VISITED); }
+  {
+    return HasStyleBit(Bit::RelevantLinkVisited);
+  }
 
   ComputedStyle* GetCachedInheritingAnonBoxStyle(nsAtom* aAnonBox) const
   {
     MOZ_ASSERT(nsCSSAnonBoxes::IsInheritingAnonBox(aAnonBox));
     return mCachedInheritingStyles.Lookup(aAnonBox);
   }
 
   void SetCachedInheritedAnonBoxStyle(nsAtom* aAnonBox, ComputedStyle* aStyle)
@@ -321,30 +315,27 @@ public:
 
   /**
    * aColors should be a two element array of nscolor in which the first
    * color is the unvisited color and the second is the visited color.
    *
    * Combine the R, G, and B components of whichever of aColors should
    * be used based on aLinkIsVisited with the A component of aColors[0].
    */
-  static nscolor CombineVisitedColors(nscolor *aColors,
-                                      bool aLinkIsVisited);
+  static nscolor CombineVisitedColors(nscolor* aColors, bool aLinkIsVisited);
 
   /**
    * Start the background image loads for this ComputedStyle.
    */
   inline void StartBackgroundImageLoads();
 
-  static uint32_t GetBitForSID(const nsStyleStructID aSID) { return 1 << aSID; }
-
 #ifdef DEBUG
   void List(FILE* out, int32_t aIndent);
-  static const char* StructName(nsStyleStructID aSID);
-  static bool LookupStruct(const nsACString& aName, nsStyleStructID& aResult);
+  static const char* StructName(StyleStructID aSID);
+  static Maybe<StyleStructID> LookupStruct(const nsACString& aName);
 #endif
 
   /**
    * Makes this context match |aOther| in terms of which style structs have
    * been resolved.
    */
   inline void ResolveSameStructsAs(const ComputedStyle* aOther);
 
--- a/layout/style/ComputedStyleInlines.h
+++ b/layout/style/ComputedStyleInlines.h
@@ -37,47 +37,47 @@ const nsStyle##name_ * ComputedStyle::Pe
 }
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
 
 // Helper functions for GetStyle* and PeekStyle*
 #define STYLE_STRUCT_INHERITED(name_)                                       \
 template<bool aComputeData>                                                 \
 const nsStyle##name_ * ComputedStyle::DoGetStyle##name_() {                 \
-  const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));        \
+  const bool needToCompute = !(mBits & STYLE_STRUCT_BIT(name_));            \
   if (!aComputeData && needToCompute) {                                     \
     return nullptr;                                                         \
   }                                                                         \
                                                                             \
   const nsStyle##name_* data = ComputedData()->GetStyle##name_();           \
                                                                             \
   /* perform any remaining main thread work on the struct */                \
   if (needToCompute) {                                                      \
     MOZ_ASSERT(NS_IsMainThread());                                          \
     MOZ_ASSERT(!mozilla::IsInServoTraversal());                             \
     const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, nullptr);  \
     /* the ComputedStyle owns the struct */                                 \
-    AddStyleBit(NS_STYLE_INHERIT_BIT(name_));                               \
+    AddStyleBit(STYLE_STRUCT_BIT(name_));                                   \
   }                                                                         \
   return data;                                                              \
 }
 
 #define STYLE_STRUCT_RESET(name_)                                           \
 template<bool aComputeData>                                                 \
 const nsStyle##name_ * ComputedStyle::DoGetStyle##name_() {                 \
-  const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));        \
+  const bool needToCompute = !(mBits & STYLE_STRUCT_BIT(name_));            \
   if (!aComputeData && needToCompute) {                                     \
     return nullptr;                                                         \
   }                                                                         \
   const nsStyle##name_* data = ComputedData()->GetStyle##name_();           \
   /* perform any remaining main thread work on the struct */                \
   if (needToCompute) {                                                      \
     const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, nullptr);  \
     /* the ComputedStyle owns the struct */                                 \
-    AddStyleBit(NS_STYLE_INHERIT_BIT(name_));                               \
+    AddStyleBit(STYLE_STRUCT_BIT(name_));                                   \
   }                                                                         \
   return data;                                                              \
 }
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT_RESET
 #undef STYLE_STRUCT_INHERITED
 
 void
@@ -86,23 +86,23 @@ ComputedStyle::StartBackgroundImageLoads
   // Just get our background struct; that should do the trick
   StyleBackground();
 }
 
 void
 ComputedStyle::ResolveSameStructsAs(const ComputedStyle* aOther)
 {
   // Only resolve structs that are not already resolved in this struct.
-  uint64_t ourBits = mBits & NS_STYLE_INHERIT_MASK;
-  uint64_t otherBits = aOther->mBits & NS_STYLE_INHERIT_MASK;
-  uint64_t newBits = otherBits & ~ourBits & NS_STYLE_INHERIT_MASK;
+  uint64_t ourBits = mBits & StyleStructConstants::kAllStructsMask;
+  uint64_t otherBits = aOther->mBits & StyleStructConstants::kAllStructsMask;
+  uint64_t newBits = otherBits & ~ourBits & StyleStructConstants::kAllStructsMask;
 
 #define STYLE_STRUCT(name_)                                                    \
   if (nsStyle##name_::kHasFinishStyle &&                                       \
-      (newBits & NS_STYLE_INHERIT_BIT(name_))) {                               \
+      (newBits & STYLE_STRUCT_BIT(name_))) {                                   \
     const nsStyle##name_* data = ComputedData()->GetStyle##name_();            \
     const nsStyle##name_* oldData = aOther->ComputedData()->GetStyle##name_(); \
     const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, oldData);     \
   }
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
 
   mBits |= newBits;
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -345,28 +345,25 @@ Gecko_CalcStyleDifference(ComputedStyleB
                           ComputedStyleBorrowed aNewStyle,
                           bool* aAnyStyleStructChanged,
                           bool* aOnlyResetStructsChanged)
 {
   MOZ_ASSERT(aOldStyle);
   MOZ_ASSERT(aNewStyle);
 
   uint32_t equalStructs;
-  nsChangeHint result = const_cast<mozilla::ComputedStyle*>(aOldStyle)->
-    CalcStyleDifference(
-      const_cast<mozilla::ComputedStyle*>(aNewStyle),
-      &equalStructs);
-
-  *aAnyStyleStructChanged = equalStructs != NS_STYLE_INHERIT_MASK;
-
-  const uint32_t kInheritStructsMask =
-    NS_STYLE_INHERIT_MASK & ~NS_STYLE_RESET_STRUCT_MASK;
-
+  nsChangeHint result = const_cast<ComputedStyle*>(aOldStyle)->
+    CalcStyleDifference(const_cast<ComputedStyle*>(aNewStyle), &equalStructs);
+
+  *aAnyStyleStructChanged =
+    equalStructs != StyleStructConstants::kAllStructsMask;
+
+  const auto kInheritedStructsMask = StyleStructConstants::kInheritedStructsMask;
   *aOnlyResetStructsChanged =
-    (equalStructs & kInheritStructsMask) == kInheritStructsMask;
+    (equalStructs & kInheritedStructsMask) == kInheritedStructsMask;
 
   return result;
 }
 
 const ServoElementSnapshot*
 Gecko_GetElementSnapshot(const ServoElementSnapshotTable* aTable,
                          const Element* aElement)
 {
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -40,20 +40,16 @@
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #include <algorithm>
 #include "ImageLoader.h"
 
 using namespace mozilla;
 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::kMaxLine;
 
 // We set the size limit of style structs to 504 bytes so that when they
 // are allocated by Servo side with Arc, the total size doesn't exceed
 // 512 bytes, which minimizes allocator slop.
 static constexpr size_t kStyleStructSizeLimit = 504;
 #define STYLE_STRUCT(name_) \
--- a/layout/style/nsStyleStructFwd.h
+++ b/layout/style/nsStyleStructFwd.h
@@ -6,58 +6,78 @@
 
 /*
  * Forward declarations to avoid including all of nsStyleStruct.h.
  */
 
 #ifndef nsStyleStructFwd_h_
 #define nsStyleStructFwd_h_
 
-enum nsStyleStructID {
+namespace mozilla {
 
+enum class StyleStructID : uint32_t {
 /*
  * Define the constants eStyleStruct_Font, etc.
  *
  * The C++ standard, section 7.2, guarantees that enums begin with 0 and
  * increase by 1.
  *
- * We separate the IDs of Reset and Inherited structs so that we can use
- * the IDs as indices (offset by nsStyleStructID_*_Start) into arrays of
- * one type or the other.
+ * Note that we rely on the inherited structs being before the rest in
+ * ComputedStyle.
  */
-
-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_INHERITED(name) name,
 #define STYLE_STRUCT_RESET(name)
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT_INHERITED
 #undef STYLE_STRUCT_RESET
 
-nsStyleStructID_Reset_Start,
-// 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_RESET(name) name,
 #define STYLE_STRUCT_INHERITED(name)
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT_INHERITED
 #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,
-
 };
 
+struct StyleStructConstants
+{
+  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;
+
+  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
+
 // A bit corresponding to each struct ID
-#define NS_STYLE_INHERIT_BIT(sid_)        (1 << uint64_t(eStyleStruct_##sid_))
-
-typedef decltype(nsStyleStructID(0) + nsStyleStructID(0)) nsStyleStructID_size_t;
+#define STYLE_STRUCT_BIT(name_) \
+  mozilla::StyleStructConstants::BitFor(mozilla::StyleStructID::name_)
 
 #endif /* nsStyleStructFwd_h_ */
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -36,17 +36,16 @@ use gecko_bindings::bindings::Gecko_SetL
 use gecko_bindings::bindings::Gecko_SetListStyleImageImageValue;
 use gecko_bindings::bindings::Gecko_SetNullImageValue;
 use gecko_bindings::bindings::{Gecko_ResetFilters, Gecko_CopyFiltersFrom};
 use gecko_bindings::bindings::RawGeckoPresContextBorrowed;
 use gecko_bindings::structs;
 use gecko_bindings::structs::nsCSSPropertyID;
 use gecko_bindings::structs::mozilla::CSSPseudoElementType;
 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::refptr::RefPtr;
 use gecko::values::convert_nscolor_to_rgba;
 use gecko::values::convert_rgba_to_nscolor;
 use gecko::values::GeckoStyleCoordConvertible;
 use gecko::values::round_border_to_device_pixels;
 use logical_geometry::WritingMode;
 use media_queries::Device;
@@ -134,17 +133,17 @@ impl ComputedValues {
         }
 
         let atom = unsafe { Atom::from_raw(atom) };
         PseudoElement::from_atom(&atom)
     }
 
     fn get_pseudo_type(&self) -> CSSPseudoElementType {
         let bits = (self.0).mBits;
-        let our_type = bits >> NS_STYLE_CONTEXT_TYPE_SHIFT;
+        let our_type = bits >> structs::ComputedStyle_kTypeShift;
         unsafe { transmute(our_type as u8) }
     }
 
     pub fn is_anon_box(&self) -> bool {
         let our_type = self.get_pseudo_type();
         return our_type == CSSPseudoElementType_InheritingAnonBox ||
                our_type == CSSPseudoElementType::NonInheritingAnonBox;
     }
@@ -2980,17 +2979,16 @@ fn static_assert() {
 
 <%def name="impl_animation_keyword(ident, gecko_ffi_name, keyword, cast_type='u8')">
     #[allow(non_snake_case)]
     pub fn set_animation_${ident}<I>(&mut self, v: I)
         where I: IntoIterator<Item = longhands::animation_${ident}::computed_value::single_value::T>,
               I::IntoIter: ExactSizeIterator + Clone
     {
         use properties::longhands::animation_${ident}::single_value::computed_value::T as Keyword;
-        use gecko_bindings::structs;
 
         let v = v.into_iter();
 
         debug_assert_ne!(v.len(), 0);
         let input_len = v.len();
         self.gecko.mAnimations.ensure_len(input_len);
 
         self.gecko.mAnimation${gecko_ffi_name}Count = input_len as u32;
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -3098,29 +3098,29 @@ pub unsafe extern "C" fn Servo_ComputedV
 
 #[no_mangle]
 pub extern "C" fn Servo_ComputedValues_GetStyleBits(values: ComputedStyleBorrowed) -> u64 {
     use style::properties::computed_value_flags::ComputedValueFlags;
     // FIXME(emilio): We could do this more efficiently I'm quite sure.
     let flags = values.flags;
     let mut result = 0;
     if flags.contains(ComputedValueFlags::IS_RELEVANT_LINK_VISITED) {
-        result |= structs::NS_STYLE_RELEVANT_LINK_VISITED as u64;
+        result |= structs::ComputedStyle_Bit_RelevantLinkVisited as u64;
     }
     if flags.contains(ComputedValueFlags::HAS_TEXT_DECORATION_LINES) {
-        result |= structs::NS_STYLE_HAS_TEXT_DECORATION_LINES as u64;
+        result |= structs::ComputedStyle_Bit_HasTextDecorationLines as u64;
     }
     if flags.contains(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK) {
-        result |= structs::NS_STYLE_SUPPRESS_LINEBREAK as u64;
+        result |= structs::ComputedStyle_Bit_SuppressLineBreak as u64;
     }
     if flags.contains(ComputedValueFlags::IS_TEXT_COMBINED) {
-        result |= structs::NS_STYLE_IS_TEXT_COMBINED as u64;
+        result |= structs::ComputedStyle_Bit_IsTextCombined as u64;
     }
     if flags.contains(ComputedValueFlags::IS_IN_PSEUDO_ELEMENT_SUBTREE) {
-        result |= structs::NS_STYLE_HAS_PSEUDO_ELEMENT_DATA as u64;
+        result |= structs::ComputedStyle_Bit_HasPseudoElementData as u64;
     }
     result
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_ComputedValues_SpecifiesAnimationsOrTransitions(
     values: ComputedStyleBorrowed,
 ) -> bool {