Bug 1724236 - Move stencil duplication out of JoinOffThread, Decode, Compile r=arai

In InstantiateClassicScriptFromMaybeEncodedSource(), I need to use a local
ErrorResult because calling `aRv.NoteJSContextException(aCx)` must be followed
by an immediate return, but that would avoid adding the compile time to
mMainThreadParseTime.

Differential Revision: https://phabricator.services.mozilla.com/D222301
This commit is contained in:
Bryan Thrall
2024-10-30 13:41:43 +00:00
parent 38fb4a0034
commit b9d1574361
4 changed files with 45 additions and 44 deletions

View File

@@ -99,15 +99,6 @@ void JSExecutionContext::JoinOffThread(JSContext* aCx,
aRv.NoteJSContextException(aCx); aRv.NoteJSContextException(aCx);
return; return;
} }
if (mKeepStencil) {
mStencil = JS::DuplicateStencil(aCx, aStencil.get());
if (!mStencil) {
mSkip = true;
aRv.NoteJSContextException(aCx);
return;
}
}
} }
template <typename Unit> template <typename Unit>
@@ -126,15 +117,6 @@ void JSExecutionContext::InternalCompile(JSContext* aCx,
aRv.NoteJSContextException(aCx); aRv.NoteJSContextException(aCx);
return; return;
} }
if (mKeepStencil) {
mStencil = JS::DuplicateStencil(aCx, aStencil.get());
if (!mStencil) {
mSkip = true;
aRv.NoteJSContextException(aCx);
return;
}
}
} }
void JSExecutionContext::Compile(JSContext* aCx, void JSExecutionContext::Compile(JSContext* aCx,
@@ -194,15 +176,6 @@ void JSExecutionContext::Decode(JSContext* aCx,
aRv = NS_ERROR_DOM_JS_DECODING_ERROR; aRv = NS_ERROR_DOM_JS_DECODING_ERROR;
return; return;
} }
if (mKeepStencil) {
mStencil = JS::DuplicateStencil(aCx, aStencil.get());
if (!mStencil) {
mSkip = true;
aRv.NoteJSContextException(aCx);
return;
}
}
} }
void JSExecutionContext::InstantiateStencil( void JSExecutionContext::InstantiateStencil(

View File

@@ -43,14 +43,10 @@ class MOZ_STACK_CLASS JSExecutionContext final {
JS::Rooted<JS::Value> mDebuggerPrivateValue; JS::Rooted<JS::Value> mDebuggerPrivateValue;
JS::Rooted<JSScript*> mDebuggerIntroductionScript; JS::Rooted<JSScript*> mDebuggerIntroductionScript;
RefPtr<JS::Stencil> mStencil;
// Used to skip upcoming phases in case of a failure. In such case the // Used to skip upcoming phases in case of a failure. In such case the
// result is carried by mRv. // result is carried by mRv.
bool mSkip; bool mSkip;
bool mKeepStencil = false;
private: private:
// Compile a script contained in a SourceText. // Compile a script contained in a SourceText.
template <typename Unit> template <typename Unit>
@@ -82,9 +78,6 @@ class MOZ_STACK_CLASS JSExecutionContext final {
// MOZ_ASSERT_IF(mEncodeBytecode && mScript && mRv == NS_OK, mScriptUsed); // MOZ_ASSERT_IF(mEncodeBytecode && mScript && mRv == NS_OK, mScriptUsed);
} }
void SetKeepStencil() { mKeepStencil = true; }
already_AddRefed<JS::Stencil> StealStencil() { return mStencil.forget(); }
// After getting a notification that an off-thread compile/decode finished, // After getting a notification that an off-thread compile/decode finished,
// this function will take the result of the off-thread operation and move it // this function will take the result of the off-thread operation and move it
// to the main thread. // to the main thread.

View File

@@ -2724,7 +2724,8 @@ nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) {
void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource( void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource(
JSContext* aCx, JSExecutionContext& aExec, JSContext* aCx, JSExecutionContext& aExec,
JS::CompileOptions& aCompileOptions, ScriptLoadRequest* aRequest, JS::CompileOptions& aCompileOptions, ScriptLoadRequest* aRequest,
JS::MutableHandle<JSScript*> aScript, ErrorResult& aRv) { JS::MutableHandle<JSScript*> aScript, bool aKeepStencil,
RefPtr<JS::Stencil>& aStencilDup, ErrorResult& aRv) {
nsAutoCString profilerLabelString; nsAutoCString profilerLabelString;
aRequest->GetScriptLoadContext()->GetProfilerLabel(profilerLabelString); aRequest->GetScriptLoadContext()->GetProfilerLabel(profilerLabelString);
@@ -2737,6 +2738,13 @@ void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource(
aExec.JoinOffThread(aCx, aCompileOptions, aExec.JoinOffThread(aCx, aCompileOptions,
aRequest->GetScriptLoadContext(), stencil, storage, aRequest->GetScriptLoadContext(), stencil, storage,
aRv); aRv);
if (!aRv.Failed() && aKeepStencil) {
aStencilDup = JS::DuplicateStencil(aCx, stencil.get());
if (!aStencilDup) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (stencil) { if (stencil) {
bool unused; bool unused;
aExec.InstantiateStencil(aCx, aCompileOptions, std::move(stencil), aExec.InstantiateStencil(aCx, aCompileOptions, std::move(stencil),
@@ -2750,6 +2758,14 @@ void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource(
RefPtr<JS::Stencil> stencil; RefPtr<JS::Stencil> stencil;
aExec.Decode(aCx, aCompileOptions, aRequest->Bytecode(), stencil, aRv); aExec.Decode(aCx, aCompileOptions, aRequest->Bytecode(), stencil, aRv);
if (!aRv.Failed() && aKeepStencil) {
aStencilDup = JS::DuplicateStencil(aCx, stencil.get());
if (!aStencilDup) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (stencil) { if (stencil) {
bool unused; bool unused;
aExec.InstantiateStencil(aCx, aCompileOptions, std::move(stencil), aExec.InstantiateStencil(aCx, aCompileOptions, std::move(stencil),
@@ -2778,6 +2794,13 @@ void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource(
JS::InstantiationStorage storage; JS::InstantiationStorage storage;
aExec.JoinOffThread(aCx, aCompileOptions, aRequest->GetScriptLoadContext(), aExec.JoinOffThread(aCx, aCompileOptions, aRequest->GetScriptLoadContext(),
stencil, storage, aRv); stencil, storage, aRv);
if (!aRv.Failed() && aKeepStencil) {
aStencilDup = JS::DuplicateStencil(aCx, stencil.get());
if (!aStencilDup) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (stencil) { if (stencil) {
bool unused; bool unused;
aExec.InstantiateStencil(aCx, aCompileOptions, std::move(stencil), aExec.InstantiateStencil(aCx, aCompileOptions, std::move(stencil),
@@ -2796,20 +2819,29 @@ void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource(
profilerLabelString); profilerLabelString);
RefPtr<JS::Stencil> stencil; RefPtr<JS::Stencil> stencil;
ErrorResult erv;
auto compile = [&](auto& source) { auto compile = [&](auto& source) {
aExec.Compile(aCx, aCompileOptions, source, stencil, aRv); aExec.Compile(aCx, aCompileOptions, source, stencil, erv);
}; };
MOZ_ASSERT(!maybeSource.empty()); MOZ_ASSERT(!maybeSource.empty());
TimeStamp startTime = TimeStamp::Now(); TimeStamp startTime = TimeStamp::Now();
maybeSource.mapNonEmpty(compile); maybeSource.mapNonEmpty(compile);
if (!erv.Failed() && aKeepStencil) {
aStencilDup = JS::DuplicateStencil(aCx, stencil.get());
if (!aStencilDup) {
erv.NoteJSContextException(aCx);
}
}
if (stencil) { if (stencil) {
bool unused; bool unused;
aExec.InstantiateStencil(aCx, aCompileOptions, std::move(stencil), aExec.InstantiateStencil(aCx, aCompileOptions, std::move(stencil),
aScript, unused, aRv); aScript, unused, erv);
} }
mMainThreadParseTime += TimeStamp::Now() - startTime; mMainThreadParseTime += TimeStamp::Now() - startTime;
aRv = std::move(erv);
} }
} }
} }
@@ -2856,18 +2888,17 @@ void ScriptLoader::InstantiateClassicScriptFromAny(
// NOTE: Avoid creating cache regardless of CSP. // NOTE: Avoid creating cache regardless of CSP.
createCache = false; createCache = false;
} }
if (createCache) {
aExec.SetKeepStencil();
}
} }
RefPtr<JS::Stencil> stencilDup;
InstantiateClassicScriptFromMaybeEncodedSource(aCx, aExec, aCompileOptions, InstantiateClassicScriptFromMaybeEncodedSource(aCx, aExec, aCompileOptions,
aRequest, aScript, aRv); aRequest, aScript, createCache,
stencilDup, aRv);
if (!aRv.Failed()) { if (!aRv.Failed()) {
if (createCache) { if (createCache) {
MOZ_ASSERT(mCache); MOZ_ASSERT(mCache);
aRequest->SetStencil(aExec.StealStencil()); MOZ_ASSERT(stencilDup);
aRequest->SetStencil(stencilDup.forget());
auto loadData = MakeRefPtr<ScriptLoadData>(this, aRequest); auto loadData = MakeRefPtr<ScriptLoadData>(this, aRequest);
mCache->Insert(*loadData); mCache->Insert(*loadData);
} }

View File

@@ -648,10 +648,14 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface {
// Instantiate classic script from one of the following data: // Instantiate classic script from one of the following data:
// * text source // * text source
// * encoded bytecode // * encoded bytecode
//
// If keepStencil is true and this function is successful, aStencilDup will
// contain a copy of the compiled stencil for use by the caller.
void InstantiateClassicScriptFromMaybeEncodedSource( void InstantiateClassicScriptFromMaybeEncodedSource(
JSContext* aCx, JSExecutionContext& aExec, JSContext* aCx, JSExecutionContext& aExec,
JS::CompileOptions& aCompileOptions, ScriptLoadRequest* aRequest, JS::CompileOptions& aCompileOptions, ScriptLoadRequest* aRequest,
JS::MutableHandle<JSScript*> aScript, ErrorResult& aRv); JS::MutableHandle<JSScript*> aScript, bool keepStencil,
RefPtr<JS::Stencil>& aStencilDup, ErrorResult& aRv);
// Instantiate classic script from the following data: // Instantiate classic script from the following data:
// * cached stencil // * cached stencil