Bug 1290218 Part 2: Uplift mInner pointer from CSSStyleSheetInner into StyleSheetInfo. draft
authorBrad Werth <bwerth@mozilla.com>
Tue, 14 Feb 2017 09:41:33 -0800
changeset 488919 ce81d4fae368b5aa2d29d983605a22ce856a9444
parent 488918 f53a1339fc34107f90b081e90d3a718b8efc68f8
child 488920 7b976dae3061fe128f32313d8597d7a6c35d3eff
push id46687
push userbwerth@mozilla.com
push dateFri, 24 Feb 2017 01:52:48 +0000
bugs1290218
milestone54.0a1
Bug 1290218 Part 2: Uplift mInner pointer from CSSStyleSheetInner into StyleSheetInfo. MozReview-Commit-ID: K6FbTN1r4Qg
layout/style/CSSStyleSheet.cpp
layout/style/CSSStyleSheet.h
layout/style/StyleSheet.cpp
layout/style/StyleSheet.h
layout/style/nsCSSRuleProcessor.cpp
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -213,18 +213,18 @@ CSSStyleSheet::SizeOfIncludingThis(Mallo
   while (s) {
     // Each inner can be shared by multiple sheets.  So we only count the inner
     // if this sheet is the last one in the list of those sharing it.  As a
     // result, the last such sheet takes all the blame for the memory
     // consumption of the inner, which isn't ideal but it's better than
     // double-counting the inner.  We use last instead of first since the first
     // sheet may be held in the nsXULPrototypeCache and not used in a window at
     // all.
-    if (s->mInner->mSheets.LastElement() == s) {
-      n += s->mInner->SizeOfIncludingThis(aMallocSizeOf);
+    if (Inner()->mSheets.LastElement() == s) {
+      n += Inner()->SizeOfIncludingThis(aMallocSizeOf);
     }
 
     // Measurement of the following members may be added later if DMD finds it
     // is worthwhile:
     // - s->mRuleCollection
     // - s->mRuleProcessors
     //
     // The following members are not measured:
@@ -397,36 +397,35 @@ CSSStyleSheet::CSSStyleSheet(const CSSSt
                              css::ImportRule* aOwnerRuleToUse,
                              nsIDocument* aDocumentToUse,
                              nsINode* aOwningNodeToUse)
   : StyleSheet(aCopy, aDocumentToUse, aOwningNodeToUse),
     mOwnerRule(aOwnerRuleToUse),
     mDirty(aCopy.mDirty),
     mInRuleProcessorCache(false),
     mScopeElement(nullptr),
-    mInner(aCopy.mInner),
     mRuleProcessors(nullptr)
 {
   mParent = aParentToUse;
 
-  mInner->AddSheet(this);
+  Inner()->AddSheet(this);
 
   if (mDirty) { // CSSOM's been there, force full copy now
     NS_ASSERTION(mInner->mComplete, "Why have rules been accessed on an incomplete sheet?");
     // FIXME: handle failure?
     EnsureUniqueInner();
   }
 }
 
 CSSStyleSheet::~CSSStyleSheet()
 {
   UnparentChildren();
 
   DropRuleCollection();
-  mInner->RemoveSheet(this);
+  Inner()->RemoveSheet(this);
   // XXX The document reference is not reference counted and should
   // not be released. The document will let us know when it is going
   // away.
   if (mRuleProcessors) {
     NS_ASSERTION(mRuleProcessors->Length() == 0, "destructing sheet with rule processor reference");
     delete mRuleProcessors; // weak refs, should be empty here anyway
   }
   if (mInRuleProcessorCache) {
@@ -443,22 +442,22 @@ CSSStyleSheet::DropRuleCollection()
   }
 }
 
 void
 CSSStyleSheet::UnlinkInner()
 {
   // We can only have a cycle through our inner if we have a unique inner,
   // because otherwise there are no JS wrappers for anything in the inner.
-  if (mInner->mSheets.Length() != 1) {
+  if (Inner()->mSheets.Length() != 1) {
     return;
   }
 
-  mInner->mOrderedRules.EnumerateForwards(SetStyleSheetReference, nullptr);
-  mInner->mOrderedRules.Clear();
+  Inner()->mOrderedRules.EnumerateForwards(SetStyleSheetReference, nullptr);
+  Inner()->mOrderedRules.Clear();
 
   // Have to be a bit careful with child sheets, because we want to
   // drop their mNext pointers and null out their mParent and
   // mDocument, but don't want to work with deleted objects.  And we
   // don't want to do any addrefing in the process, just to make sure
   // we don't confuse the cycle collector (though on the face of it,
   // addref/release pairs during unlink should probably be ok).
   RefPtr<StyleSheet> child;
@@ -478,28 +477,28 @@ CSSStyleSheet::UnlinkInner()
   }
 }
 
 void
 CSSStyleSheet::TraverseInner(nsCycleCollectionTraversalCallback &cb)
 {
   // We can only have a cycle through our inner if we have a unique inner,
   // because otherwise there are no JS wrappers for anything in the inner.
-  if (mInner->mSheets.Length() != 1) {
+  if (Inner()->mSheets.Length() != 1) {
     return;
   }
 
   StyleSheet* childSheet = GetFirstChild();
   while (childSheet) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "child sheet");
     cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, childSheet));
     childSheet = childSheet->mNext;
   }
 
-  const nsCOMArray<css::Rule>& rules = mInner->mOrderedRules;
+  const nsCOMArray<css::Rule>& rules = Inner()->mOrderedRules;
   for (int32_t i = 0, count = rules.Count(); i < count; ++i) {
     if (!rules[i]->IsCCLeaf()) {
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mOrderedRules[i]");
       cb.NoteXPCOMChild(rules[i]);
     }
   }
 }
 
@@ -625,58 +624,58 @@ CSSStyleSheet::FindOwningWindowInnerID()
 }
 
 void
 CSSStyleSheet::AppendStyleRule(css::Rule* aRule)
 {
   NS_PRECONDITION(nullptr != aRule, "null arg");
 
   WillDirty();
-  mInner->mOrderedRules.AppendObject(aRule);
+  Inner()->mOrderedRules.AppendObject(aRule);
   aRule->SetStyleSheet(this);
   DidDirty();
 
   if (css::Rule::NAMESPACE_RULE == aRule->GetType()) {
 #ifdef DEBUG
     nsresult rv =
 #endif
       RegisterNamespaceRule(aRule);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                          "RegisterNamespaceRule returned error");
   }
 }
 
 int32_t
 CSSStyleSheet::StyleRuleCount() const
 {
-  return mInner->mOrderedRules.Count();
+  return Inner()->mOrderedRules.Count();
 }
 
 css::Rule*
 CSSStyleSheet::GetStyleRuleAt(int32_t aIndex) const
 {
   // Important: If this function is ever made scriptable, we must add
   // a security check here. See GetCssRules below for an example.
-  return mInner->mOrderedRules.SafeObjectAt(aIndex);
+  return Inner()->mOrderedRules.SafeObjectAt(aIndex);
 }
 
 void
 CSSStyleSheet::EnsureUniqueInner()
 {
   mDirty = true;
 
-  MOZ_ASSERT(mInner->mSheets.Length() != 0,
+  MOZ_ASSERT(Inner()->mSheets.Length() != 0,
              "unexpected number of outers");
-  if (mInner->mSheets.Length() == 1) {
+  if (Inner()->mSheets.Length() == 1) {
     // already unique
     return;
   }
-  CSSStyleSheetInner* clone = mInner->CloneFor(this);
+  CSSStyleSheetInner* clone = Inner()->CloneFor(this);
   MOZ_ASSERT(clone);
-  mInner->RemoveSheet(this);
+  Inner()->RemoveSheet(this);
   mInner = clone;
 
   // otherwise the rule processor has pointers to the old rules
   ClearRuleCascades();
 
   // let our containing style sets know that if we call
   // nsPresContext::EnsureSafeToHandOutCSSRules we will need to restyle the
   // document
@@ -719,17 +718,17 @@ ListRules(const nsCOMArray<css::Rule>& a
 }
 
 void
 CSSStyleSheet::List(FILE* out, int32_t aIndent) const
 {
   StyleSheet::List(out, aIndent);
 
   fprintf_stderr(out, "%s", "Rules in source order:\n");
-  ListRules(mInner->mOrderedRules, out, aIndent);
+  ListRules(Inner()->mOrderedRules, out, aIndent);
 }
 #endif
 
 void 
 CSSStyleSheet::ClearRuleCascades()
 {
   // We might be in ClearRuleCascades because we had a modification
   // to the sheet that resulted in an nsCSSSelector being destroyed.
@@ -775,22 +774,22 @@ CSSStyleSheet::DidDirty()
   MOZ_ASSERT(!mInner->mComplete || mDirty,
              "caller must have called WillDirty()");
   ClearRuleCascades();
 }
 
 nsresult
 CSSStyleSheet::RegisterNamespaceRule(css::Rule* aRule)
 {
-  if (!mInner->mNameSpaceMap) {
-    nsresult rv = mInner->CreateNamespaceMap();
+  if (!Inner()->mNameSpaceMap) {
+    nsresult rv = Inner()->CreateNamespaceMap();
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  AddNamespaceRuleToMap(aRule, mInner->mNameSpaceMap);
+  AddNamespaceRuleToMap(aRule, Inner()->mNameSpaceMap);
   return NS_OK;
 }
 
 css::Rule*
 CSSStyleSheet::GetDOMOwnerRule() const
 {
   return mOwnerRule;
 }
@@ -818,23 +817,23 @@ RuleHasPendingChildSheet(css::Rule *cssR
 uint32_t
 CSSStyleSheet::InsertRuleInternal(const nsAString& aRule,
                                   uint32_t aIndex,
                                   ErrorResult& aRv)
 {
   MOZ_ASSERT(mInner->mComplete);
 
   WillDirty();
-  
-  if (aIndex > uint32_t(mInner->mOrderedRules.Count())) {
+
+  if (aIndex > uint32_t(Inner()->mOrderedRules.Count())) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return 0;
   }
-  
-  NS_ASSERTION(uint32_t(mInner->mOrderedRules.Count()) <= INT32_MAX,
+
+  NS_ASSERTION(uint32_t(Inner()->mOrderedRules.Count()) <= INT32_MAX,
                "Too many style rules!");
 
   // Hold strong ref to the CSSLoader in case the document update
   // kills the document
   RefPtr<css::Loader> loader;
   if (mDocument) {
     loader = mDocument->CSSLoader();
     NS_ASSERTION(loader, "Document with no CSS loader!");
@@ -850,17 +849,17 @@ CSSStyleSheet::InsertRuleInternal(const 
   if (NS_WARN_IF(aRv.Failed())) {
     return 0;
   }
 
   // Hierarchy checking.
   int32_t newType = rule->GetType();
 
   // check that we're not inserting before a charset rule
-  css::Rule* nextRule = mInner->mOrderedRules.SafeObjectAt(aIndex);
+  css::Rule* nextRule = Inner()->mOrderedRules.SafeObjectAt(aIndex);
   if (nextRule) {
     int32_t nextType = nextRule->GetType();
     if (nextType == css::Rule::CHARSET_RULE) {
       aRv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
       return 0;
     }
 
     if (nextType == css::Rule::IMPORT_RULE &&
@@ -881,17 +880,17 @@ CSSStyleSheet::InsertRuleInternal(const 
 
   if (aIndex != 0) {
     // no inserting charset at nonzero position
     if (newType == css::Rule::CHARSET_RULE) {
       aRv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
       return 0;
     }
 
-    css::Rule* prevRule = mInner->mOrderedRules.SafeObjectAt(aIndex - 1);
+    css::Rule* prevRule = Inner()->mOrderedRules.SafeObjectAt(aIndex - 1);
     int32_t prevType = prevRule->GetType();
 
     if (newType == css::Rule::IMPORT_RULE &&
         prevType != css::Rule::CHARSET_RULE &&
         prevType != css::Rule::IMPORT_RULE) {
       aRv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
       return 0;
     }
@@ -900,17 +899,17 @@ CSSStyleSheet::InsertRuleInternal(const 
         prevType != css::Rule::CHARSET_RULE &&
         prevType != css::Rule::IMPORT_RULE &&
         prevType != css::Rule::NAMESPACE_RULE) {
       aRv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
       return 0;
     }
   }
 
-  if (!mInner->mOrderedRules.InsertObjectAt(rule, aIndex)) {
+  if (!Inner()->mOrderedRules.InsertObjectAt(rule, aIndex)) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return 0;
   }
 
   DidDirty();
 
   rule->SetStyleSheet(this);
 
@@ -935,31 +934,31 @@ CSSStyleSheet::InsertRuleInternal(const 
   return aIndex;
 }
 
 void
 CSSStyleSheet::DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv)
 {
   // XXX TBI: handle @rule types
   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
-    
+
   WillDirty();
 
-  if (aIndex >= uint32_t(mInner->mOrderedRules.Count())) {
+  if (aIndex >= uint32_t(Inner()->mOrderedRules.Count())) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
-  NS_ASSERTION(uint32_t(mInner->mOrderedRules.Count()) <= INT32_MAX,
+  NS_ASSERTION(uint32_t(Inner()->mOrderedRules.Count()) <= INT32_MAX,
                "Too many style rules!");
 
   // Hold a strong ref to the rule so it doesn't die when we RemoveObjectAt
-  RefPtr<css::Rule> rule = mInner->mOrderedRules.ObjectAt(aIndex);
+  RefPtr<css::Rule> rule = Inner()->mOrderedRules.ObjectAt(aIndex);
   if (rule) {
-    mInner->mOrderedRules.RemoveObjectAt(aIndex);
+    Inner()->mOrderedRules.RemoveObjectAt(aIndex);
     rule->SetStyleSheet(nullptr);
     DidDirty();
 
     if (mDocument) {
       mDocument->StyleRuleRemoved(this, rule);
     }
   }
 }
@@ -1109,19 +1108,19 @@ CSSStyleSheet::ReparseSheet(const nsAStr
 
   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
 
   WillDirty();
 
   // detach existing rules (including child sheets via import rules)
   css::LoaderReusableStyleSheets reusableSheets;
   int ruleCount;
-  while ((ruleCount = mInner->mOrderedRules.Count()) != 0) {
-    RefPtr<css::Rule> rule = mInner->mOrderedRules.ObjectAt(ruleCount - 1);
-    mInner->mOrderedRules.RemoveObjectAt(ruleCount - 1);
+  while ((ruleCount = Inner()->mOrderedRules.Count()) != 0) {
+    RefPtr<css::Rule> rule = Inner()->mOrderedRules.ObjectAt(ruleCount - 1);
+    Inner()->mOrderedRules.RemoveObjectAt(ruleCount - 1);
     rule->SetStyleSheet(nullptr);
     if (rule->GetType() == css::Rule::IMPORT_RULE) {
       nsCOMPtr<nsIDOMCSSImportRule> importRule(do_QueryInterface(rule));
       NS_ASSERTION(importRule, "GetType lied");
 
       nsCOMPtr<nsIDOMCSSStyleSheet> childSheet;
       importRule->GetStyleSheet(getter_AddRefs(childSheet));
 
@@ -1140,17 +1139,17 @@ CSSStyleSheet::ReparseSheet(const nsAStr
     NS_ASSERTION(child->mParent == this, "Child sheet is not parented to this!");
     StyleSheet* next = child->mNext;
     child->mParent = nullptr;
     child->mDocument = nullptr;
     child->mNext = nullptr;
     child = next;
   }
   SheetInfo().mFirstChild = nullptr;
-  mInner->mNameSpaceMap = nullptr;
+  Inner()->mNameSpaceMap = nullptr;
 
   uint32_t lineNumber = 1;
   if (mOwningNode) {
     nsCOMPtr<nsIStyleSheetLinkingElement> link = do_QueryInterface(mOwningNode);
     if (link) {
       lineNumber = link->GetLineNumber();
     }
   }
@@ -1158,18 +1157,18 @@ CSSStyleSheet::ReparseSheet(const nsAStr
   nsCSSParser parser(loader, this);
   nsresult rv = parser.ParseSheet(aInput, mInner->mSheetURI, mInner->mBaseURI,
                                   mInner->mPrincipal, lineNumber, &reusableSheets);
   DidDirty(); // we are always 'dirty' here since we always remove rules first
   NS_ENSURE_SUCCESS(rv, rv);
 
   // notify document of all new rules
   if (mDocument) {
-    for (int32_t index = 0; index < mInner->mOrderedRules.Count(); ++index) {
-      RefPtr<css::Rule> rule = mInner->mOrderedRules.ObjectAt(index);
+    for (int32_t index = 0; index < Inner()->mOrderedRules.Count(); ++index) {
+      RefPtr<css::Rule> rule = Inner()->mOrderedRules.ObjectAt(index);
       if (rule->GetType() == css::Rule::IMPORT_RULE &&
           RuleHasPendingChildSheet(rule)) {
         continue; // notify when loaded (see StyleSheetLoaded)
       }
       mDocument->StyleRuleAdded(this, rule);
     }
   }
   return NS_OK;
--- a/layout/style/CSSStyleSheet.h
+++ b/layout/style/CSSStyleSheet.h
@@ -123,17 +123,19 @@ public:
   nsresult DeleteRuleFromGroup(css::GroupRule* aGroup, uint32_t aIndex);
   nsresult InsertRuleIntoGroup(const nsAString& aRule, css::GroupRule* aGroup, uint32_t aIndex, uint32_t* _retval);
 
   void SetOwnerRule(css::ImportRule* aOwnerRule) { mOwnerRule = aOwnerRule; /* Not ref counted */ }
   css::ImportRule* GetOwnerRule() const { return mOwnerRule; }
   // Workaround overloaded-virtual warning in GCC.
   using StyleSheet::GetOwnerRule;
 
-  nsXMLNameSpaceMap* GetNameSpaceMap() const { return mInner->mNameSpaceMap; }
+  nsXMLNameSpaceMap* GetNameSpaceMap() const {
+    return Inner()->mNameSpaceMap;
+  }
 
   already_AddRefed<CSSStyleSheet> Clone(CSSStyleSheet* aCloneParent,
                                         css::ImportRule* aCloneOwnerRule,
                                         nsIDocument* aCloneDocument,
                                         nsINode* aCloneOwningNode) const;
 
   bool IsModified() const final { return mDirty; }
 
@@ -202,16 +204,21 @@ protected:
   void ClearRuleCascades();
 
   // Add the namespace mapping from this @namespace rule to our namespace map
   nsresult RegisterNamespaceRule(css::Rule* aRule);
 
   // Drop our reference to mRuleCollection
   void DropRuleCollection();
 
+  CSSStyleSheetInner* Inner() const
+  {
+    return static_cast<CSSStyleSheetInner*>(mInner);
+  }
+
   // Unlink our inner, if needed, for cycle collection
   void UnlinkInner();
   // Traverse our inner, if needed, for cycle collection
   void TraverseInner(nsCycleCollectionTraversalCallback &);
 
 protected:
   // Internal methods which do not have security check and completeness check.
   dom::CSSRuleList* GetCssRulesInternal(ErrorResult& aRv);
@@ -223,18 +230,16 @@ protected:
 
   css::ImportRule*      mOwnerRule; // weak ref
 
   RefPtr<CSSRuleListImpl> mRuleCollection;
   bool                  mDirty; // has been modified 
   bool                  mInRuleProcessorCache;
   RefPtr<dom::Element> mScopeElement;
 
-  CSSStyleSheetInner*   mInner;
-
   AutoTArray<nsCSSRuleProcessor*, 8>* mRuleProcessors;
   nsTArray<nsStyleSet*> mStyleSets;
 
   friend class mozilla::StyleSheet;
   friend class ::nsCSSRuleProcessor;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(CSSStyleSheet, NS_CSS_STYLE_SHEET_IMPL_CID)
--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -21,32 +21,34 @@ namespace mozilla {
 StyleSheet::StyleSheet(StyleBackendType aType, css::SheetParsingMode aParsingMode)
   : mParent(nullptr)
   , mDocument(nullptr)
   , mOwningNode(nullptr)
   , mParsingMode(aParsingMode)
   , mType(aType)
   , mDisabled(false)
   , mDocumentAssociationMode(NotOwnedByDocument)
+  , mInner(nullptr)
 {
 }
 
 StyleSheet::StyleSheet(const StyleSheet& aCopy,
                        nsIDocument* aDocumentToUse,
                        nsINode* aOwningNodeToUse)
   : mParent(nullptr)
   , mTitle(aCopy.mTitle)
   , mDocument(aDocumentToUse)
   , mOwningNode(aOwningNodeToUse)
   , mParsingMode(aCopy.mParsingMode)
   , mType(aCopy.mType)
   , mDisabled(aCopy.mDisabled)
     // We only use this constructor during cloning.  It's the cloner's
     // responsibility to notify us if we end up being owned by a document.
   , mDocumentAssociationMode(NotOwnedByDocument)
+  , mInner(aCopy.mInner) // Shallow copy, but concrete subclasses will fix up.
 {
   if (aCopy.mMedia) {
     // XXX This is wrong; we should be keeping @import rules and
     // sheets in sync!
     mMedia = aCopy.mMedia->Clone();
   }
 }
 
--- a/layout/style/StyleSheet.h
+++ b/layout/style/StyleSheet.h
@@ -253,16 +253,20 @@ protected:
   const StyleBackendType mType;
   bool                  mDisabled;
 
   // mDocumentAssociationMode determines whether mDocument directly owns us (in
   // the sense that if it's known-live then we're known-live).  Always
   // NotOwnedByDocument when mDocument is null.
   DocumentAssociationMode mDocumentAssociationMode;
 
+  // Core information we get from parsed sheets, which are shared amongst
+  // StyleSheet clones.
+  StyleSheetInfo* mInner;
+
   friend class ::nsCSSRuleProcessor;
   friend struct mozilla::ChildSheetListBuilder;
 
   // Make CSSStyleSheet and ServoStyleSheet friends so they can access
   // protected members of other StyleSheet objects (useful for iterating
   // through children).
   friend class mozilla::CSSStyleSheet;
   friend class mozilla::ServoStyleSheet;
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -3668,17 +3668,17 @@ nsCSSRuleProcessor::CascadeSheet(CSSStyl
 
     StyleSheet* child = aSheet->GetFirstChild();
     while (child) {
       CascadeSheet(child->AsGecko(), aData);
 
       child = child->mNext;
     }
 
-    if (!aSheet->mInner->mOrderedRules.EnumerateForwards(CascadeRuleEnumFunc,
+    if (!aSheet->Inner()->mOrderedRules.EnumerateForwards(CascadeRuleEnumFunc,
                                                          aData))
       return false;
   }
   return true;
 }
 
 static int CompareWeightData(const void* aArg1, const void* aArg2,
                              void* closure)