Bug 1339629 Part 4: Uplift CloneFor into StyleSheetInfo, and EnsureUniqueInner into StyleSheet. r=heycam
authorBrad Werth <bwerth@mozilla.com>
Mon, 15 May 2017 16:19:17 -0700
changeset 408700 7a72e493e820f2db317e0e42879dff149dfcd770
parent 408699 a16551697e09403101ab4252fddd635aae0b47df
child 408701 e0abb8753179806b16babbb958120f011580eb63
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1339629
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1339629 Part 4: Uplift CloneFor into StyleSheetInfo, and EnsureUniqueInner into StyleSheet. r=heycam MozReview-Commit-ID: 4aZJYAsmZ2h
layout/style/CSSStyleSheet.cpp
layout/style/CSSStyleSheet.h
layout/style/ServoBindingList.h
layout/style/ServoStyleSheet.cpp
layout/style/ServoStyleSheet.h
layout/style/StyleSheet.cpp
layout/style/StyleSheet.h
layout/style/StyleSheetInfo.h
layout/style/StyleSheetInlines.h
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -227,20 +227,21 @@ CSSStyleSheetInner::CSSStyleSheetInner(C
 CSSStyleSheetInner::~CSSStyleSheetInner()
 {
   MOZ_COUNT_DTOR(CSSStyleSheetInner);
   for (css::Rule* rule : mOrderedRules) {
     rule->SetStyleSheet(nullptr);
   }
 }
 
-CSSStyleSheetInner*
-CSSStyleSheetInner::CloneFor(CSSStyleSheet* aPrimarySheet)
+StyleSheetInfo*
+CSSStyleSheetInner::CloneFor(StyleSheet* aPrimarySheet)
 {
-  return new CSSStyleSheetInner(*this, aPrimarySheet);
+  return new CSSStyleSheetInner(*this,
+                                static_cast<CSSStyleSheet*>(aPrimarySheet));
 }
 
 void
 CSSStyleSheetInner::RemoveSheet(StyleSheet* aSheet)
 {
   if (aSheet == mSheets.ElementAt(0) && mSheets.Length() > 1) {
     StyleSheet* sheet = mSheets[1];
     for (css::Rule* rule : mOrderedRules) {
@@ -358,26 +359,17 @@ CSSStyleSheet::CSSStyleSheet(const CSSSt
                              nsIDocument* aDocumentToUse,
                              nsINode* aOwningNodeToUse)
   : StyleSheet(aCopy, aDocumentToUse, aOwningNodeToUse),
     mOwnerRule(aOwnerRuleToUse),
     mInRuleProcessorCache(false),
     mScopeElement(nullptr),
     mRuleProcessors(nullptr)
 {
-  MOZ_ASSERT(mInner, "We should have an mInner after copy.");
-  MOZ_ASSERT(mInner->mSheets.Contains(this), "Our mInner should include us.");
-
   mParent = aParentToUse;
-
-  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();
   // XXX The document reference is not reference counted and should
@@ -590,28 +582,17 @@ CSSStyleSheet::GetStyleRuleAt(int32_t aI
   // Important: If this function is ever made scriptable, we must add
   // a security check here. See GetCssRules below for an example.
   return Inner()->mOrderedRules.SafeObjectAt(aIndex);
 }
 
 void
 CSSStyleSheet::EnsureUniqueInner()
 {
-  mDirty = true;
-
-  MOZ_ASSERT(mInner->mSheets.Length() != 0,
-             "unexpected number of outers");
-  if (mInner->mSheets.Length() == 1) {
-    // already unique
-    return;
-  }
-  CSSStyleSheetInner* clone = Inner()->CloneFor(this);
-  MOZ_ASSERT(clone);
-  mInner->RemoveSheet(this);
-  mInner = clone;
+  StyleSheet::EnsureUniqueInner();
 
   // 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
   for (nsStyleSet* styleSet : mStyleSets) {
@@ -691,24 +672,16 @@ CSSStyleSheet::ClearRuleCascades()
   }
   if (mParent) {
     CSSStyleSheet* parent = (CSSStyleSheet*)mParent;
     parent->ClearRuleCascades();
   }
 }
 
 void
-CSSStyleSheet::WillDirty()
-{
-  if (mInner->mComplete) {
-    EnsureUniqueInner();
-  }
-}
-
-void
 CSSStyleSheet::DidDirty()
 {
   MOZ_ASSERT(!mInner->mComplete || mDirty,
              "caller must have called WillDirty()");
   ClearRuleCascades();
 }
 
 nsresult
--- a/layout/style/CSSStyleSheet.h
+++ b/layout/style/CSSStyleSheet.h
@@ -54,17 +54,17 @@ struct CSSStyleSheetInner : public Style
 {
   CSSStyleSheetInner(CORSMode aCORSMode,
                      ReferrerPolicy aReferrerPolicy,
                      const dom::SRIMetadata& aIntegrity);
   CSSStyleSheetInner(CSSStyleSheetInner& aCopy,
                      CSSStyleSheet* aPrimarySheet);
   ~CSSStyleSheetInner();
 
-  CSSStyleSheetInner* CloneFor(CSSStyleSheet* aPrimarySheet);
+  StyleSheetInfo* CloneFor(StyleSheet* aPrimarySheet) override;
   void RemoveSheet(StyleSheet* aSheet) override;
 
   void RebuildNameSpaces();
 
   // Create a new namespace map
   nsresult CreateNamespaceMap();
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
@@ -139,17 +139,17 @@ public:
 
   void AddStyleSet(nsStyleSet* aStyleSet);
   void DropStyleSet(nsStyleSet* aStyleSet);
 
   // nsICSSLoaderObserver interface
   NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasAlternate,
                               nsresult aStatus) override;
 
-  void EnsureUniqueInner();
+  void EnsureUniqueInner() override;
 
   // Append all of this sheet's child sheets to aArray.
   void AppendAllChildSheets(nsTArray<CSSStyleSheet*>& aArray);
 
   bool UseForPresentation(nsPresContext* aPresContext,
                             nsMediaQueryResultCacheKey& aKey) const;
 
   nsresult ReparseSheet(const nsAString& aInput);
@@ -167,18 +167,17 @@ public:
   void SetScopeElement(dom::Element* aScopeElement);
 
   // WebIDL CSSStyleSheet API
   // Can't be inline because we can't include ImportRule here.  And can't be
   // called GetOwnerRule because that would be ambiguous with the ImportRule
   // version.
   css::Rule* GetDOMOwnerRule() const final;
 
-  void WillDirty();
-  void DidDirty();
+  void DidDirty() override;
 
 private:
   CSSStyleSheet(const CSSStyleSheet& aCopy,
                 CSSStyleSheet* aParentToUse,
                 css::ImportRule* aOwnerRuleToUse,
                 nsIDocument* aDocumentToUse,
                 nsINode* aOwningNodeToUse);
 
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -43,16 +43,18 @@ SERVO_BINDING_FUNC(Servo_StyleSheet_Clea
                    mozilla::ServoStyleSheet* gecko_stylesheet,
                    const nsACString* data,
                    RawGeckoURLExtraData* extra_data,
                    uint32_t line_number_offset)
 SERVO_BINDING_FUNC(Servo_StyleSheet_HasRules, bool,
                    RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSheet_GetRules, ServoCssRulesStrong,
                    RawServoStyleSheetBorrowed sheet)
+SERVO_BINDING_FUNC(Servo_StyleSheet_Clone, RawServoStyleSheetStrong,
+                   RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_Init, RawServoStyleSetOwned, RawGeckoPresContextOwned pres_context)
 SERVO_BINDING_FUNC(Servo_StyleSet_Clear, void,
                    RawServoStyleSetBorrowed set)
 SERVO_BINDING_FUNC(Servo_StyleSet_RebuildData, void,
                    RawServoStyleSetBorrowed set)
 SERVO_BINDING_FUNC(Servo_StyleSet_Drop, void, RawServoStyleSetOwned set)
 SERVO_BINDING_FUNC(Servo_StyleSet_AppendStyleSheet, void,
                    RawServoStyleSetBorrowed set,
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -25,16 +25,41 @@ namespace mozilla {
 // CSS Style Sheet Inner Data Container
 //
 
 ServoStyleSheetInner::ServoStyleSheetInner(CORSMode aCORSMode,
                                            ReferrerPolicy aReferrerPolicy,
                                            const SRIMetadata& aIntegrity)
   : StyleSheetInfo(aCORSMode, aReferrerPolicy, aIntegrity)
 {
+  MOZ_COUNT_CTOR(ServoStyleSheetInner);
+}
+
+ServoStyleSheetInner::ServoStyleSheetInner(ServoStyleSheetInner& aCopy,
+                                           ServoStyleSheet* aPrimarySheet)
+  : StyleSheetInfo(aCopy, aPrimarySheet)
+{
+  MOZ_COUNT_CTOR(ServoStyleSheetInner);
+
+  // Actually clone aCopy's mSheet and use that as our mSheet.
+  mSheet = Servo_StyleSheet_Clone(aCopy.mSheet).Consume();
+
+  mURLData = aCopy.mURLData;
+}
+
+ServoStyleSheetInner::~ServoStyleSheetInner()
+{
+  MOZ_COUNT_DTOR(ServoStyleSheetInner);
+}
+
+StyleSheetInfo*
+ServoStyleSheetInner::CloneFor(StyleSheet* aPrimarySheet)
+{
+  return new ServoStyleSheetInner(*this,
+                                  static_cast<ServoStyleSheet*>(aPrimarySheet));
 }
 
 size_t
 ServoStyleSheetInner::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
 
   // XXX: need to measure mSheet
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -28,16 +28,21 @@ class Loader;
 // Servo Style Sheet Inner Data Container
 //
 
 struct ServoStyleSheetInner : public StyleSheetInfo
 {
   ServoStyleSheetInner(CORSMode aCORSMode,
                        ReferrerPolicy aReferrerPolicy,
                        const dom::SRIMetadata& aIntegrity);
+  ServoStyleSheetInner(ServoStyleSheetInner& aCopy,
+                       ServoStyleSheet* aPrimarySheet);
+  ~ServoStyleSheetInner();
+
+  StyleSheetInfo* CloneFor(StyleSheet* aPrimarySheet) override;
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
 
   RefPtr<const RawServoStyleSheet> mSheet;
   // XXX StyleSheetInfo already has mSheetURI, mBaseURI, and mPrincipal.
   // Can we somehow replace them with URLExtraData directly? The issue
   // is currently URLExtraData is immutable, but URIs in StyleSheetInfo
   // seems to be mutable, so we probably cannot set them altogether.
@@ -89,18 +94,17 @@ public:
   URLExtraData* URLData() const { return Inner()->mURLData; }
 
   // WebIDL CSSStyleSheet API
   // Can't be inline because we can't include ImportRule here.  And can't be
   // called GetOwnerRule because that would be ambiguous with the ImportRule
   // version.
   css::Rule* GetDOMOwnerRule() const final;
 
-  void WillDirty() {}
-  void DidDirty() {}
+  void DidDirty() override {}
 
   virtual already_AddRefed<StyleSheet> Clone(StyleSheet* aCloneParent,
     css::ImportRule* aCloneOwnerRule,
     nsIDocument* aCloneDocument,
     nsINode* aCloneOwningNode) const final;
 
   // nsICSSLoaderObserver interface
   NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasAlternate,
--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -45,16 +45,22 @@ StyleSheet::StyleSheet(const StyleSheet&
     // 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.
   , mDirty(aCopy.mDirty)
 {
   MOZ_ASSERT(mInner, "Should only copy StyleSheets with an mInner.");
   mInner->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();
+  }
+
   if (aCopy.mMedia) {
     // XXX This is wrong; we should be keeping @import rules and
     // sheets in sync!
     mMedia = aCopy.mMedia->Clone();
   }
 }
 
 StyleSheet::~StyleSheet()
@@ -236,16 +242,20 @@ StyleSheetInfo::StyleSheetInfo(StyleShee
                    // without children.
 #ifdef DEBUG
   , mPrincipalSet(aCopy.mPrincipalSet)
 #endif
 {
   AddSheet(aPrimarySheet);
 }
 
+StyleSheetInfo::~StyleSheetInfo()
+{
+}
+
 void
 StyleSheetInfo::AddSheet(StyleSheet* aSheet)
 {
   mSheets.AppendElement(aSheet);
 }
 
 void
 StyleSheetInfo::RemoveSheet(StyleSheet* aSheet)
@@ -383,16 +393,42 @@ StyleSheet::InsertRule(const nsAString& 
 NS_IMETHODIMP
 StyleSheet::DeleteRule(uint32_t aIndex)
 {
   ErrorResult rv;
   DeleteRule(aIndex, *nsContentUtils::SubjectPrincipal(), rv);
   return rv.StealNSResult();
 }
 
+void
+StyleSheet::WillDirty()
+{
+  if (mInner->mComplete) {
+    EnsureUniqueInner();
+  }
+}
+
+void
+StyleSheet::EnsureUniqueInner()
+{
+  MOZ_ASSERT(mInner->mSheets.Length() != 0,
+             "unexpected number of outers");
+  mDirty = true;
+
+  if (mInner->mSheets.Length() == 1) {
+    // already unique
+    return;
+  }
+
+  StyleSheetInfo* clone = mInner->CloneFor(this);
+  MOZ_ASSERT(clone);
+  mInner->RemoveSheet(this);
+  mInner = clone;
+}
+
 // WebIDL CSSStyleSheet API
 
 #define FORWARD_INTERNAL(method_, args_) \
   if (IsServo()) { \
     return AsServo()->method_ args_; \
   } \
   return AsGecko()->method_ args_;
 
--- a/layout/style/StyleSheet.h
+++ b/layout/style/StyleSheet.h
@@ -115,16 +115,18 @@ public:
 
   virtual already_AddRefed<StyleSheet> Clone(StyleSheet* aCloneParent,
                                              css::ImportRule* aCloneOwnerRule,
                                              nsIDocument* aCloneDocument,
                                              nsINode* aCloneOwningNode) const = 0;
 
   bool IsModified() const { return mDirty; }
 
+  virtual void EnsureUniqueInner();
+
   // style sheet owner info
   enum DocumentAssociationMode {
     // OwnedByDocument means mDocument owns us (possibly via a chain of other
     // stylesheets).
     OwnedByDocument,
     // NotOwnedByDocument means we're owned by something that might have a
     // different lifetime than mDocument.
     NotOwnedByDocument
@@ -208,18 +210,18 @@ public:
   NS_IMETHOD GetCssRules(nsIDOMCSSRuleList** aCssRules) final;
   NS_IMETHOD InsertRule(const nsAString& aRule, uint32_t aIndex,
                       uint32_t* aReturn) final;
   NS_IMETHOD DeleteRule(uint32_t aIndex) final;
 
   // Changes to sheets should be inside of a WillDirty-DidDirty pair.
   // However, the calls do not need to be matched; it's ok to call
   // WillDirty and then make no change and skip the DidDirty call.
-  inline void WillDirty();
-  inline void DidDirty();
+  void WillDirty();
+  virtual void DidDirty() {}
 
   nsresult DeleteRuleFromGroup(css::GroupRule* aGroup, uint32_t aIndex);
   nsresult InsertRuleIntoGroup(const nsAString& aRule,
                                css::GroupRule* aGroup, uint32_t aIndex);
 
 private:
   // Get a handle to the various stylesheet bits which live on the 'inner' for
   // gecko stylesheets and live on the StyleSheet for Servo stylesheets.
--- a/layout/style/StyleSheetInfo.h
+++ b/layout/style/StyleSheetInfo.h
@@ -30,17 +30,19 @@ struct StyleSheetInfo
 
   StyleSheetInfo(CORSMode aCORSMode,
                  ReferrerPolicy aReferrerPolicy,
                  const dom::SRIMetadata& aIntegrity);
 
   StyleSheetInfo(StyleSheetInfo& aCopy,
                  StyleSheet* aPrimarySheet);
 
-  virtual ~StyleSheetInfo() {}
+  virtual ~StyleSheetInfo();
+
+  virtual StyleSheetInfo* CloneFor(StyleSheet* aPrimarySheet) = 0;
 
   virtual void AddSheet(StyleSheet* aSheet);
   virtual void RemoveSheet(StyleSheet* aSheet);
 
   nsCOMPtr<nsIURI>       mSheetURI; // for error reports, etc.
   nsCOMPtr<nsIURI>       mOriginalSheetURI;  // for GetHref.  Can be null.
   nsCOMPtr<nsIURI>       mBaseURI; // for resolving relative URIs
   nsCOMPtr<nsIPrincipal> mPrincipal;
--- a/layout/style/StyleSheetInlines.h
+++ b/layout/style/StyleSheetInlines.h
@@ -124,15 +124,11 @@ StyleSheet::GetReferrerPolicy() const
 }
 
 void
 StyleSheet::GetIntegrity(dom::SRIMetadata& aResult) const
 {
   aResult = SheetInfo().mIntegrity;
 }
 
-void StyleSheet::WillDirty() { MOZ_STYLO_FORWARD(WillDirty, ()) }
-void StyleSheet::DidDirty() { MOZ_STYLO_FORWARD(DidDirty, ()) }
-
-
 }
 
 #endif // mozilla_StyleSheetInlines_h