Bug 1382329: Part 1 - Enable lazy source whenever compiling for the preloader. r?mccr8,nbp
In general, we always want to compile with lazy source whenever we intend to
store code in the startup bytecode cache. Currently, we only do so when the
main StartupCache is available (which is only in the parent process), even if
we'll be storing code in the ScriptPreloader cache.
The main side-effect of this is that scripts which are used in a content
process do not use lazy source, but *do* use lazy parsing. And since we need
to clone pre-loaded scripts into their target compartment before executing, we
end up eagerly compiling those lazy functions on the main athreads soon as we
execute the script, in order to clone them. And this causes two side-effects
of its own:
1) It's terrible for startup performance.
2) It creates new scope chains which didn't exist when the clone began, and
which are likely responsible for
bug 1367896.
MozReview-Commit-ID: 6lZLb68zitp
--- a/js/xpconnect/loader/ScriptPreloader.cpp
+++ b/js/xpconnect/loader/ScriptPreloader.cpp
@@ -691,17 +691,17 @@ ScriptPreloader::Run()
}
void
ScriptPreloader::NoteScript(const nsCString& url, const nsCString& cachePath,
JS::HandleScript jsscript)
{
// Don't bother trying to cache any URLs with cache-busting query
// parameters.
- if (mStartupFinished || !mCacheInitialized || cachePath.FindChar('?') >= 0) {
+ if (!Active() || cachePath.FindChar('?') >= 0) {
return;
}
// Don't bother caching files that belong to the mochitest harness.
NS_NAMED_LITERAL_CSTRING(mochikitPrefix, "chrome://mochikit/");
if (StringHead(url, mochikitPrefix.Length()) == mochikitPrefix) {
return;
}
@@ -935,17 +935,18 @@ ScriptPreloader::DecodeNextBatch(size_t
return;
}
AutoJSAPI jsapi;
MOZ_RELEASE_ASSERT(jsapi.Init(xpc::CompilationScope()));
JSContext* cx = jsapi.cx();
JS::CompileOptions options(cx, JSVERSION_LATEST);
- options.setNoScriptRval(true);
+ options.setNoScriptRval(true)
+ .setSourceIsLazy(true);
if (!JS::CanCompileOffThread(cx, options, size) ||
!JS::DecodeMultiOffThreadScripts(cx, options, mParsingSources,
OffThreadDecodeCallback,
static_cast<void*>(this))) {
// If we fail here, we don't move on to process the next batch, so make
// sure we don't have any other scripts left to process.
MOZ_ASSERT(mPendingScripts.isEmpty());
--- a/js/xpconnect/loader/ScriptPreloader.h
+++ b/js/xpconnect/loader/ScriptPreloader.h
@@ -86,16 +86,21 @@ public:
ProcessType processType, nsTArray<uint8_t>&& xdrData,
TimeStamp loadTime);
// Initializes the script cache from the startup script cache file.
Result<Ok, nsresult> InitCache(const nsAString& = NS_LITERAL_STRING("scriptCache"));
Result<Ok, nsresult> InitCache(const Maybe<ipc::FileDescriptor>& cacheFile, ScriptCacheChild* cacheChild);
+ bool Active()
+ {
+ return mCacheInitialized && !mStartupFinished;
+ }
+
private:
Result<Ok, nsresult> InitCacheInternal();
public:
void Trace(JSTracer* trc);
static ProcessType CurrentProcessType()
{
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -642,17 +642,17 @@ mozJSComponentLoader::ObjectForLocation(
// XDR encoded modules in omni.ja). Also, XDR decoding is relatively
// fast. When we're not using the startup cache, we want to use non-lazy
// source code so that we can use lazy parsing.
// See bug 1303754.
CompileOptions options(cx);
options.setNoScriptRval(true)
.setVersion(JSVERSION_LATEST)
.setFileAndLine(nativePath.get(), 1)
- .setSourceIsLazy(!!cache);
+ .setSourceIsLazy(cache || ScriptPreloader::GetSingleton().Active());
if (realFile) {
AutoMemMap map;
MOZ_TRY(map.init(aComponentFile));
// Note: exceptions will get handled further down;
// don't early return for them here.
auto buf = map.get<char>();