mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1286159 - Clean up FinishOffThread* APIs for off-thread parsing. r=jonco
This commit is contained in:
parent
d8b9227dbe
commit
0f65c9be84
@ -195,7 +195,7 @@ nsJSUtils::EvaluateString(JSContext* aCx,
|
||||
|
||||
if (ok && aOffThreadToken) {
|
||||
JS::Rooted<JSScript*>
|
||||
script(aCx, JS::FinishOffThreadScript(aCx, JS_GetRuntime(aCx), *aOffThreadToken));
|
||||
script(aCx, JS::FinishOffThreadScript(aCx, *aOffThreadToken));
|
||||
*aOffThreadToken = nullptr; // Mark the token as having been finished.
|
||||
if (script) {
|
||||
ok = JS_ExecuteScript(aCx, scopeChain, script);
|
||||
|
@ -708,8 +708,7 @@ nsScriptLoader::CreateModuleScript(nsModuleLoadRequest* aRequest)
|
||||
JS::Rooted<JSObject*> module(cx);
|
||||
|
||||
if (aRequest->mWasCompiledOMT) {
|
||||
module = JS::FinishOffThreadModule(cx, xpc::GetJSRuntime(),
|
||||
aRequest->mOffThreadToken);
|
||||
module = JS::FinishOffThreadModule(cx, aRequest->mOffThreadToken);
|
||||
aRequest->mOffThreadToken = nullptr;
|
||||
rv = module ? NS_OK : NS_ERROR_FAILURE;
|
||||
} else {
|
||||
@ -1829,7 +1828,8 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
|
||||
// (disappearing window, some other error, ...). Finish the
|
||||
// request to avoid leaks in the JS engine.
|
||||
MOZ_ASSERT(!aRequest->IsModuleRequest());
|
||||
JS::FinishOffThreadScript(nullptr, xpc::GetJSRuntime(), aRequest->mOffThreadToken);
|
||||
JSContext* cx = JS_GetContext(xpc::GetJSRuntime());
|
||||
JS::CancelOffThreadScript(cx, aRequest->mOffThreadToken);
|
||||
aRequest->mOffThreadToken = nullptr;
|
||||
}
|
||||
|
||||
|
@ -2768,7 +2768,7 @@ NotifyOffThreadScriptCompletedRunnable::Run()
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
script = JS::FinishOffThreadScript(cx, JS_GetRuntime(cx), mToken);
|
||||
script = JS::FinishOffThreadScript(cx, mToken);
|
||||
}
|
||||
|
||||
if (!sReceivers) {
|
||||
|
@ -4081,10 +4081,19 @@ JS::CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript*)
|
||||
JS::FinishOffThreadScript(JSContext* maybecx, JSRuntime* rt, void* token)
|
||||
JS::FinishOffThreadScript(JSContext* cx, void* token)
|
||||
{
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||
return HelperThreadState().finishScriptParseTask(maybecx, rt, token);
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx));
|
||||
return HelperThreadState().finishScriptParseTask(cx, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelOffThreadScript(JSContext* cx, void* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx));
|
||||
HelperThreadState().cancelParseTask(cx, ParseTaskKind::Script, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
@ -4097,10 +4106,19 @@ JS::CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
JS::FinishOffThreadModule(JSContext* maybecx, JSRuntime* rt, void* token)
|
||||
JS::FinishOffThreadModule(JSContext* cx, void* token)
|
||||
{
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||
return HelperThreadState().finishModuleParseTask(maybecx, rt, token);
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx));
|
||||
return HelperThreadState().finishModuleParseTask(cx, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelOffThreadModule(JSContext* cx, void* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx));
|
||||
HelperThreadState().cancelParseTask(cx, ParseTaskKind::Module, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
@ -4050,10 +4050,11 @@ CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t
|
||||
* After successfully triggering an off thread compile of a script, the
|
||||
* callback will eventually be invoked with the specified data and a token
|
||||
* for the compilation. The callback will be invoked while off the main thread,
|
||||
* so must ensure that its operations are thread safe. Afterwards,
|
||||
* FinishOffThreadScript must be invoked on the main thread to get the result
|
||||
* script or nullptr. If maybecx is not specified, the resources will be freed,
|
||||
* but no script will be returned.
|
||||
* so must ensure that its operations are thread safe. Afterwards, one of the
|
||||
* following functions must be invoked on the main thread:
|
||||
*
|
||||
* - FinishOffThreadScript, to get the result script (or nullptr on failure).
|
||||
* - CancelOffThreadScript, to free the resources without creating a script.
|
||||
*
|
||||
* The characters passed in to CompileOffThread must remain live until the
|
||||
* callback is invoked, and the resulting script will be rooted until the call
|
||||
@ -4066,7 +4067,10 @@ CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
OffThreadCompileCallback callback, void* callbackData);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript*)
|
||||
FinishOffThreadScript(JSContext* maybecx, JSRuntime* rt, void* token);
|
||||
FinishOffThreadScript(JSContext* cx, void* token);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
CancelOffThreadScript(JSContext* cx, void* token);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
@ -4074,7 +4078,10 @@ CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
OffThreadCompileCallback callback, void* callbackData);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
FinishOffThreadModule(JSContext* maybecx, JSRuntime* rt, void* token);
|
||||
FinishOffThreadModule(JSContext* cx, void* token);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
CancelOffThreadModule(JSContext* cx, void* token);
|
||||
|
||||
/**
|
||||
* Compile a function with scopeChain plus the global as its scope chain.
|
||||
|
@ -3928,8 +3928,7 @@ runOffThreadScript(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
JSRuntime* rt = cx->runtime();
|
||||
if (OffThreadParsingMustWaitForGC(rt))
|
||||
if (OffThreadParsingMustWaitForGC(cx))
|
||||
gc::FinishGC(cx);
|
||||
|
||||
void* token = offThreadState.waitUntilDone(cx, ScriptKind::Script);
|
||||
@ -3938,7 +3937,7 @@ runOffThreadScript(JSContext* cx, unsigned argc, Value* vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedScript script(cx, JS::FinishOffThreadScript(cx, rt, token));
|
||||
RootedScript script(cx, JS::FinishOffThreadScript(cx, token));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
@ -4014,8 +4013,7 @@ FinishOffThreadModule(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
JSRuntime* rt = cx->runtime();
|
||||
if (OffThreadParsingMustWaitForGC(rt))
|
||||
if (OffThreadParsingMustWaitForGC(cx))
|
||||
gc::FinishGC(cx);
|
||||
|
||||
void* token = offThreadState.waitUntilDone(cx, ScriptKind::Module);
|
||||
@ -4024,7 +4022,7 @@ FinishOffThreadModule(JSContext* cx, unsigned argc, Value* vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject module(cx, JS::FinishOffThreadModule(cx, rt, token));
|
||||
RootedObject module(cx, JS::FinishOffThreadModule(cx, token));
|
||||
if (!module)
|
||||
return false;
|
||||
|
||||
|
@ -346,8 +346,7 @@ js::CancelOffThreadParses(JSRuntime* rt)
|
||||
if (task->runtimeMatches(rt)) {
|
||||
found = true;
|
||||
AutoUnlockHelperThreadState unlock(lock);
|
||||
HelperThreadState().finishParseTask(/* maybecx = */ nullptr, rt, task->kind,
|
||||
task);
|
||||
HelperThreadState().cancelParseTask(rt->contextFromMainThread(), task->kind, task);
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
@ -1119,41 +1118,40 @@ LeaveParseTaskZone(JSRuntime* rt, ParseTask* task)
|
||||
rt->clearUsedByExclusiveThread(task->cx->zone());
|
||||
}
|
||||
|
||||
JSScript*
|
||||
GlobalHelperThreadState::finishParseTask(JSContext* maybecx, JSRuntime* rt, ParseTaskKind kind,
|
||||
void* token)
|
||||
ParseTask*
|
||||
GlobalHelperThreadState::removeFinishedParseTask(ParseTaskKind kind, void* token)
|
||||
{
|
||||
ScopedJSDeletePtr<ParseTask> parseTask;
|
||||
|
||||
// The token is a ParseTask* which should be in the finished list.
|
||||
// Find and remove its entry.
|
||||
{
|
||||
AutoLockHelperThreadState lock;
|
||||
ParseTaskVector& finished = parseFinishedList();
|
||||
for (size_t i = 0; i < finished.length(); i++) {
|
||||
if (finished[i] == token) {
|
||||
parseTask = finished[i];
|
||||
remove(finished, &i);
|
||||
break;
|
||||
}
|
||||
|
||||
AutoLockHelperThreadState lock;
|
||||
ParseTaskVector& finished = parseFinishedList();
|
||||
|
||||
for (size_t i = 0; i < finished.length(); i++) {
|
||||
if (finished[i] == token) {
|
||||
ParseTask* parseTask = finished[i];
|
||||
remove(finished, &i);
|
||||
MOZ_ASSERT(parseTask);
|
||||
MOZ_ASSERT(parseTask->kind == kind);
|
||||
return parseTask;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(parseTask);
|
||||
MOZ_ASSERT(parseTask->kind == kind);
|
||||
|
||||
if (!maybecx) {
|
||||
LeaveParseTaskZone(rt, parseTask);
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_CRASH("Invalid ParseTask token");
|
||||
}
|
||||
|
||||
JSContext* cx = maybecx;
|
||||
JSScript*
|
||||
GlobalHelperThreadState::finishParseTask(JSContext* cx, ParseTaskKind kind, void* token)
|
||||
{
|
||||
MOZ_ASSERT(cx->compartment());
|
||||
|
||||
ScopedJSDeletePtr<ParseTask> parseTask(removeFinishedParseTask(kind, token));
|
||||
|
||||
// Make sure we have all the constructors we need for the prototype
|
||||
// remapping below, since we can't GC while that's happening.
|
||||
Rooted<GlobalObject*> global(cx, &cx->global()->as<GlobalObject>());
|
||||
if (!EnsureParserCreatedClasses(cx, kind)) {
|
||||
LeaveParseTaskZone(rt, parseTask);
|
||||
LeaveParseTaskZone(cx, parseTask);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1162,7 +1160,7 @@ GlobalHelperThreadState::finishParseTask(JSContext* maybecx, JSRuntime* rt, Pars
|
||||
if (!parseTask->finish(cx))
|
||||
return nullptr;
|
||||
|
||||
RootedScript script(rt, parseTask->script);
|
||||
RootedScript script(cx, parseTask->script);
|
||||
releaseAssertSameCompartment(cx, script);
|
||||
|
||||
// Report out of memory errors eagerly, or errors could be malformed.
|
||||
@ -1194,25 +1192,22 @@ GlobalHelperThreadState::finishParseTask(JSContext* maybecx, JSRuntime* rt, Pars
|
||||
}
|
||||
|
||||
JSScript*
|
||||
GlobalHelperThreadState::finishScriptParseTask(JSContext* maybecx, JSRuntime* rt, void* token)
|
||||
GlobalHelperThreadState::finishScriptParseTask(JSContext* cx, void* token)
|
||||
{
|
||||
JSScript* script = finishParseTask(maybecx, rt, ParseTaskKind::Script, token);
|
||||
JSScript* script = finishParseTask(cx, ParseTaskKind::Script, token);
|
||||
MOZ_ASSERT_IF(script, script->isGlobalCode());
|
||||
return script;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
GlobalHelperThreadState::finishModuleParseTask(JSContext* maybecx, JSRuntime* rt, void* token)
|
||||
GlobalHelperThreadState::finishModuleParseTask(JSContext* cx, void* token)
|
||||
{
|
||||
JSScript* script = finishParseTask(maybecx, rt, ParseTaskKind::Module, token);
|
||||
JSScript* script = finishParseTask(cx, ParseTaskKind::Module, token);
|
||||
if (!script)
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(script->module());
|
||||
if (!maybecx)
|
||||
return nullptr;
|
||||
|
||||
JSContext* cx = maybecx;
|
||||
RootedModuleObject module(cx, script->module());
|
||||
module->fixScopesAfterCompartmentMerge(cx);
|
||||
if (!ModuleObject::Freeze(cx, module))
|
||||
@ -1221,6 +1216,13 @@ GlobalHelperThreadState::finishModuleParseTask(JSContext* maybecx, JSRuntime* rt
|
||||
return module;
|
||||
}
|
||||
|
||||
void
|
||||
GlobalHelperThreadState::cancelParseTask(JSContext* cx, ParseTaskKind kind, void* token)
|
||||
{
|
||||
ScopedJSDeletePtr<ParseTask> parseTask(removeFinishedParseTask(kind, token));
|
||||
LeaveParseTaskZone(cx, parseTask);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
GlobalObject::getStarGeneratorFunctionPrototype()
|
||||
{
|
||||
|
@ -101,6 +101,8 @@ class GlobalHelperThreadState
|
||||
// GC tasks needing to be done in parallel.
|
||||
GCParallelTaskVector gcParallelWorklist_;
|
||||
|
||||
ParseTask* removeFinishedParseTask(ParseTaskKind kind, void* token);
|
||||
|
||||
public:
|
||||
size_t maxIonCompilationThreads() const;
|
||||
size_t maxUnpausedIonCompilationThreads() const;
|
||||
@ -225,7 +227,9 @@ class GlobalHelperThreadState
|
||||
return bool(numWasmFailedJobs);
|
||||
}
|
||||
|
||||
JSScript* finishParseTask(JSContext* maybecx, JSRuntime* rt, ParseTaskKind kind, void* token);
|
||||
JSScript* finishParseTask(JSContext* cx, ParseTaskKind kind, void* token);
|
||||
void cancelParseTask(JSContext* cx, ParseTaskKind kind, void* token);
|
||||
|
||||
void mergeParseTaskCompartment(JSContext* cx, ParseTask* parseTask,
|
||||
Handle<GlobalObject*> global,
|
||||
JSCompartment* dest);
|
||||
@ -238,8 +242,8 @@ class GlobalHelperThreadState
|
||||
uint32_t numWasmFailedJobs;
|
||||
|
||||
public:
|
||||
JSScript* finishScriptParseTask(JSContext* maybecx, JSRuntime* rt, void* token);
|
||||
JSObject* finishModuleParseTask(JSContext* maybecx, JSRuntime* rt, void* token);
|
||||
JSScript* finishScriptParseTask(JSContext* cx, void* token);
|
||||
JSObject* finishModuleParseTask(JSContext* cx, void* token);
|
||||
bool compressionInProgress(SourceCompressionTask* task);
|
||||
SourceCompressionTask* compressionTaskForSource(ScriptSource* ss);
|
||||
|
||||
|
@ -776,9 +776,9 @@ NotifyPrecompilationCompleteRunnable::Run(void)
|
||||
AutoSendObserverNotification notifier(mPrecompiler);
|
||||
|
||||
if (mToken) {
|
||||
JSRuntime* rt = XPCJSRuntime::Get()->Runtime();
|
||||
NS_ENSURE_TRUE(rt, NS_ERROR_FAILURE);
|
||||
JS::FinishOffThreadScript(nullptr, rt, mToken);
|
||||
JSContext* cx = XPCJSRuntime::Get()->Context();
|
||||
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
|
||||
JS::CancelOffThreadScript(cx, mToken);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
Loading…
Reference in New Issue
Block a user