From 965cab1dbcd4f0e5551249c215524726963899a4 Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Wed, 12 May 2021 13:57:56 +0000 Subject: [PATCH] Bug 1458339 part 2 - Use shared memory to initialize the JS engine. r=smaug,tcampbell,necko-reviewers This modification relies on the shared memory implemented in Bug 1698045 and on the ability to encode and decode self-hosted content from Bug 1668361 to optimize the JS engine initialization by making the parent process encode the self-hosted stencil, such that all other runtime initialization would only have to decode it, including content processes. Differential Revision: https://phabricator.services.mozilla.com/D110578 --- dom/workers/RuntimeService.cpp | 9 ++++++- dom/worklet/WorkletThread.cpp | 9 ++++++- js/xpconnect/src/XPCJSContext.cpp | 32 +++++++++++++++++++++++- modules/libpref/init/StaticPrefList.yaml | 9 +++++++ netwerk/base/ProxyAutoConfig.cpp | 14 +++++++++-- 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 3e548b35d6f5..efae970da588 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -25,6 +25,7 @@ #include "jsfriendapi.h" #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* #include "js/ContextOptions.h" +#include "js/Initialization.h" #include "js/LocaleSensitive.h" #include "js/WasmFeatures.h" #include "mozilla/ArrayUtils.h" @@ -64,6 +65,7 @@ #include "nsXPCOMPrivate.h" #include "OSFileConstants.h" #include "xpcpublic.h" +#include "XPCSelfHostedShmem.h" #if defined(XP_MACOSX) # include "nsMacUtilsImpl.h" @@ -729,7 +731,12 @@ bool InitJSContextForWorker(WorkerPrivate* aWorkerPrivate, JS::InitConsumeStreamCallback(aWorkerCx, ConsumeStream, FetchUtil::ReportJSStreamError); - if (!JS::InitSelfHostedCode(aWorkerCx)) { + // When available, set the self-hosted shared memory to be read, so that we + // can decode the self-hosted content instead of parsing it. + auto& shm = xpc::SelfHostedShmem::GetSingleton(); + JS::SelfHostedCache selfHostedContent = shm.Content(); + + if (!JS::InitSelfHostedCode(aWorkerCx, selfHostedContent)) { NS_WARNING("Could not init self-hosted code!"); return false; } diff --git a/dom/worklet/WorkletThread.cpp b/dom/worklet/WorkletThread.cpp index e59c7c791988..c672dfb21b8b 100644 --- a/dom/worklet/WorkletThread.cpp +++ b/dom/worklet/WorkletThread.cpp @@ -18,6 +18,8 @@ #include "mozilla/EventQueue.h" #include "mozilla/ThreadEventQueue.h" #include "js/Exception.h" +#include "js/Initialization.h" +#include "XPCSelfHostedShmem.h" namespace mozilla { namespace dom { @@ -369,7 +371,12 @@ void WorkletThread::EnsureCycleCollectedJSContext(JSRuntime* aParentRuntime) { JS_SetNativeStackQuota(context->Context(), WORKLET_CONTEXT_NATIVE_STACK_LIMIT); - if (!JS::InitSelfHostedCode(context->Context())) { + // When available, set the self-hosted shared memory to be read, so that we + // can decode the self-hosted content instead of parsing it. + auto& shm = xpc::SelfHostedShmem::GetSingleton(); + JS::SelfHostedCache selfHostedContent = shm.Content(); + + if (!JS::InitSelfHostedCode(context->Context(), selfHostedContent)) { // TODO: error propagation return; } diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp index 184d504692b1..aca25c4d1d1a 100644 --- a/js/xpconnect/src/XPCJSContext.cpp +++ b/js/xpconnect/src/XPCJSContext.cpp @@ -13,6 +13,7 @@ #include "xpcpublic.h" #include "XPCWrapper.h" #include "XPCJSMemoryReporter.h" +#include "XPCSelfHostedShmem.h" #include "WrapperFactory.h" #include "mozJSComponentLoader.h" #include "nsNetUtil.h" @@ -40,6 +41,7 @@ #include "jsapi.h" #include "js/ArrayBuffer.h" #include "js/ContextOptions.h" +#include "js/Initialization.h" #include "js/MemoryMetrics.h" #include "js/OffThreadScriptCompilation.h" #include "js/WasmFeatures.h" @@ -794,6 +796,9 @@ void xpc::SetPrefableRealmOptions(JS::RealmOptions& options) { .setIteratorHelpersEnabled(sIteratorHelpersEnabled); } +// Mirrored value of javascript.options.self_hosted.use_shared_memory. +static bool sSelfHostedUseSharedMemory = false; + static void LoadStartupJSPrefs(XPCJSContext* xpccx) { // Prefs that require a restart are handled here. This includes the // process-wide JIT options because toggling these at runtime can easily cause @@ -830,6 +835,7 @@ static void LoadStartupJSPrefs(XPCJSContext* xpccx) { cx, JSJITCOMPILER_JIT_TRUSTEDPRINCIPALS_ENABLE, false); JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_NATIVE_REGEXP_ENABLE, false); + sSelfHostedUseSharedMemory = false; } else { JS_SetGlobalJitCompilerOption( cx, JSJITCOMPILER_BASELINE_ENABLE, @@ -843,6 +849,9 @@ static void LoadStartupJSPrefs(XPCJSContext* xpccx) { JS_SetGlobalJitCompilerOption( cx, JSJITCOMPILER_NATIVE_REGEXP_ENABLE, StaticPrefs::javascript_options_native_regexp_DoNotUseDirectly()); + sSelfHostedUseSharedMemory = + StaticPrefs:: + javascript_options_self_hosted_use_shared_memory_DoNotUseDirectly(); } JS_SetOffthreadIonCompilationEnabled( @@ -1170,6 +1179,16 @@ bool DispatchOffThreadTask(js::UniquePtr task) { return true; } +static bool CreateSelfHostedSharedMemory(JSContext* aCx, + JS::SelfHostedCache aBuf) { + auto& shm = xpc::SelfHostedShmem::GetSingleton(); + MOZ_RELEASE_ASSERT(shm.Content().IsEmpty()); + // Failures within InitFromParent output warnings but do not cause + // unrecoverable failures. + shm.InitFromParent(aBuf); + return true; +} + nsresult XPCJSContext::Initialize() { SetHelperThreadTaskCallback(&DispatchOffThreadTask); @@ -1340,7 +1359,18 @@ nsresult XPCJSContext::Initialize() { NS_ABORT_OOM(0); // Size is unknown. } - if (!JS::InitSelfHostedCode(cx)) { + // When available, set the self-hosted shared memory to be read, so that we + // can decode the self-hosted content instead of parsing it. + auto& shm = xpc::SelfHostedShmem::GetSingleton(); + JS::SelfHostedCache selfHostedContent = shm.Content(); + JS::SelfHostedWriter writer = nullptr; + if (XRE_IsParentProcess() && sSelfHostedUseSharedMemory) { + // Only the Parent process has permissions to write to the self-hosted + // shared memory. + writer = CreateSelfHostedSharedMemory; + } + + if (!JS::InitSelfHostedCode(cx, selfHostedContent, writer)) { // Note: If no exception is pending, failure is due to OOM. if (!JS_IsExceptionPending(cx) || JS_IsThrowingOutOfMemory(cx)) { NS_ABORT_OOM(0); // Size is unknown. diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 09ac9169551a..b6483c42bb6e 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -5779,6 +5779,15 @@ value: false mirror: always +# Whether the Parent process allocates and shares memory with all content +# processes. This is mirrored once, as the parent process will do this +# allocation early on. +- name: javascript.options.self_hosted.use_shared_memory + type: bool + value: true + mirror: always # LoadStartupJSPrefs + do_not_use_directly: true + # Streams API. - name: javascript.options.streams type: RelaxedAtomicBool diff --git a/netwerk/base/ProxyAutoConfig.cpp b/netwerk/base/ProxyAutoConfig.cpp index 5736fb7b51a1..8c79b188a99f 100644 --- a/netwerk/base/ProxyAutoConfig.cpp +++ b/netwerk/base/ProxyAutoConfig.cpp @@ -17,6 +17,7 @@ #include "jsfriendapi.h" #include "js/CompilationAndEvaluation.h" // JS::Compile #include "js/ContextOptions.h" +#include "js/Initialization.h" #include "js/PropertySpec.h" #include "js/SourceText.h" // JS::Source{Ownership,Text} #include "js/Utility.h" @@ -34,6 +35,8 @@ # include "nsMacUtilsImpl.h" #endif +#include "XPCSelfHostedShmem.h" + namespace mozilla { namespace net { @@ -642,8 +645,15 @@ class JSContextWrapper { JS::SetWarningReporter(mContext, PACWarningReporter); - if (!JS::InitSelfHostedCode(mContext)) { - return NS_ERROR_OUT_OF_MEMORY; + // When available, set the self-hosted shared memory to be read, so that + // we can decode the self-hosted content instead of parsing it. + { + auto& shm = xpc::SelfHostedShmem::GetSingleton(); + JS::SelfHostedCache selfHostedContent = shm.Content(); + + if (!JS::InitSelfHostedCode(mContext, selfHostedContent)) { + return NS_ERROR_OUT_OF_MEMORY; + } } JS::RealmOptions options;