Bug 1188721 - Part 3: Update refcounts of style structs stored in style contexts and rule nodes. r?dbaron draft
authorCameron McCormack <cam@mcc.id.au>
Wed, 23 Mar 2016 17:35:58 +1100
changeset 343753 ed5d5d8e740ba35535711a4be6444ef7ecb3e5af
parent 343752 c479cf7d499edbe188760444b9dc898be3920953
child 343754 f5e5637e85325cc557aafd967535616c86a3ef72
push id13680
push usercmccormack@mozilla.com
push dateWed, 23 Mar 2016 06:36:18 +0000
reviewersdbaron
bugs1188721
milestone48.0a1
Bug 1188721 - Part 3: Update refcounts of style structs stored in style contexts and rule nodes. r?dbaron MozReview-Commit-ID: ZoIQyWKnRW
layout/style/nsRuleNode.cpp
layout/style/nsRuleNode.h
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -2733,21 +2733,18 @@ nsRuleNode::SetDefaultOnRoot(const nsSty
                    "specified with values other than inherit");               \
   if (conditions.CacheableWithoutDependencies()) {                            \
     /* We were fully specified and can therefore be cached right on the */    \
     /* rule node. */                                                          \
     if (!aHighestNode->mStyleData.mInheritedData) {                           \
       aHighestNode->mStyleData.mInheritedData =                               \
         new (mPresContext) nsInheritedStyleData;                              \
     }                                                                         \
-    NS_ASSERTION(!aHighestNode->mStyleData.mInheritedData->                   \
-                   mStyleStructs[eStyleStruct_##type_],                       \
-                 "Going to leak style data");                                 \
     aHighestNode->mStyleData.mInheritedData->                                 \
-      mStyleStructs[eStyleStruct_##type_] = data_;                            \
+      SetStyleData(eStyleStruct_##type_, data_);                              \
     /* Propagate the bit down. */                                             \
     PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_);         \
     /* Tell the style context that it doesn't own the data */                 \
     aContext->AddStyleBit(NS_STYLE_INHERIT_BIT(type_));                       \
   }                                                                           \
   /* For inherited structs, our caller will cache the data on the */          \
   /* style context */                                                         \
                                                                               \
@@ -2769,19 +2766,16 @@ nsRuleNode::SetDefaultOnRoot(const nsSty
                    "inherit");                                                \
   if (conditions.CacheableWithoutDependencies()) {                            \
     /* We were fully specified and can therefore be cached right on the */    \
     /* rule node. */                                                          \
     if (!aHighestNode->mStyleData.mResetData) {                               \
       aHighestNode->mStyleData.mResetData =                                   \
         new (mPresContext) nsConditionalResetStyleData;                       \
     }                                                                         \
-    NS_ASSERTION(!aHighestNode->mStyleData.mResetData->                       \
-                   GetStyleData(eStyleStruct_##type_),                        \
-                 "Going to leak style data");                                 \
     aHighestNode->mStyleData.mResetData->                                     \
       SetStyleData(eStyleStruct_##type_, data_);                              \
     /* Propagate the bit down. */                                             \
     PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_);         \
   } else if (conditions.Cacheable()) {                                        \
     if (!mStyleData.mResetData) {                                             \
       mStyleData.mResetData = new (mPresContext) nsConditionalResetStyleData; \
     }                                                                         \
--- a/layout/style/nsRuleNode.h
+++ b/layout/style/nsRuleNode.h
@@ -24,21 +24,41 @@ class nsCSSValue;
 class nsIStyleRule;
 class nsStyleContext;
 class nsStyleCoord;
 struct nsCSSRect;
 struct nsCSSValueList;
 struct nsCSSValuePairList;
 struct nsRuleData;
 
-struct nsInheritedStyleData
+class nsInheritedStyleData
 {
-  mozilla::RangedArray<nsStyleStruct*,
-                       nsStyleStructID_Inherited_Start,
-                       nsStyleStructID_Inherited_Count> mStyleStructs;
+public:
+  nsStyleStruct* GetStyleData(nsStyleStructID aSID) const {
+    return mStyleStructs[aSID];
+  }
+  void SetStyleData(nsStyleStructID aSID, nsStyleStruct* aStyleStruct) {
+    MOZ_ASSERT(aStyleStruct);
+    if (mStyleStructs[aSID] != aStyleStruct) {
+      NS_ASSERTION(!mStyleStructs[aSID], "Going to leak style data");
+      aStyleStruct->AddRef();
+      mStyleStructs[aSID] = aStyleStruct;
+    }
+  }
+  void ClearStyleData(nsStyleStructID aSID) {
+    if (mStyleStructs[aSID]) {
+      // XXX A later patch will act upon the ReleaseWithoutDestroying
+      // return value.
+      Unused << mStyleStructs[aSID]->ReleaseWithoutDestroying();
+    }
+    mStyleStructs[aSID] = nullptr;
+  }
+  void SwapStyleData(nsStyleStructID aSID, nsInheritedStyleData& aOther) {
+    std::swap(mStyleStructs[aSID], aOther.mStyleStructs[aSID]);
+  }
 
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsInheritedStyleData, sz);
   }
 
   void DestroyStructs(uint64_t aBits, nsPresContext* aContext) {
 #define STYLE_STRUCT_INHERITED(name, checkdata_cb) \
@@ -61,23 +81,48 @@ struct nsInheritedStyleData
 
   nsInheritedStyleData() {
     for (nsStyleStructID i = nsStyleStructID_Inherited_Start;
          i < nsStyleStructID_Inherited_Start + nsStyleStructID_Inherited_Count;
          i = nsStyleStructID(i + 1)) {
       mStyleStructs[i] = nullptr;
     }
   }
+
+private:
+  mozilla::RangedArray<nsStyleStruct*,
+                       nsStyleStructID_Inherited_Start,
+                       nsStyleStructID_Inherited_Count> mStyleStructs;
 };
 
-struct nsResetStyleData
+class nsResetStyleData
 {
-  mozilla::RangedArray<nsStyleStruct*,
-                       nsStyleStructID_Reset_Start,
-                       nsStyleStructID_Reset_Count> mStyleStructs;
+public:
+  nsStyleStruct* GetStyleData(nsStyleStructID aSID) const {
+    return mStyleStructs[aSID];
+  }
+  void SetStyleData(nsStyleStructID aSID, nsStyleStruct* aStyleStruct) {
+    MOZ_ASSERT(aStyleStruct);
+    if (mStyleStructs[aSID] != aStyleStruct) {
+      NS_ASSERTION(!mStyleStructs[aSID], "Going to leak style data");
+      aStyleStruct->AddRef();
+      mStyleStructs[aSID] = aStyleStruct;
+    }
+  }
+  void ClearStyleData(nsStyleStructID aSID) {
+    if (mStyleStructs[aSID]) {
+      // XXX A later patch will act upon the ReleaseWithoutDestroying
+      // return value.
+      Unused << mStyleStructs[aSID]->ReleaseWithoutDestroying();
+    }
+    mStyleStructs[aSID] = nullptr;
+  }
+  void SwapStyleData(nsStyleStructID aSID, nsResetStyleData& aOther) {
+    std::swap(mStyleStructs[aSID], aOther.mStyleStructs[aSID]);
+  }
 
   nsResetStyleData()
   {
     for (nsStyleStructID i = nsStyleStructID_Reset_Start;
          i < nsStyleStructID_Reset_Start + nsStyleStructID_Reset_Count;
          i = nsStyleStructID(i + 1)) {
       mStyleStructs[i] = nullptr;
     }
@@ -98,50 +143,30 @@ struct nsResetStyleData
 #include "nsStyleStructList.h"
 
 #undef STYLE_STRUCT_RESET
 #undef STYLE_STRUCT_INHERITED
 
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsResetStyleData, this);
   }
+
+private:
+  mozilla::RangedArray<nsStyleStruct*,
+                       nsStyleStructID_Reset_Start,
+                       nsStyleStructID_Reset_Count> mStyleStructs;
 };
 
-struct nsConditionalResetStyleData
+class nsConditionalResetStyleData
 {
+public:
   static uint32_t GetBitForSID(const nsStyleStructID aSID) {
     return 1 << aSID;
   }
 
-  struct Entry
-  {
-    Entry(const mozilla::RuleNodeCacheConditions& aConditions,
-          nsStyleStruct* aStyleStruct,
-          Entry* aNext)
-      : mConditions(aConditions), mStyleStruct(aStyleStruct), mNext(aNext) {}
-
-    void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
-      return aContext->PresShell()->AllocateByObjectID(
-          mozilla::eArenaObjectID_nsConditionalResetStyleDataEntry, sz);
-    }
-
-    const mozilla::RuleNodeCacheConditions mConditions;
-    nsStyleStruct* const mStyleStruct;
-    Entry* const mNext;
-  };
-
-  // Each entry is either a pointer to a style struct or a
-  // pointer to an Entry object.  A bit in mConditionalBits
-  // means that it is an Entry.
-  mozilla::RangedArray<void*,
-                       nsStyleStructID_Reset_Start,
-                       nsStyleStructID_Reset_Count> mEntries;
-
-  uint32_t mConditionalBits;
-
   nsConditionalResetStyleData()
   {
     for (nsStyleStructID i = nsStyleStructID_Reset_Start;
          i < nsStyleStructID_Reset_Start + nsStyleStructID_Reset_Count;
          i = nsStyleStructID(i + 1)) {
       mEntries[i] = nullptr;
     }
     mConditionalBits = 0;
@@ -182,38 +207,45 @@ private:
   nsStyleStruct* GetConditionalStyleData(nsStyleStructID aSID,
                                          nsStyleContext* aStyleContext) const;
 
 public:
   void SetStyleData(nsStyleStructID aSID, nsStyleStruct* aStyleStruct) {
     MOZ_ASSERT(!(mConditionalBits & GetBitForSID(aSID)),
                "rule node should not have unconditional and conditional style "
                "data for a given struct");
-    mEntries[aSID] = aStyleStruct;
+    MOZ_ASSERT(aStyleStruct);
+    if (mEntries[aSID] != aStyleStruct) {
+      NS_ASSERTION(!mEntries[aSID], "Going to leak style data");
+      aStyleStruct->AddRef();
+      mEntries[aSID] = aStyleStruct;
+    }
   }
 
   void SetStyleData(nsStyleStructID aSID,
                     nsPresContext* aPresContext,
                     nsStyleStruct* aStyleStruct,
                     const mozilla::RuleNodeCacheConditions& aConditions) {
     MOZ_ASSERT((mConditionalBits & GetBitForSID(aSID)) ||
                !mEntries[aSID],
                "rule node should not have unconditional and conditional style "
                "data for a given struct");
+    MOZ_ASSERT(aStyleStruct);
     MOZ_ASSERT(aConditions.CacheableWithDependencies(),
                "don't call SetStyleData with a cache key that has no "
                "conditions or is uncacheable");
 #ifdef DEBUG
     for (Entry* e = static_cast<Entry*>(mEntries[aSID]); e; e = e->mNext) {
       NS_WARN_IF_FALSE(e->mConditions != aConditions,
                        "wasteful to have duplicate conditional style data");
     }
 #endif
 
     mConditionalBits |= GetBitForSID(aSID);
+    aStyleStruct->AddRef();
     mEntries[aSID] =
       new (aPresContext) Entry(aConditions, aStyleStruct,
                                static_cast<Entry*>(mEntries[aSID]));
   }
 
   void Destroy(uint64_t aBits, nsPresContext* aContext) {
 #define STYLE_STRUCT_RESET(name, checkdata_cb)                                 \
     void* name##Ptr = mEntries[eStyleStruct_##name];                           \
@@ -241,16 +273,42 @@ public:
 
 #undef STYLE_STRUCT_RESET
 #undef STYLE_STRUCT_INHERITED
 
     aContext->PresShell()->FreeByObjectID(
         mozilla::eArenaObjectID_nsConditionalResetStyleData, this);
   }
 
+private:
+  struct Entry
+  {
+    Entry(const mozilla::RuleNodeCacheConditions& aConditions,
+          nsStyleStruct* aStyleStruct,
+          Entry* aNext)
+      : mConditions(aConditions), mStyleStruct(aStyleStruct), mNext(aNext) {}
+
+    void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
+      return aContext->PresShell()->AllocateByObjectID(
+          mozilla::eArenaObjectID_nsConditionalResetStyleDataEntry, sz);
+    }
+
+    const mozilla::RuleNodeCacheConditions mConditions;
+    nsStyleStruct* const mStyleStruct;
+    Entry* const mNext;
+  };
+
+  // Each entry is either a pointer to a style struct or a
+  // pointer to an Entry object.  A bit in mConditionalBits
+  // means that it is an Entry.
+  mozilla::RangedArray<void*,
+                       nsStyleStructID_Reset_Start,
+                       nsStyleStructID_Reset_Count> mEntries;
+
+  uint32_t mConditionalBits;
 };
 
 struct nsCachedStyleData
 {
   nsInheritedStyleData* mInheritedData;
   nsConditionalResetStyleData* mResetData;
 
   static bool IsReset(const nsStyleStructID aSID) {
@@ -269,32 +327,32 @@ struct nsCachedStyleData
 
   nsStyleStruct* NS_FASTCALL GetStyleData(const nsStyleStructID aSID) {
     if (IsReset(aSID)) {
       if (mResetData) {
         return mResetData->GetStyleData(aSID);
       }
     } else {
       if (mInheritedData) {
-        return mInheritedData->mStyleStructs[aSID];
+        return mInheritedData->GetStyleData(aSID);
       }
     }
     return nullptr;
   }
 
   nsStyleStruct* NS_FASTCALL GetStyleData(const nsStyleStructID aSID,
                                           nsStyleContext* aStyleContext,
                                           bool aCanComputeData) {
     if (IsReset(aSID)) {
       if (mResetData) {
         return mResetData->GetStyleData(aSID, aStyleContext, aCanComputeData);
       }
     } else {
       if (mInheritedData) {
-        return mInheritedData->mStyleStructs[aSID];
+        return mInheritedData->GetStyleData(aSID);
       }
     }
     return nullptr;
   }
 
   void NS_FASTCALL SetStyleData(const nsStyleStructID aSID,
                                 nsPresContext *aPresContext,
                                 nsStyleStruct* aData) {
@@ -302,25 +360,25 @@ struct nsCachedStyleData
       if (!mResetData) {
         mResetData = new (aPresContext) nsConditionalResetStyleData;
       }
       mResetData->SetStyleData(aSID, aData);
     } else {
       if (!mInheritedData) {
         mInheritedData = new (aPresContext) nsInheritedStyleData;
       }
-      mInheritedData->mStyleStructs[aSID] = aData;
+      mInheritedData->SetStyleData(aSID, aData);
     }
   }
 
   // Typesafe and faster versions of the above
   #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_)                         \
     nsStyle##name_ * NS_FASTCALL GetStyle##name_ () {                          \
       return mInheritedData ? static_cast<nsStyle##name_*>(                    \
-        mInheritedData->mStyleStructs[eStyleStruct_##name_]) : nullptr;        \
+        mInheritedData->GetStyleData(eStyleStruct_##name_)) : nullptr;         \
     }
   #define STYLE_STRUCT_RESET(name_, checkdata_cb_)                             \
     nsStyle##name_ * NS_FASTCALL GetStyle##name_ (nsStyleContext* aContext,    \
                                                   bool aCanComputeData) {      \
       return mResetData ? static_cast<nsStyle##name_*>(                        \
         mResetData->GetStyleData(eStyleStruct_##name_, aContext,               \
                                  aCanComputeData))                             \
                         : nullptr;                                             \
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -205,20 +205,20 @@ nsStyleContext::AssertStructsNotUsedElse
   if (mBits & NS_STYLE_IS_GOING_AWAY) {
     return;
   }
 
   if (this != aDestroyingContext) {
     nsInheritedStyleData& destroyingInheritedData =
       aDestroyingContext->mCachedInheritedData;
 #define STYLE_STRUCT_INHERITED(name_, checkdata_cb)                            \
-    data = destroyingInheritedData.mStyleStructs[eStyleStruct_##name_];        \
+    data = destroyingInheritedData.GetStyleData(eStyleStruct_##name_);         \
     if (data &&                                                                \
         !(aDestroyingContext->mBits & NS_STYLE_INHERIT_BIT(name_)) &&          \
-         (mCachedInheritedData.mStyleStructs[eStyleStruct_##name_] == data)) { \
+         (mCachedInheritedData.GetStyleData(eStyleStruct_##name_) == data)) {  \
       printf_stderr("style struct %p found on style context %p\n", data, this);\
       nsString url;                                                            \
       PresContext()->Document()->GetURL(url);                                  \
       printf_stderr("  in %s\n", NS_ConvertUTF16toUTF8(url).get());            \
       MOZ_ASSERT(false, "destroying " #name_ " style struct still present "    \
                         "in style context tree");                              \
     }
 #define STYLE_STRUCT_RESET(name_, checkdata_cb)
@@ -229,20 +229,20 @@ nsStyleContext::AssertStructsNotUsedElse
 #undef STYLE_STRUCT_RESET
 
     if (mCachedResetData) {
       nsResetStyleData* destroyingResetData =
         aDestroyingContext->mCachedResetData;
       if (destroyingResetData) {
 #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_)
 #define STYLE_STRUCT_RESET(name_, checkdata_cb)                                \
-        data = destroyingResetData->mStyleStructs[eStyleStruct_##name_];       \
+        data = destroyingResetData->GetStyleData(eStyleStruct_##name_);        \
         if (data &&                                                            \
             !(aDestroyingContext->mBits & NS_STYLE_INHERIT_BIT(name_)) &&      \
-            (mCachedResetData->mStyleStructs[eStyleStruct_##name_] == data)) { \
+            (mCachedResetData->GetStyleData(eStyleStruct_##name_) == data)) {  \
           printf_stderr("style struct %p found on style context %p\n", data,   \
                         this);                                                 \
           nsString url;                                                        \
           PresContext()->Document()->GetURL(url);                              \
           printf_stderr("  in %s\n", NS_ConvertUTF16toUTF8(url).get());        \
           MOZ_ASSERT(false, "destroying " #name_ " style struct still present "\
                             "in style context tree");                          \
         }
@@ -420,17 +420,17 @@ nsStyleContext::StyleData(nsStyleStructI
   const nsStyleStruct* cachedData = GetCachedStyleData(aSID);
   if (cachedData)
     return cachedData; // We have computed data stored on this node in the context tree.
   // Our rule node will take care of it for us.
   const nsStyleStruct* newData = mRuleNode->GetStyleData(aSID, this, true);
   if (!nsCachedStyleData::IsReset(aSID)) {
     // always cache inherited data on the style context; the rule
     // node set the bit in mBits for us if needed.
-    mCachedInheritedData.mStyleStructs[aSID] = const_cast<nsStyleStruct*>(newData);
+    mCachedInheritedData.SetStyleData(aSID, const_cast<nsStyleStruct*>(newData));
   }
   return newData;
 }
 
 // This is an evil evil function, since it forces you to alloc your own separate copy of
 // style data!  Do not use this function unless you absolutely have to!  You should avoid
 // this at all costs! -dwh
 nsStyleStruct*
@@ -517,28 +517,24 @@ nsStyleContext::SetStyle(nsStyleStructID
   // method!
   
   NS_ASSERTION(aSID >= 0 && aSID < nsStyleStructID_Length, "out of bounds");
 
   // NOTE:  nsCachedStyleData::GetStyleData works roughly the same way.
   // See the comments there (in nsRuleNode.h) for more details about
   // what this is doing and why.
 
-  nsStyleStruct** dataSlot;
   if (nsCachedStyleData::IsReset(aSID)) {
     if (!mCachedResetData) {
       mCachedResetData = new (mRuleNode->PresContext()) nsResetStyleData;
     }
-    dataSlot = &mCachedResetData->mStyleStructs[aSID];
+    mCachedResetData->SetStyleData(aSID, aStruct);
   } else {
-    dataSlot = &mCachedInheritedData.mStyleStructs[aSID];
+    mCachedInheritedData.SetStyleData(aSID, aStruct);
   }
-  NS_ASSERTION(!*dataSlot || (mBits & nsCachedStyleData::GetBitForSID(aSID)),
-               "Going to leak style data");
-  *dataSlot = aStruct;
 }
 
 static bool
 ShouldSuppressLineBreak(const nsStyleContext* aContext,
                         const nsStyleDisplay* aDisplay,
                         const nsStyleContext* aParentContext,
                         const nsStyleDisplay* aParentDisplay)
 {
@@ -1392,24 +1388,24 @@ nsStyleContext::SwapStyleData(nsStyleCon
 
   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)) {
       continue;
     }
-    nsStyleStruct*& thisData = mCachedInheritedData.mStyleStructs[i];
-    nsStyleStruct*& otherData = aNewContext->mCachedInheritedData.mStyleStructs[i];
+    nsStyleStruct* thisData = mCachedInheritedData.GetStyleData(i);
+    nsStyleStruct* otherData = aNewContext->mCachedInheritedData.GetStyleData(i);
     if (mBits & bit) {
       if (thisData == otherData) {
-        thisData = nullptr;
+        mCachedInheritedData.ClearStyleData(i);
       }
     } else if (!(aNewContext->mBits & bit) && thisData && otherData) {
-      std::swap(thisData, otherData);
+      mCachedInheritedData.SwapStyleData(i, aNewContext->mCachedInheritedData);
     }
   }
 
   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)) {
@@ -1417,24 +1413,24 @@ nsStyleContext::SwapStyleData(nsStyleCon
     }
     if (!mCachedResetData) {
       mCachedResetData = new (mRuleNode->PresContext()) nsResetStyleData;
     }
     if (!aNewContext->mCachedResetData) {
       aNewContext->mCachedResetData =
         new (mRuleNode->PresContext()) nsResetStyleData;
     }
-    nsStyleStruct*& thisData = mCachedResetData->mStyleStructs[i];
-    nsStyleStruct*& otherData = aNewContext->mCachedResetData->mStyleStructs[i];
+    nsStyleStruct* thisData = mCachedResetData->GetStyleData(i);
+    nsStyleStruct* otherData = aNewContext->mCachedResetData->GetStyleData(i);
     if (mBits & bit) {
       if (thisData == otherData) {
-        thisData = nullptr;
+        mCachedResetData->ClearStyleData(i);
       }
     } else if (!(aNewContext->mBits & bit) && thisData && otherData) {
-      std::swap(thisData, otherData);
+      mCachedResetData->SwapStyleData(i, *aNewContext->mCachedResetData);
     }
   }
 }
 
 void
 nsStyleContext::ClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs)
 {
   if (mChild) {
@@ -1457,34 +1453,34 @@ 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]) {
+      if (!(mBits & bit) && mCachedInheritedData.GetStyleData(i)) {
         aStructs &= ~bit;
       } else {
-        mCachedInheritedData.mStyleStructs[i] = nullptr;
+        mCachedInheritedData.ClearStyleData(i);
       }
     }
   }
 
   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]) {
+        if (!(mBits & bit) && mCachedResetData->GetStyleData(i)) {
           aStructs &= ~bit;
         } else {
-          mCachedResetData->mStyleStructs[i] = nullptr;
+          mCachedResetData->ClearStyleData(i);
         }
       }
     }
   }
 
   if (aStructs == 0) {
     return;
   }
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -447,22 +447,22 @@ public:
    *
    * For "internal" use only in nsStyleContext and nsRuleNode.
    */
   const nsStyleStruct* GetCachedStyleData(nsStyleStructID aSID)
   {
     const nsStyleStruct* cachedData;
     if (nsCachedStyleData::IsReset(aSID)) {
       if (mCachedResetData) {
-        cachedData = mCachedResetData->mStyleStructs[aSID];
+        cachedData = mCachedResetData->GetStyleData(aSID);
       } else {
         cachedData = nullptr;
       }
     } else {
-      cachedData = mCachedInheritedData.mStyleStructs[aSID];
+      cachedData = mCachedInheritedData.GetStyleData(aSID);
     }
     return cachedData;
   }
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~nsStyleContext();
 
@@ -504,41 +504,41 @@ private:
 #endif
 
   // Helper functions for GetStyle* and PeekStyle*
   #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_)                  \
     template<bool aComputeData>                                         \
     const nsStyle##name_ * DoGetStyle##name_() {                        \
       const nsStyle##name_ * cachedData =                               \
         static_cast<nsStyle##name_*>(                                   \
-          mCachedInheritedData.mStyleStructs[eStyleStruct_##name_]);    \
+          mCachedInheritedData.GetStyleData(eStyleStruct_##name_));     \
       if (cachedData) /* Have it cached already, yay */                 \
         return cachedData;                                              \
       if (!aComputeData) {                                              \
         /* We always cache inherited structs on the context when we */  \
         /* compute them. */                                             \
         return nullptr;                                                 \
       }                                                                 \
       /* Have the rulenode deal */                                      \
       AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_);                      \
       const nsStyle##name_ * newData =                                  \
         mRuleNode->GetStyle##name_<aComputeData>(this, mBits);          \
       /* always cache inherited data on the style context; the rule */  \
       /* node set the bit in mBits for us if needed. */                 \
-      mCachedInheritedData.mStyleStructs[eStyleStruct_##name_] =        \
-        const_cast<nsStyle##name_ *>(newData);                          \
+      mCachedInheritedData.SetStyleData(eStyleStruct_##name_,           \
+        const_cast<nsStyle##name_ *>(newData));                         \
       return newData;                                                   \
     }
   #define STYLE_STRUCT_RESET(name_, checkdata_cb_)                      \
     template<bool aComputeData>                                         \
     const nsStyle##name_ * DoGetStyle##name_() {                        \
       if (mCachedResetData) {                                           \
         const nsStyle##name_ * cachedData =                             \
           static_cast<nsStyle##name_*>(                                 \
-            mCachedResetData->mStyleStructs[eStyleStruct_##name_]);     \
+            mCachedResetData->GetStyleData(eStyleStruct_##name_));      \
         if (cachedData) /* Have it cached already, yay */               \
           return cachedData;                                            \
       }                                                                 \
       /* Have the rulenode deal */                                      \
       AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_);                      \
       return mRuleNode->GetStyle##name_<aComputeData>(this);            \
     }
   #include "nsStyleStructList.h"