Bug 1415940 Part 1: Expand StyleSheet dirty flag into a bitfield, to allow more types of dirtiness. r=bz
authorBrad Werth <bwerth@mozilla.com>
Wed, 03 Jan 2018 14:25:56 -0800
changeset 454368 307642e5b5f4d2205ee2237bde0f8c79f18bc817
parent 454367 3a19f7ca7ad8fcbdd1a9457c924ed571943077f8
child 454369 f76d80e4c6fb7d5c6a0efb90ea5bf6abf0693065
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1415940
milestone59.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 1415940 Part 1: Expand StyleSheet dirty flag into a bitfield, to allow more types of dirtiness. r=bz MozReview-Commit-ID: 7IasNqj85il
dom/base/nsTreeSanitizer.cpp
layout/style/CSSStyleSheet.cpp
layout/style/Loader.cpp
layout/style/ServoStyleSheet.cpp
layout/style/StyleSheet.cpp
layout/style/StyleSheet.h
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -1107,18 +1107,18 @@ nsTreeSanitizer::SanitizeStyleSheet(cons
   } else {
     // Create the CSS parser, and parse the CSS text.
     nsCSSParser parser(nullptr, sheet->AsGecko());
     rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
                            aDocument->NodePrincipal(), 0);
   }
   NS_ENSURE_SUCCESS(rv, true);
   // Mark the sheet as complete.
-  MOZ_ASSERT(!sheet->IsModified(),
-             "should not get marked modified during parsing");
+  MOZ_ASSERT(!sheet->HasForcedUniqueInner(),
+             "should not get a forced unique inner during parsing");
   sheet->SetComplete();
   // Loop through all the rules found in the CSS text
   ErrorResult err;
   RefPtr<dom::CSSRuleList> rules =
     sheet->GetCssRules(*nsContentUtils::GetSystemPrincipal(), err);
   err.SuppressException();
   if (!rules) {
     return true;
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -348,17 +348,17 @@ CSSStyleSheet::CSSStyleSheet(const CSSSt
                aParentToUse,
                aOwnerRuleToUse,
                aDocumentToUse,
                aOwningNodeToUse)
   , mInRuleProcessorCache(false)
   , mScopeElement(nullptr)
   , mRuleProcessors(nullptr)
 {
-  if (mDirty) { // CSSOM's been there, force full copy now
+  if (HasForcedUniqueInner()) { // CSSOM's been there, force full copy now
     NS_ASSERTION(mInner->mComplete,
                  "Why have rules been accessed on an incomplete sheet?");
     // FIXME: handle failure?
     //
     // NOTE: It's important to call this from the subclass, since it could
     // access uninitialized members otherwise.
     EnsureUniqueInner();
   }
@@ -605,17 +605,17 @@ CSSStyleSheet::ClearRuleCascades()
   if (mParent) {
     static_cast<CSSStyleSheet*>(mParent)->ClearRuleCascades();
   }
 }
 
 void
 CSSStyleSheet::DidDirty()
 {
-  MOZ_ASSERT(!mInner->mComplete || mDirty,
+  MOZ_ASSERT(!mInner->mComplete || HasForcedUniqueInner(),
              "caller must have called WillDirty()");
   ClearRuleCascades();
 }
 
 nsresult
 CSSStyleSheet::RegisterNamespaceRule(css::Rule* aRule)
 {
   if (!Inner()->mNameSpaceMap) {
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -998,19 +998,22 @@ Loader::CreateSheet(nsIURI* aURI,
     }
 
     if (sheet) {
       // This sheet came from the XUL cache or our per-document hashtable; it
       // better be a complete sheet.
       NS_ASSERTION(sheet->IsComplete(),
                    "Sheet thinks it's not complete while we think it is");
 
-      // Make sure it hasn't been modified; if it has, we can't use it
-      if (sheet->IsModified()) {
-        LOG(("  Not cloning completed sheet %p because it's been modified",
+      // Make sure it hasn't been forced to have a unique inner;
+      // that is an indication that its rules have been exposed to
+      // CSSOM and so we can't use it.
+      if (sheet->HasForcedUniqueInner()) {
+        LOG(("  Not cloning completed sheet %p because it has a "
+             "forced unique inner",
              sheet.get()));
         sheet = nullptr;
         fromCompleteSheets = false;
       }
     }
 
     // Then loading sheets
     if (!sheet && !aSyncLoad) {
@@ -1051,20 +1054,21 @@ Loader::CreateSheet(nsIURI* aURI,
                                             &debugEqual)) && debugEqual),
                        "Principals should be the same");
 #endif
         }
       }
     }
 
     if (sheet) {
-      // The sheet we have now should be either incomplete or unmodified
-      NS_ASSERTION(!sheet->IsModified() ||
+      // The sheet we have now should be either incomplete or without
+      // a forced unique inner.
+      NS_ASSERTION(!sheet->HasForcedUniqueInner() ||
                    !sheet->IsComplete(),
-                   "Unexpected modified complete sheet");
+                   "Unexpected complete sheet with forced unique inner");
       NS_ASSERTION(sheet->IsComplete() ||
                    aSheetState != eSheetComplete,
                    "Sheet thinks it's not complete while we think it is");
 
       RefPtr<StyleSheet> clonedSheet =
         sheet->Clone(nullptr, nullptr, nullptr, nullptr);
       *aSheet = Move(clonedSheet);
       if (*aSheet && fromCompleteSheets &&
@@ -1807,18 +1811,18 @@ Loader::DoSheetComplete(SheetLoadData* a
 
   // Go through and deal with the whole linked list.
   SheetLoadData* data = aLoadData;
   while (data) {
     if (!data->mSheetAlreadyComplete) {
       // If mSheetAlreadyComplete, then the sheet could well be modified between
       // when we posted the async call to SheetComplete and now, since the sheet
       // was page-accessible during that whole time.
-      MOZ_ASSERT(!data->mSheet->IsModified(),
-                 "should not get marked modified during parsing");
+      MOZ_ASSERT(!data->mSheet->HasForcedUniqueInner(),
+                 "should not get a forced unique inner during parsing");
       data->mSheet->SetComplete();
       data->ScheduleLoadEventIfNeeded(aStatus);
     }
     if (data->mMustNotify && (data->mObserver || !mObservers.IsEmpty())) {
       // Don't notify here so we don't trigger script.  Remember the
       // info we need to notify, then do it later when it's safe.
       aDatasToNotify.AppendElement(data);
 
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -144,17 +144,17 @@ ServoStyleSheet::ServoStyleSheet(const S
                                  nsIDocument* aDocumentToUse,
                                  nsINode* aOwningNodeToUse)
   : StyleSheet(aCopy,
                aParentToUse,
                aOwnerRuleToUse,
                aDocumentToUse,
                aOwningNodeToUse)
 {
-  if (mDirty) { // CSSOM's been there, force full copy now
+  if (HasForcedUniqueInner()) { // CSSOM's been there, force full copy now
     NS_ASSERTION(mInner->mComplete,
                  "Why have rules been accessed on an incomplete sheet?");
     // FIXME: handle failure?
     //
     // NOTE: It's important to call this from the subclass, since this could
     // access uninitialized members otherwise.
     EnsureUniqueInner();
   }
--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -23,17 +23,17 @@ namespace mozilla {
 StyleSheet::StyleSheet(StyleBackendType aType, css::SheetParsingMode aParsingMode)
   : mParent(nullptr)
   , mDocument(nullptr)
   , mOwningNode(nullptr)
   , mOwnerRule(nullptr)
   , mParsingMode(aParsingMode)
   , mType(aType)
   , mDisabled(false)
-  , mDirty(false)
+  , mDirtyFlags(0)
   , mDocumentAssociationMode(NotOwnedByDocument)
   , mInner(nullptr)
 {
 }
 
 StyleSheet::StyleSheet(const StyleSheet& aCopy,
                        StyleSheet* aParentToUse,
                        dom::CSSImportRule* aOwnerRuleToUse,
@@ -42,17 +42,17 @@ StyleSheet::StyleSheet(const StyleSheet&
   : mParent(aParentToUse)
   , mTitle(aCopy.mTitle)
   , mDocument(aDocumentToUse)
   , mOwningNode(aOwningNodeToUse)
   , mOwnerRule(aOwnerRuleToUse)
   , mParsingMode(aCopy.mParsingMode)
   , mType(aCopy.mType)
   , mDisabled(aCopy.mDisabled)
-  , mDirty(aCopy.mDirty)
+  , mDirtyFlags(aCopy.mDirtyFlags)
   // 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.
 {
   MOZ_ASSERT(mInner, "Should only copy StyleSheets with an mInner.");
   mInner->AddSheet(this);
 
@@ -191,17 +191,19 @@ bool
 StyleSheet::IsComplete() const
 {
   return SheetInfo().mComplete;
 }
 
 void
 StyleSheet::SetComplete()
 {
-  NS_ASSERTION(!mDirty, "Can't set a dirty sheet complete!");
+  NS_ASSERTION(!HasForcedUniqueInner(),
+               "Can't complete a sheet that's already been forced "
+               "unique.");
   SheetInfo().mComplete = true;
   if (mDocument && !mDisabled) {
     // Let the document know
     mDocument->BeginUpdate(UPDATE_STYLE);
     mDocument->SetStyleSheetApplicableState(this, true);
     mDocument->EndUpdate(UPDATE_STYLE);
   }
 
@@ -372,17 +374,17 @@ StyleSheet::DropStyleSet(const StyleSetH
   NS_ASSERTION(found, "didn't find style set");
 }
 
 void
 StyleSheet::EnsureUniqueInner()
 {
   MOZ_ASSERT(mInner->mSheets.Length() != 0,
              "unexpected number of outers");
-  mDirty = true;
+  mDirtyFlags |= FORCED_UNIQUE_INNER;
 
   if (HasUniqueInner()) {
     // already unique
     return;
   }
 
   // If this stylesheet is for XBL with Servo, don't bother cloning
   // it, as it may break ServoStyleRuleMap. XBL stylesheets are not
--- a/layout/style/StyleSheet.h
+++ b/layout/style/StyleSheet.h
@@ -127,17 +127,18 @@ public:
   inline bool IsApplicable() const;
   inline bool HasRules() const;
 
   virtual already_AddRefed<StyleSheet> Clone(StyleSheet* aCloneParent,
                                              dom::CSSImportRule* aCloneOwnerRule,
                                              nsIDocument* aCloneDocument,
                                              nsINode* aCloneOwningNode) const = 0;
 
-  bool IsModified() const { return mDirty; }
+  bool HasForcedUniqueInner() const { return mDirtyFlags &
+                                             FORCED_UNIQUE_INNER; }
 
   inline bool HasUniqueInner() const;
   void EnsureUniqueInner();
 
   // Append all of this sheet's child sheets to aArray.
   void AppendAllChildSheets(nsTArray<StyleSheet*>& aArray);
 
   // style sheet owner info
@@ -333,17 +334,20 @@ protected:
   // mParsingMode controls access to nonstandard style constructs that
   // are not safe for use on the public Web but necessary in UA sheets
   // and/or useful in user sheets.
   css::SheetParsingMode mParsingMode;
 
   const StyleBackendType mType;
   bool                  mDisabled;
 
-  bool mDirty; // has been modified
+  enum dirtyFlagAttributes {
+    FORCED_UNIQUE_INNER = 0x1,
+  };
+  uint8_t mDirtyFlags; // has been modified
 
   // 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.