mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
Bug 961318 - Tweak off-main-thread parsing heuristic to avoid delaying execution when an atoms-zone GC is in progress (r=billm)
--HG-- extra : rebase_source : bd4e6b296e7a02dbe2370a515174dcd1a6a57ffa
This commit is contained in:
parent
745799819a
commit
82167b9620
@ -841,7 +841,7 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
|
||||
JS::CompileOptions options(cx);
|
||||
FillCompileOptionsForRequest(aRequest, global, &options);
|
||||
|
||||
if (!JS::CanCompileOffThread(cx, options)) {
|
||||
if (!JS::CanCompileOffThread(cx, options, aRequest->mScriptText.Length())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -2656,7 +2656,7 @@ nsXULPrototypeScript::Compile(const char16_t* aText,
|
||||
JS::ExposeObjectToActiveJS(scope);
|
||||
}
|
||||
|
||||
if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options)) {
|
||||
if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aTextLength)) {
|
||||
if (!JS::CompileOffThread(cx, scope, options,
|
||||
static_cast<const jschar*>(aText), aTextLength,
|
||||
OffThreadScriptReceiverCallback,
|
||||
|
@ -4442,8 +4442,22 @@ JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optio
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options)
|
||||
JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length)
|
||||
{
|
||||
static const unsigned TINY_LENGTH = 1000;
|
||||
static const unsigned HUGE_LENGTH = 100*1000;
|
||||
|
||||
// Compiling off the main thread inolves creating a new Zone and other
|
||||
// significant overheads. Don't bother if the script is tiny.
|
||||
if (length < TINY_LENGTH)
|
||||
return false;
|
||||
|
||||
// If the parsing task would have to wait for GC to complete, it'll probably
|
||||
// be faster to just start it synchronously on the main thread unless the
|
||||
// script is huge.
|
||||
if (OffThreadParsingMustWaitForGC(cx->runtime()) && length < HUGE_LENGTH)
|
||||
return false;
|
||||
|
||||
return cx->runtime()->canUseParallelParsing();
|
||||
}
|
||||
|
||||
@ -4452,7 +4466,7 @@ JS::CompileOffThread(JSContext *cx, Handle<JSObject*> obj, const ReadOnlyCompile
|
||||
const jschar *chars, size_t length,
|
||||
OffThreadCompileCallback callback, void *callbackData)
|
||||
{
|
||||
JS_ASSERT(CanCompileOffThread(cx, options));
|
||||
JS_ASSERT(CanCompileOffThread(cx, options, length));
|
||||
return StartOffThreadParseScript(cx, options, chars, length, obj, callback, callbackData);
|
||||
}
|
||||
|
||||
|
@ -3647,7 +3647,7 @@ extern JS_PUBLIC_API(JSScript *)
|
||||
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const char *filename);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options);
|
||||
CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length);
|
||||
|
||||
/*
|
||||
* Off thread compilation control flow.
|
||||
|
@ -229,6 +229,18 @@ ParseTask::~ParseTask()
|
||||
js_delete(errors[i]);
|
||||
}
|
||||
|
||||
bool
|
||||
js::OffThreadParsingMustWaitForGC(JSRuntime *rt)
|
||||
{
|
||||
// Off thread parsing can't occur during incremental collections on the
|
||||
// atoms compartment, to avoid triggering barriers. (Outside the atoms
|
||||
// compartment, the compilation will use a new zone that is never
|
||||
// collected.) If an atoms-zone GC is in progress, hold off on executing the
|
||||
// parse task until the atoms-zone GC completes (see
|
||||
// EnqueuePendingParseTasksAfterGC).
|
||||
return rt->activeGCInAtomsZone();
|
||||
}
|
||||
|
||||
bool
|
||||
js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &options,
|
||||
const jschar *chars, size_t length, HandleObject scopeChain,
|
||||
@ -299,13 +311,7 @@ js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &optio
|
||||
WorkerThreadState &state = *cx->runtime()->workerThreadState;
|
||||
JS_ASSERT(state.numThreads);
|
||||
|
||||
// Off thread parsing can't occur during incremental collections on the
|
||||
// atoms compartment, to avoid triggering barriers. (Outside the atoms
|
||||
// compartment, the compilation will use a new zone which doesn't require
|
||||
// barriers itself.) If an atoms-zone GC is in progress, hold off on
|
||||
// executing the parse task until the atoms-zone GC completes (see
|
||||
// EnqueuePendingParseTasksAfterGC).
|
||||
if (cx->runtime()->activeGCInAtomsZone()) {
|
||||
if (OffThreadParsingMustWaitForGC(cx->runtime())) {
|
||||
if (!state.parseWaitingOnGC.append(task.get()))
|
||||
return false;
|
||||
} else {
|
||||
@ -327,7 +333,7 @@ js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &optio
|
||||
void
|
||||
js::EnqueuePendingParseTasksAfterGC(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(!rt->activeGCInAtomsZone());
|
||||
JS_ASSERT(!OffThreadParsingMustWaitForGC(rt));
|
||||
|
||||
if (!rt->workerThreadState || rt->workerThreadState->parseWaitingOnGC.empty())
|
||||
return;
|
||||
|
@ -371,6 +371,11 @@ struct ParseTask
|
||||
~ParseTask();
|
||||
};
|
||||
|
||||
// Return whether, if a new parse task was started, it would need to wait for
|
||||
// an in-progress GC to complete before starting.
|
||||
extern bool
|
||||
OffThreadParsingMustWaitForGC(JSRuntime *rt);
|
||||
|
||||
// Compression tasks are allocated on the stack by their triggering thread,
|
||||
// which will block on the compression completing as the task goes out of scope
|
||||
// to ensure it completes at the required time.
|
||||
|
@ -3304,16 +3304,16 @@ OffThreadCompileScript(JSContext *cx, unsigned argc, jsval *vp)
|
||||
.setCompileAndGo(true)
|
||||
.setSourcePolicy(CompileOptions::SAVE_SOURCE);
|
||||
|
||||
if (!JS::CanCompileOffThread(cx, options)) {
|
||||
JS_ReportError(cx, "cannot compile code on worker thread");
|
||||
return false;
|
||||
}
|
||||
|
||||
const jschar *chars = JS_GetStringCharsZ(cx, scriptContents);
|
||||
if (!chars)
|
||||
return false;
|
||||
size_t length = JS_GetStringLength(scriptContents);
|
||||
|
||||
if (!JS::CanCompileOffThread(cx, options, length)) {
|
||||
JS_ReportError(cx, "cannot compile code on worker thread");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!offThreadState.startIfIdle(cx, scriptContents)) {
|
||||
JS_ReportError(cx, "called offThreadCompileScript without calling runOffThreadScript"
|
||||
" to receive prior off-thread compilation");
|
||||
|
Loading…
Reference in New Issue
Block a user