Bug 1383215: Part 4 - Use location string as key in modules map. r?mccr8
Using the unmolested module location string as the cache key removes a huge
chunk of overhead when loading cached modules.
This also ensures that multiple URLs are not used to load the same module,
which would result in it being loaded more than once in the new regime
MozReview-Commit-ID: BAWoOJQSTc1
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -191,16 +191,17 @@ ReportOnCallerUTF8(JSCLContextHelper& he
va_end(ap);
return NS_OK;
}
mozJSComponentLoader::mozJSComponentLoader()
: mModules(16),
mImports(16),
mInProgressImports(16),
+ mLocations(16),
mInitialized(false)
{
MOZ_ASSERT(!sSelf, "mozJSComponentLoader should be a singleton");
sSelf = this;
}
#define ENSURE_DEP(name) { nsresult rv = Ensure##name(); NS_ENSURE_SUCCESS(rv, rv); }
@@ -247,19 +248,18 @@ class MOZ_STACK_CLASS ComponentLoaderInf
nsIURI* ResolvedURI() { MOZ_ASSERT(mResolvedURI); return mResolvedURI; }
nsresult EnsureResolvedURI() {
BEGIN_ENSURE(ResolvedURI, URI);
return ResolveURI(mURI, getter_AddRefs(mResolvedURI));
}
nsAutoCString& Key() { return *mKey; }
nsresult EnsureKey() {
- ENSURE_DEPS(ResolvedURI);
- mKey.emplace();
- return mResolvedURI->GetSpec(*mKey);
+ mKey.emplace(mLocation);
+ return NS_OK;
}
MOZ_MUST_USE nsresult GetLocation(nsCString& aLocation) {
nsresult rv = EnsureURI();
NS_ENSURE_SUCCESS(rv, rv);
return mURI->GetSpec(aLocation);
}
@@ -444,16 +444,17 @@ SizeOfTableExcludingThis(const nsBaseHas
}
size_t
mozJSComponentLoader::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
{
size_t n = aMallocSizeOf(this);
n += SizeOfTableExcludingThis(mModules, aMallocSizeOf);
n += SizeOfTableExcludingThis(mImports, aMallocSizeOf);
+ n += mLocations.ShallowSizeOfExcludingThis(aMallocSizeOf);
n += SizeOfTableExcludingThis(mInProgressImports, aMallocSizeOf);
return n;
}
void
mozJSComponentLoader::CreateLoaderGlobal(JSContext* aCx,
nsACString& aLocation,
JSAddonId* aAddonID,
@@ -758,16 +759,17 @@ mozJSComponentLoader::ObjectForLocation(
void
mozJSComponentLoader::UnloadModules()
{
mInitialized = false;
mInProgressImports.Clear();
mImports.Clear();
+ mLocations.Clear();
for (auto iter = mModules.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->Clear();
iter.Remove();
}
}
nsresult
@@ -936,16 +938,25 @@ mozJSComponentLoader::ImportInto(const n
baseFileURL = do_QueryInterface(info.ResolvedURI(), &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIFile> sourceFile;
rv = baseFileURL->GetFile(getter_AddRefs(sourceFile));
NS_ENSURE_SUCCESS(rv, rv);
+ rv = info.ResolvedURI()->GetSpec(newEntry->resolvedURL);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString* existingPath;
+ if (mLocations.Get(newEntry->resolvedURL, &existingPath) && *existingPath != info.Key()) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ mLocations.Put(newEntry->resolvedURL, &info.Key());
mInProgressImports.Put(info.Key(), newEntry);
rv = info.EnsureURI();
NS_ENSURE_SUCCESS(rv, rv);
RootedValue exception(callercx);
rv = ObjectForLocation(info, sourceFile, &newEntry->obj,
&newEntry->thisObjectKey,
&newEntry->location, true, &exception);
@@ -1107,16 +1118,17 @@ mozJSComponentLoader::Unload(const nsACS
return NS_OK;
}
ComponentLoaderInfo info(aLocation);
rv = info.EnsureKey();
NS_ENSURE_SUCCESS(rv, rv);
ModuleEntry* mod;
if (mImports.Get(info.Key(), &mod)) {
+ mLocations.Remove(mod->resolvedURL);
mImports.Remove(info.Key());
}
return NS_OK;
}
NS_IMETHODIMP
mozJSComponentLoader::Observe(nsISupports* subject, const char* topic,
--- a/js/xpconnect/loader/mozJSComponentLoader.h
+++ b/js/xpconnect/loader/mozJSComponentLoader.h
@@ -140,28 +140,34 @@ class mozJSComponentLoader : public mozi
static already_AddRefed<nsIFactory> GetFactory(const mozilla::Module& module,
const mozilla::Module::CIDEntry& entry);
nsCOMPtr<xpcIJSGetFactory> getfactoryobj;
JS::PersistentRootedObject obj;
JS::PersistentRootedScript thisObjectKey;
char* location;
+ nsCString resolvedURL;
};
friend class ModuleEntry;
static size_t DataEntrySizeOfExcludingThis(const nsACString& aKey, ModuleEntry* const& aData,
mozilla::MallocSizeOf aMallocSizeOf, void* arg);
static size_t ClassEntrySizeOfExcludingThis(const nsACString& aKey,
const nsAutoPtr<ModuleEntry>& aData,
mozilla::MallocSizeOf aMallocSizeOf, void* arg);
// Modules are intentionally leaked, but still cleared.
nsDataHashtable<nsCStringHashKey, ModuleEntry*> mModules;
nsClassHashtable<nsCStringHashKey, ModuleEntry> mImports;
nsDataHashtable<nsCStringHashKey, ModuleEntry*> mInProgressImports;
+ // A map of on-disk file locations which are loaded as modules to the
+ // pre-resolved URIs they were loaded from. Used to prevent the same file
+ // from being loaded separately, from multiple URLs.
+ nsClassHashtable<nsCStringHashKey, nsCString> mLocations;
+
bool mInitialized;
};
#endif