Bug 1363640 Part 5 - Add a table in nsXULPrototypeCache to cache XBL documents with servo backend.
We assume those XBL documents without a bound document use gecko style
backend. Their backend type will be explicitly set when loading in Part 6.
MozReview-Commit-ID: 5c5xtYFvgAD
--- a/dom/xbl/nsXBLDocumentInfo.h
+++ b/dom/xbl/nsXBLDocumentInfo.h
@@ -18,18 +18,17 @@ class nsXBLPrototypeBinding;
class nsXBLDocumentInfo final : public nsSupportsWeakReference
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
explicit nsXBLDocumentInfo(nsIDocument* aDocument);
- already_AddRefed<nsIDocument> GetDocument()
- { nsCOMPtr<nsIDocument> copy = mDocument; return copy.forget(); }
+ nsIDocument* GetDocument() const { return mDocument; }
bool GetScriptAccess() const { return mScriptAccess; }
nsIURI* DocumentURI() { return mDocument->GetDocumentURI(); }
nsXBLPrototypeBinding* GetPrototypeBinding(const nsACString& aRef);
nsresult SetPrototypeBinding(const nsACString& aRef,
nsXBLPrototypeBinding* aBinding);
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -946,19 +946,26 @@ nsXBLService::LoadBindingDocumentInfo(ns
#ifdef MOZ_XUL
// The second line of defense is the global nsXULPrototypeCache,
// if it's being used.
nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
bool useXULCache = cache && cache->IsEnabled();
if (!info && useXULCache) {
+ // Assume Gecko style backend for the XBL document without a bound
+ // document. The only case is loading platformHTMLBindings.xml which
+ // doesn't have any style sheets or style attributes.
+ StyleBackendType styleBackend
+ = aBoundDocument ? aBoundDocument->GetStyleBackendType()
+ : StyleBackendType::Gecko;
+
// This cache crosses the entire product, so that any XBL bindings that are
// part of chrome will be reused across all XUL documents.
- info = cache->GetXBLDocumentInfo(documentURI);
+ info = cache->GetXBLDocumentInfo(documentURI, styleBackend);
}
bool useStartupCache = useXULCache && IsChromeOrResourceURI(documentURI);
if (!info) {
// Next, look in the startup cache
if (!info && useStartupCache) {
rv = nsXBLDocumentInfo::ReadPrototypeBindings(documentURI, getter_AddRefs(info));
@@ -1011,16 +1018,22 @@ nsXBLService::LoadBindingDocumentInfo(ns
// before, it can continue to use it even if the XUL prototype
// cache gets flushed. That way, if a flush does occur, we
// don't get into a weird state where we're using different
// XBLDocumentInfos for the same XBL document in a single
// document that has loaded some bindings.
bindingManager->PutXBLDocumentInfo(info);
}
+ MOZ_ASSERT(!aBoundDocument || !info ||
+ aBoundDocument->GetStyleBackendType() ==
+ info->GetDocument()->GetStyleBackendType(),
+ "Style backend type mismatched between the bound document and "
+ "the XBL document loaded.");
+
info.forget(aResult);
return NS_OK;
}
nsresult
nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoundDocument,
nsIURI* aDocumentURI, nsIURI* aBindingURI,
--- a/dom/xul/nsXULPrototypeCache.cpp
+++ b/dom/xul/nsXULPrototypeCache.cpp
@@ -233,77 +233,90 @@ nsXULPrototypeCache::PutScript(nsIURI* a
}
#endif
mScriptTable.Put(aURI, aScriptObject);
return NS_OK;
}
+nsXBLDocumentInfo*
+nsXULPrototypeCache::GetXBLDocumentInfo(nsIURI* aURL,
+ StyleBackendType aType)
+{
+ MOZ_ASSERT(aType != StyleBackendType::None,
+ "Please use either gecko or servo when looking up for the cache!");
+ return XBLDocTableFor(aType).GetWeak(aURL);
+}
+
nsresult
nsXULPrototypeCache::PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo)
{
- nsIURI* uri = aDocumentInfo->DocumentURI();
+ nsIURI* uri = aDocumentInfo->DocumentURI();
+ XBLDocTable& table =
+ XBLDocTableFor(aDocumentInfo->GetDocument()->GetStyleBackendType());
- RefPtr<nsXBLDocumentInfo> info;
- mXBLDocTable.Get(uri, getter_AddRefs(info));
- if (!info) {
- mXBLDocTable.Put(uri, aDocumentInfo);
- }
- return NS_OK;
+ nsXBLDocumentInfo* info = table.GetWeak(uri);
+ if (!info) {
+ table.Put(uri, aDocumentInfo);
+ }
+ return NS_OK;
}
void
nsXULPrototypeCache::FlushSkinFiles()
{
- // Flush out skin XBL files from the cache.
- for (auto iter = mXBLDocTable.Iter(); !iter.Done(); iter.Next()) {
- nsAutoCString str;
- iter.Key()->GetPath(str);
- if (strncmp(str.get(), "/skin", 5) == 0) {
- iter.Remove();
+ StyleBackendType tableTypes[] = { StyleBackendType::Gecko,
+ StyleBackendType::Servo };
+
+ for (auto tableType : tableTypes) {
+ // Flush out skin XBL files from the cache.
+ XBLDocTable& xblDocTable = XBLDocTableFor(tableType);
+ for (auto iter = xblDocTable.Iter(); !iter.Done(); iter.Next()) {
+ nsAutoCString str;
+ iter.Key()->GetPath(str);
+ if (strncmp(str.get(), "/skin", 5) == 0) {
+ iter.Remove();
+ }
}
- }
- // Now flush out our skin stylesheets from the cache.
- mozilla::StyleBackendType tableTypes[] = { StyleBackendType::Gecko,
- StyleBackendType::Servo };
- for (auto tableType : tableTypes) {
+ // Now flush out our skin stylesheets from the cache.
StyleSheetTable& table = StyleSheetTableFor(tableType);
for (auto iter = table.Iter(); !iter.Done(); iter.Next()) {
nsAutoCString str;
iter.Data()->GetSheetURI()->GetPath(str);
if (strncmp(str.get(), "/skin", 5) == 0) {
iter.Remove();
}
}
- }
- // Iterate over all the remaining XBL and make sure cached
- // scoped skin stylesheets are flushed and refetched by the
- // prototype bindings.
- for (auto iter = mXBLDocTable.Iter(); !iter.Done(); iter.Next()) {
- iter.Data()->FlushSkinStylesheets();
+ // Iterate over all the remaining XBL and make sure cached
+ // scoped skin stylesheets are flushed and refetched by the
+ // prototype bindings.
+ for (auto iter = xblDocTable.Iter(); !iter.Done(); iter.Next()) {
+ iter.Data()->FlushSkinStylesheets();
+ }
}
}
void
nsXULPrototypeCache::FlushScripts()
{
mScriptTable.Clear();
}
void
nsXULPrototypeCache::Flush()
{
mPrototypeTable.Clear();
mScriptTable.Clear();
mGeckoStyleSheetTable.Clear();
mServoStyleSheetTable.Clear();
- mXBLDocTable.Clear();
+ mGeckoXBLDocTable.Clear();
+ mServoXBLDocTable.Clear();
}
bool
nsXULPrototypeCache::IsEnabled()
{
return !gDisableXULCache;
}
@@ -588,18 +601,24 @@ nsXULPrototypeCache::BeginCaching(nsIURI
}
return NS_OK;
}
void
nsXULPrototypeCache::MarkInCCGeneration(uint32_t aGeneration)
{
- for (auto iter = mXBLDocTable.Iter(); !iter.Done(); iter.Next()) {
- iter.Data()->MarkInCCGeneration(aGeneration);
+ StyleBackendType tableTypes[] = { StyleBackendType::Gecko,
+ StyleBackendType::Servo };
+
+ for (auto tableType : tableTypes) {
+ XBLDocTable& xblDocTable = XBLDocTableFor(tableType);
+ for (auto iter = xblDocTable.Iter(); !iter.Done(); iter.Next()) {
+ iter.Data()->MarkInCCGeneration(aGeneration);
+ }
}
for (auto iter = mPrototypeTable.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->MarkInCCGeneration(aGeneration);
}
}
void
nsXULPrototypeCache::MarkInGC(JSTracer* aTrc)
--- a/dom/xul/nsXULPrototypeCache.h
+++ b/dom/xul/nsXULPrototypeCache.h
@@ -60,19 +60,19 @@ public:
// from the cache.
nsXULPrototypeDocument* GetPrototype(nsIURI* aURI);
nsresult PutPrototype(nsXULPrototypeDocument* aDocument);
JSScript* GetScript(nsIURI* aURI);
nsresult PutScript(nsIURI* aURI, JS::Handle<JSScript*> aScriptObject);
- nsXBLDocumentInfo* GetXBLDocumentInfo(nsIURI* aURL) {
- return mXBLDocTable.GetWeak(aURL);
- }
+ nsXBLDocumentInfo* GetXBLDocumentInfo(nsIURI* aURL,
+ mozilla::StyleBackendType aType);
+
nsresult PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo);
/**
* Get a style sheet by URI. If the style sheet is not in the cache,
* returns nullptr.
*/
mozilla::StyleSheet* GetStyleSheet(nsIURI* aURI,
mozilla::StyleBackendType aType);
@@ -117,27 +117,35 @@ protected:
nsXULPrototypeCache();
virtual ~nsXULPrototypeCache();
static nsXULPrototypeCache* sInstance;
void FlushSkinFiles();
- typedef nsRefPtrHashtable<nsURIHashKey, mozilla::StyleSheet> StyleSheetTable;
+ using StyleSheetTable = nsRefPtrHashtable<nsURIHashKey, mozilla::StyleSheet>;
+ using XBLDocTable = nsRefPtrHashtable<nsURIHashKey, nsXBLDocumentInfo>;
+
StyleSheetTable& StyleSheetTableFor(mozilla::StyleBackendType aType) {
return aType == mozilla::StyleBackendType::Gecko ? mGeckoStyleSheetTable
: mServoStyleSheetTable;
}
+ XBLDocTable& XBLDocTableFor(mozilla::StyleBackendType aType) {
+ return aType == mozilla::StyleBackendType::Gecko ? mGeckoXBLDocTable
+ : mServoXBLDocTable;
+ }
+
nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument> mPrototypeTable; // owns the prototypes
StyleSheetTable mGeckoStyleSheetTable;
StyleSheetTable mServoStyleSheetTable;
nsJSThingHashtable<nsURIHashKey, JSScript*> mScriptTable;
- nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo> mXBLDocTable;
+ XBLDocTable mGeckoXBLDocTable;
+ XBLDocTable mServoXBLDocTable;
// URIs already written to the startup cache, to prevent double-caching.
nsTHashtable<nsURIHashKey> mStartupCacheURITable;
nsInterfaceHashtable<nsURIHashKey, nsIStorageStream> mOutputStreamTable;
nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable;
// Bootstrap caching service