diff --git a/js/xpconnect/loader/ScriptPreloader.cpp b/js/xpconnect/loader/ScriptPreloader.cpp index b22ed3161ce6..1a0879d8ff63 100644 --- a/js/xpconnect/loader/ScriptPreloader.cpp +++ b/js/xpconnect/loader/ScriptPreloader.cpp @@ -6,6 +6,7 @@ #include "ScriptPreloader-inl.h" #include "mozilla/ScriptPreloader.h" +#include "mozJSComponentLoader.h" #include "mozilla/loader/ScriptCacheActors.h" #include "mozilla/URLPreloader.h" @@ -907,6 +908,12 @@ ScriptPreloader::DoFinishOffThreadDecode() MaybeFinishOffThreadDecode(); } +JSObject* +ScriptPreloader::CompilationScope(JSContext* cx) +{ + return mozJSComponentLoader::Get()->CompilationScope(cx); +} + void ScriptPreloader::MaybeFinishOffThreadDecode() { @@ -922,10 +929,10 @@ ScriptPreloader::MaybeFinishOffThreadDecode() DecodeNextBatch(OFF_THREAD_CHUNK_SIZE); }); - AutoJSAPI jsapi; - MOZ_RELEASE_ASSERT(jsapi.Init(xpc::CompilationScope())); - + AutoSafeJSAPI jsapi; JSContext* cx = jsapi.cx(); + + JSAutoCompartment ac(cx, CompilationScope(cx)); JS::Rooted jsScripts(cx, JS::ScriptVector(cx)); // If this fails, we still need to mark the scripts as finished. Any that @@ -993,9 +1000,9 @@ ScriptPreloader::DecodeNextBatch(size_t chunkSize) return; } - AutoJSAPI jsapi; - MOZ_RELEASE_ASSERT(jsapi.Init(xpc::CompilationScope())); + AutoSafeJSAPI jsapi; JSContext* cx = jsapi.cx(); + JSAutoCompartment ac(cx, CompilationScope(cx)); JS::CompileOptions options(cx, JSVERSION_DEFAULT); options.setNoScriptRval(true) diff --git a/js/xpconnect/loader/ScriptPreloader.h b/js/xpconnect/loader/ScriptPreloader.h index ee89632e5c7b..4c83b0736847 100644 --- a/js/xpconnect/loader/ScriptPreloader.h +++ b/js/xpconnect/loader/ScriptPreloader.h @@ -390,6 +390,11 @@ private: void MaybeFinishOffThreadDecode(); void DoFinishOffThreadDecode(); + // Returns the global scope object for off-thread compilation. When global + // sharing is enabled in the component loader, this should be the shared + // module global. Otherwise, it should be the XPConnect compilation scope. + JSObject* CompilationScope(JSContext* cx); + size_t ShallowHeapSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) { return (mallocSizeOf(this) + mScripts.ShallowSizeOfExcludingThis(mallocSizeOf) + diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index b8424742f4b7..c5b441025661 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -301,6 +301,8 @@ NS_IMPL_ISUPPORTS(mozJSComponentLoader, nsresult mozJSComponentLoader::ReallyInit() { + MOZ_ASSERT(!mInitialized); + mShareLoaderGlobal = Preferences::GetBool("jsloader.shareGlobal"); nsresult rv; @@ -468,7 +470,7 @@ mozJSComponentLoader::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) void mozJSComponentLoader::CreateLoaderGlobal(JSContext* aCx, - nsACString& aLocation, + const nsACString& aLocation, JSAddonId* aAddonID, MutableHandleObject aGlobal) { @@ -550,6 +552,31 @@ mozJSComponentLoader::ReuseGlobal(bool aIsAddon, nsIURI* aURI) return true; } +JSObject* +mozJSComponentLoader::GetSharedGlobal(JSContext* aCx) +{ + if (!mLoaderGlobal) { + MOZ_ASSERT(mShareLoaderGlobal); + + JS::RootedObject globalObj(aCx); + CreateLoaderGlobal(aCx, NS_LITERAL_CSTRING("shared JSM global"), + nullptr, &globalObj); + + // If we fail to create a module global this early, we're not going to + // get very far, so just bail out now. + MOZ_RELEASE_ASSERT(globalObj); + mLoaderGlobal = globalObj; + + // AutoEntryScript required to invoke debugger hook, which is a + // Gecko-specific concept at present. + dom::AutoEntryScript aes(globalObj, + "component loader report global"); + JS_FireOnNewGlobalObject(aes.cx(), globalObj); + } + + return mLoaderGlobal; +} + JSObject* mozJSComponentLoader::PrepareObjectForLocation(JSContext* aCx, nsIFile* aComponentFile, @@ -567,25 +594,10 @@ mozJSComponentLoader::PrepareObjectForLocation(JSContext* aCx, bool createdNewGlobal = false; RootedObject globalObj(aCx); - if (reuseGlobal) - globalObj = mLoaderGlobal; - - if (!globalObj) { - nsAutoCString globalLocation; - if (reuseGlobal) { - globalLocation.AssignLiteral("shared JSM global"); - } else { - globalLocation.Assign(nativePath); - } - - CreateLoaderGlobal(aCx, globalLocation, - addonId, &globalObj); - NS_ENSURE_TRUE(globalObj, nullptr); - - if (reuseGlobal) { - mLoaderGlobal = globalObj; - } - + if (reuseGlobal) { + globalObj = GetSharedGlobal(aCx); + } else if (!globalObj) { + CreateLoaderGlobal(aCx, nativePath, addonId, &globalObj); createdNewGlobal = true; } diff --git a/js/xpconnect/loader/mozJSComponentLoader.h b/js/xpconnect/loader/mozJSComponentLoader.h index 7dbbdc758c7c..6ef4a47925b3 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.h +++ b/js/xpconnect/loader/mozJSComponentLoader.h @@ -20,12 +20,18 @@ #include "jsapi.h" #include "xpcIJSGetFactory.h" +#include "xpcpublic.h" class nsIFile; class nsIPrincipal; class nsIXPConnectJSObjectHolder; class ComponentLoaderInfo; +namespace mozilla { + class ScriptPreloader; +} // namespace mozilla + + /* 6bd13476-1dd2-11b2-bbef-f0ccb5fa64b6 (thanks, mozbot) */ #define MOZJSCOMPONENTLOADER_CID \ @@ -71,12 +77,28 @@ class mozJSComponentLoader : public mozilla::ModuleLoader, void UnloadModules(); void CreateLoaderGlobal(JSContext* aCx, - nsACString& aLocation, + const nsACString& aLocation, JSAddonId* aAddonID, JS::MutableHandleObject aGlobal); bool ReuseGlobal(bool aIsAddon, nsIURI* aComponent); + friend class mozilla::ScriptPreloader; + + JSObject* CompilationScope(JSContext* aCx) + { + if (mLoaderGlobal) + return mLoaderGlobal; + if ((mInitialized || NS_SUCCEEDED(ReallyInit())) && + mShareLoaderGlobal) + { + return GetSharedGlobal(aCx); + } + return xpc::CompilationScope(); + } + + JSObject* GetSharedGlobal(JSContext* aCx); + JSObject* PrepareObjectForLocation(JSContext* aCx, nsIFile* aComponentFile, nsIURI* aComponent,