Bug 1250379 - Create css::Loaders for specific style backend types. r=dholbert
authorCameron McCormack <cam@mcc.id.au>
Wed, 24 Feb 2016 18:01:12 +1100
changeset 285257 f1ee875a249c025d60d29fcc01a991e07df8f0db
parent 285256 5b9d0ccdf0dd75ff81681a69ae22801b7ada3b44
child 285258 fe6d5add734ec6bf779ccbca267e33b4d26f63ff
push id72299
push usercmccormack@mozilla.com
push dateWed, 24 Feb 2016 07:01:43 +0000
treeherdermozilla-inbound@f1ee875a249c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1250379
milestone47.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 1250379 - Create css::Loaders for specific style backend types. r=dholbert
dom/base/nsDocument.cpp
layout/base/nsDocumentViewer.cpp
layout/base/nsStyleSheetService.cpp
layout/style/CSSStyleSheet.cpp
layout/style/Loader.cpp
layout/style/Loader.h
layout/style/nsLayoutStylesheetCache.cpp
layout/style/nsLayoutStylesheetCache.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -4358,17 +4358,17 @@ nsDocument::LoadAdditionalStyleSheet(add
 {
   NS_PRECONDITION(aSheetURI, "null arg");
 
   // Checking if we have loaded this one already.
   if (FindSheet(mAdditionalSheets[aType], aSheetURI) >= 0)
     return NS_ERROR_INVALID_ARG;
 
   // Loading the sheet sync.
-  RefPtr<css::Loader> loader = new css::Loader();
+  RefPtr<css::Loader> loader = new css::Loader(GetStyleBackendType());
 
   css::SheetParsingMode parsingMode;
   switch (aType) {
     case nsIDocument::eAgentSheet:
       parsingMode = css::eAgentSheetFeatures;
       break;
 
     case nsIDocument::eUserSheet:
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -2232,17 +2232,18 @@ nsDocumentViewer::CreateStyleSet(nsIDocu
     nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(chromeHandler));
     nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
     if (elt && content) {
       nsCOMPtr<nsIURI> baseURI = content->GetBaseURI();
 
       nsAutoString sheets;
       elt->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets);
       if (!sheets.IsEmpty() && baseURI) {
-        RefPtr<mozilla::css::Loader> cssLoader = new mozilla::css::Loader();
+        RefPtr<mozilla::css::Loader> cssLoader =
+          new mozilla::css::Loader(backendType);
 
         char *str = ToNewCString(sheets);
         char *newStr = str;
         char *token;
         while ( (token = nsCRT::strtok(newStr, ", ", &newStr)) ) {
           NS_NewURI(getter_AddRefs(uri), nsDependentCString(token), nullptr,
                     baseURI);
           if (!uri) continue;
--- a/layout/base/nsStyleSheetService.cpp
+++ b/layout/base/nsStyleSheetService.cpp
@@ -206,17 +206,19 @@ nsStyleSheetService::LoadAndRegisterShee
       parsingMode = css::eAuthorSheetFeatures;
       break;
 
     default:
       NS_WARNING("invalid sheet type argument");
       return NS_ERROR_INVALID_ARG;
   }
 
-  RefPtr<css::Loader> loader = new css::Loader();
+  // XXXheycam We'll need to load and register both a Gecko- and Servo-backed
+  // style sheet.
+  RefPtr<css::Loader> loader = new css::Loader(StyleBackendType::Gecko);
 
   StyleSheetHandle::RefPtr sheet;
   nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mSheets[aSheetType].AppendElement(sheet);
 
   return rv;
@@ -260,17 +262,17 @@ nsStyleSheetService::PreloadSheet(nsIURI
     default:
       NS_WARNING("invalid sheet type argument");
       return NS_ERROR_INVALID_ARG;
   }
 
   // XXXheycam PreloadSheet can't support ServoStyleSheets until they implement
   // nsIDOMStyleSheet.
 
-  RefPtr<css::Loader> loader = new css::Loader();
+  RefPtr<css::Loader> loader = new css::Loader(StyleBackendType::Gecko);
 
   StyleSheetHandle::RefPtr sheet;
   nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet);
   NS_ENSURE_SUCCESS(rv, rv);
 
   MOZ_ASSERT(sheet->IsGecko(),
              "stylo: didn't expect Loader to create a ServoStyleSheet");
 
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -2239,17 +2239,17 @@ CSSStyleSheet::ReparseSheet(const nsAStr
 
   // 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!");
   } else {
-    loader = new css::Loader();
+    loader = new css::Loader(StyleBackendType::Gecko);
   }
 
   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
 
   WillDirty();
 
   // detach existing rules (including child sheets via import rules)
   css::LoaderReusableStyleSheets reusableSheets;
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -527,20 +527,21 @@ LoaderReusableStyleSheets::FindReusableS
   }
   return false;
 }
 
 /*************************
  * Loader Implementation *
  *************************/
 
-Loader::Loader(void)
+Loader::Loader(StyleBackendType aType)
   : mDocument(nullptr)
   , mDatasToNotifyOn(0)
   , mCompatMode(eCompatibility_FullStandards)
+  , mStyleBackendType(Some(aType))
   , mEnabled(true)
 #ifdef DEBUG
   , mSyncCallback(false)
 #endif
 {
 }
 
 Loader::Loader(nsIDocument* aDocument)
@@ -1083,17 +1084,17 @@ Loader::CreateSheet(nsIURI* aURI,
   *aSheet = nullptr;
   aSheetState = eSheetStateUnknown;
 
   // Check the alternate state before doing anything else, because it
   // can mess with our hashtables.
   *aIsAlternate = IsAlternate(aTitle, aHasAlternateRel);
 
   // XXXheycam Cached sheets currently must be CSSStyleSheets.
-  if (aURI) {
+  if (aURI && GetStyleBackendType() == StyleBackendType::Gecko) {
     aSheetState = eSheetComplete;
     StyleSheetHandle::RefPtr sheet;
 
     // First, the XUL cache
 #ifdef MOZ_XUL
     if (IsChromeURI(aURI)) {
       nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
       if (cache) {
@@ -2623,10 +2624,22 @@ Loader::SizeOfIncludingThis(mozilla::Mal
   //
   // The following members aren't measured:
   // - mDocument, because it's a weak backpointer
   // - mPreferredSheet, because it can be a shared string
 
   return n;
 }
 
+StyleBackendType
+Loader::GetStyleBackendType() const
+{
+  MOZ_ASSERT(mStyleBackendType || mDocument,
+             "you must construct a Loader with a document or set a "
+             "StyleBackendType on it before calling GetStyleBackendType");
+  if (mStyleBackendType) {
+    return *mStyleBackendType;
+  }
+  return mDocument->GetStyleBackendType();
+}
+
 } // namespace css
 } // namespace mozilla
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -16,17 +16,19 @@
 #include "nsRefPtrHashtable.h"
 #include "nsStringFwd.h"
 #include "nsTArray.h"
 #include "nsTObserverArray.h"
 #include "nsURIHashKey.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/CORSMode.h"
 #include "mozilla/CSSStyleSheet.h"
+#include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/StyleBackendType.h"
 #include "mozilla/StyleSheetHandle.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 class nsICSSLoaderObserver;
 class nsIContent;
 class nsIDocument;
 class nsMediaList;
 class nsIStyleSheetLinkingElement;
@@ -183,27 +185,40 @@ enum StyleSheetState {
   eSheetLoading,
   eSheetComplete
 };
 
 class Loader final {
   typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
 
 public:
-  Loader();
+  explicit Loader(StyleBackendType aType);
   explicit Loader(nsIDocument*);
 
  private:
   // Private destructor, to discourage deletion outside of Release():
   ~Loader();
 
  public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Loader)
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(Loader)
 
+  /**
+   * Returns the StyleBackendType that will be used for style sheets created
+   * by this Loader.  If SetStyleBackendType has been called, that value
+   * will be returned by GetStyleBackendType.  For Loaders created with the
+   * nsIDocument* constructor and which haven't had SetStyleBackendType
+   * called on them, the document's StyleBackendType will be returned.
+   */
+  StyleBackendType GetStyleBackendType() const;
+
+  void SetStyleBackendType(StyleBackendType aType) {
+    mStyleBackendType = Some(aType);
+  }
+
   void DropDocumentReference(); // notification that doc is going away
 
   void SetCompatibilityMode(nsCompatibility aCompatMode)
   { mCompatMode = aCompatMode; }
   nsCompatibility GetCompatibilityMode() { return mCompatMode; }
   nsresult SetPreferredSheet(const nsAString& aTitle);
 
   // XXXbz sort out what the deal is with events!  When should they fire?
@@ -568,16 +583,18 @@ private:
   // whole bunch at once (e.g. in one of the stop methods).  This is used to
   // make sure that HasPendingLoads() won't return false until we're notifying
   // on the last data we're working with.
   uint32_t          mDatasToNotifyOn;
 
   nsCompatibility   mCompatMode;
   nsString          mPreferredSheet;  // title of preferred sheet
 
+  mozilla::Maybe<StyleBackendType> mStyleBackendType;
+
   bool              mEnabled; // is enabled to load new styles
 
 #ifdef DEBUG
   bool              mSyncCallback;
 #endif
 };
 
 } // namespace css
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -238,17 +238,18 @@ nsLayoutStylesheetCache::DesignModeSheet
   }
 
   return mDesignModeSheet;
 }
 
 void
 nsLayoutStylesheetCache::Shutdown()
 {
-  NS_IF_RELEASE(gCSSLoader);
+  gCSSLoader_Gecko = nullptr;
+  gCSSLoader_Servo = nullptr;
   gStyleCache_Gecko = nullptr;
   gStyleCache_Servo = nullptr;
 }
 
 MOZ_DEFINE_MALLOC_SIZE_OF(LayoutStylesheetCacheMallocSizeOf)
 
 NS_IMETHODIMP
 nsLayoutStylesheetCache::CollectReports(nsIHandleReportCallback* aHandleReport,
@@ -285,17 +286,18 @@ nsLayoutStylesheetCache::SizeOfIncluding
   MEASURE(mScrollbarsSheet);
   MEASURE(mUASheet);
   MEASURE(mUserChromeSheet);
   MEASURE(mUserContentSheet);
   MEASURE(mXULSheet);
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
-  // - gCSSLoader
+  // - gCSSLoader_Gecko
+  // - gCSSLoader_Servo
 
   return n;
 }
 
 nsLayoutStylesheetCache::nsLayoutStylesheetCache(StyleBackendType aType)
   : mBackendType(aType)
 {
   nsCOMPtr<nsIObserverService> obsSvc =
@@ -401,17 +403,17 @@ nsLayoutStylesheetCache::InitFromProfile
 
   contentFile->Append(NS_LITERAL_STRING("userContent.css"));
   chromeFile->Append(NS_LITERAL_STRING("userChrome.css"));
 
   LoadSheetFile(contentFile, mUserContentSheet, eUserSheetFeatures);
   LoadSheetFile(chromeFile, mUserChromeSheet, eUserSheetFeatures);
 }
 
-/* static */ void
+void
 nsLayoutStylesheetCache::LoadSheetURL(const char* aURL,
                                       StyleSheetHandle::RefPtr& aSheet,
                                       SheetParsingMode aParsingMode)
 {
   nsCOMPtr<nsIURI> uri;
   NS_NewURI(getter_AddRefs(uri), aURL);
   LoadSheet(uri, aSheet, aParsingMode);
   if (!aSheet) {
@@ -730,41 +732,44 @@ nsLayoutStylesheetCache::LoadSheet(nsIUR
                                    StyleSheetHandle::RefPtr& aSheet,
                                    SheetParsingMode aParsingMode)
 {
   if (!aURI) {
     ErrorLoadingBuiltinSheet(aURI, "null URI");
     return;
   }
 
-  if (!gCSSLoader) {
-    gCSSLoader = new mozilla::css::Loader();
-    NS_IF_ADDREF(gCSSLoader);
-    if (!gCSSLoader) {
+  auto& loader = mBackendType == StyleBackendType::Gecko ?
+    gCSSLoader_Gecko :
+    gCSSLoader_Servo;
+
+  if (!loader) {
+    loader = new mozilla::css::Loader(mBackendType);
+    if (!loader) {
       ErrorLoadingBuiltinSheet(aURI, "no Loader");
       return;
     }
   }
 
-
 #ifdef MOZ_CRASHREPORTER
   nsZipArchive::sFileCorruptedReason = nullptr;
 #endif
-  nsresult rv = gCSSLoader->LoadSheetSync(aURI, aParsingMode, true, &aSheet);
+  nsresult rv = loader->LoadSheetSync(aURI, aParsingMode, true, &aSheet);
   if (NS_FAILED(rv)) {
     ErrorLoadingBuiltinSheet(aURI,
       nsPrintfCString("LoadSheetSync failed with error %x", rv).get());
   }
 }
 
 /* static */ void
 nsLayoutStylesheetCache::InvalidateSheet(StyleSheetHandle::RefPtr* aGeckoSheet,
                                          StyleSheetHandle::RefPtr* aServoSheet)
 {
-  MOZ_ASSERT(gCSSLoader, "pref changed before we loaded a sheet?");
+  MOZ_ASSERT(gCSSLoader_Gecko || gCSSLoader_Servo,
+             "pref changed before we loaded a sheet?");
 
   // Make sure sheets have the expected types
   MOZ_ASSERT(!aGeckoSheet || (*aGeckoSheet)->IsGecko());
   MOZ_ASSERT(!aServoSheet || (*aServoSheet)->IsServo());
   // Make sure the URIs match
   MOZ_ASSERT(!aGeckoSheet || !aServoSheet ||
              (*aGeckoSheet)->GetSheetURI() == (*aServoSheet)->GetSheetURI(),
              "Sheets passed should have the same URI");
@@ -773,35 +778,40 @@ nsLayoutStylesheetCache::InvalidateSheet
   if (aGeckoSheet && *aGeckoSheet) {
     uri = (*aGeckoSheet)->GetSheetURI();
   } else if (aServoSheet && *aServoSheet) {
     uri = (*aServoSheet)->GetSheetURI();
   } else {
     return;
   }
 
-  gCSSLoader->ObsoleteSheet(uri);
+  if (gCSSLoader_Gecko) {
+    gCSSLoader_Gecko->ObsoleteSheet(uri);
+  }
+  if (gCSSLoader_Servo) {
+    gCSSLoader_Servo->ObsoleteSheet(uri);
+  }
   if (aGeckoSheet) {
     *aGeckoSheet = nullptr;
   }
   if (aServoSheet) {
     *aServoSheet = nullptr;
   }
 }
 
 /* static */ void
 nsLayoutStylesheetCache::DependentPrefChanged(const char* aPref, void* aData)
 {
   MOZ_ASSERT(gStyleCache_Gecko || gStyleCache_Servo,
              "pref changed after shutdown?");
 
   // Cause any UA style sheets whose parsing depends on the value of prefs
-  // to be re-parsed by dropping the sheet from gCSSLoader's cache then
-  // setting our cached sheet pointer to null.  This will only work for sheets
-  // that are loaded lazily.
+  // to be re-parsed by dropping the sheet from gCSSLoader_{Gecko,Servo}'s cache
+  // then setting our cached sheet pointer to null.  This will only work for
+  // sheets that are loaded lazily.
 
 #define INVALIDATE(sheet_) \
   InvalidateSheet(gStyleCache_Gecko ? &gStyleCache_Gecko->sheet_ : nullptr, \
                   gStyleCache_Servo ? &gStyleCache_Servo->sheet_ : nullptr);
 
   INVALIDATE(mUASheet);  // for layout.css.grid.enabled
 
 #undef INVALIDATE
@@ -929,10 +939,13 @@ nsLayoutStylesheetCache::BuildPreference
 }
 
 mozilla::StaticRefPtr<nsLayoutStylesheetCache>
 nsLayoutStylesheetCache::gStyleCache_Gecko;
 
 mozilla::StaticRefPtr<nsLayoutStylesheetCache>
 nsLayoutStylesheetCache::gStyleCache_Servo;
 
-mozilla::css::Loader*
-nsLayoutStylesheetCache::gCSSLoader = nullptr;
+mozilla::StaticRefPtr<mozilla::css::Loader>
+nsLayoutStylesheetCache::gCSSLoader_Gecko;
+
+mozilla::StaticRefPtr<mozilla::css::Loader>
+nsLayoutStylesheetCache::gCSSLoader_Servo;
--- a/layout/style/nsLayoutStylesheetCache.h
+++ b/layout/style/nsLayoutStylesheetCache.h
@@ -70,33 +70,34 @@ class nsLayoutStylesheetCache final
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
   explicit nsLayoutStylesheetCache(mozilla::StyleBackendType aImpl);
   ~nsLayoutStylesheetCache();
 
   void InitFromProfile();
   void InitMemoryReporter();
-  static void LoadSheetURL(const char* aURL,
-                           mozilla::StyleSheetHandle::RefPtr& aSheet,
-                           mozilla::css::SheetParsingMode aParsingMode);
-  static void LoadSheetFile(nsIFile* aFile,
-                            mozilla::StyleSheetHandle::RefPtr& aSheet,
-                            mozilla::css::SheetParsingMode aParsingMode);
-  static void LoadSheet(nsIURI* aURI, mozilla::StyleSheetHandle::RefPtr& aSheet,
-                        mozilla::css::SheetParsingMode aParsingMode);
+  void LoadSheetURL(const char* aURL,
+                    mozilla::StyleSheetHandle::RefPtr& aSheet,
+                    mozilla::css::SheetParsingMode aParsingMode);
+  void LoadSheetFile(nsIFile* aFile,
+                     mozilla::StyleSheetHandle::RefPtr& aSheet,
+                     mozilla::css::SheetParsingMode aParsingMode);
+  void LoadSheet(nsIURI* aURI, mozilla::StyleSheetHandle::RefPtr& aSheet,
+                 mozilla::css::SheetParsingMode aParsingMode);
   static void InvalidateSheet(mozilla::StyleSheetHandle::RefPtr* aGeckoSheet,
                               mozilla::StyleSheetHandle::RefPtr* aServoSheet);
   static void DependentPrefChanged(const char* aPref, void* aData);
   void BuildPreferenceSheet(mozilla::StyleSheetHandle::RefPtr& aSheet,
                             nsPresContext* aPresContext);
 
   static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache_Gecko;
   static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache_Servo;
-  static mozilla::css::Loader* gCSSLoader;
+  static mozilla::StaticRefPtr<mozilla::css::Loader> gCSSLoader_Gecko;
+  static mozilla::StaticRefPtr<mozilla::css::Loader> gCSSLoader_Servo;
   mozilla::StyleBackendType mBackendType;
   mozilla::StyleSheetHandle::RefPtr mChromePreferenceSheet;
   mozilla::StyleSheetHandle::RefPtr mContentEditableSheet;
   mozilla::StyleSheetHandle::RefPtr mContentPreferenceSheet;
   mozilla::StyleSheetHandle::RefPtr mCounterStylesSheet;
   mozilla::StyleSheetHandle::RefPtr mDesignModeSheet;
   mozilla::StyleSheetHandle::RefPtr mFormsSheet;
   mozilla::StyleSheetHandle::RefPtr mHTMLSheet;