--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -299,31 +299,33 @@ static const JSClass parseTaskGlobalClas
ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal,
const char16_t* chars, size_t length,
JS::OffThreadCompileCallback callback, void* callbackData)
: kind(kind), options(cx), data(AsVariant(TwoByteChars(chars, length))),
alloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
parseGlobal(parseGlobal),
callback(callback), callbackData(callbackData),
- script(nullptr), sourceObject(nullptr),
overRecursed(false), outOfMemory(false)
{
+ Unused << scripts.reserve(scripts.capacity());
+ Unused << sourceObjects.reserve(sourceObjects.capacity());
}
ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal,
const JS::TranscodeRange& range,
JS::OffThreadCompileCallback callback, void* callbackData)
: kind(kind), options(cx), data(AsVariant(range)),
alloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
parseGlobal(parseGlobal),
callback(callback), callbackData(callbackData),
- script(nullptr), sourceObject(nullptr),
overRecursed(false), outOfMemory(false)
{
+ Unused << scripts.reserve(scripts.capacity());
+ Unused << sourceObjects.reserve(sourceObjects.capacity());
}
bool
ParseTask::init(JSContext* cx, const ReadOnlyCompileOptions& options)
{
if (!this->options.copy(cx, options))
return false;
@@ -334,17 +336,17 @@ void
ParseTask::activate(JSRuntime* rt)
{
rt->setUsedByHelperThread(parseGlobal->zone());
}
bool
ParseTask::finish(JSContext* cx)
{
- if (sourceObject) {
+ for (auto& sourceObject : sourceObjects) {
RootedScriptSource sso(cx, sourceObject);
if (!ScriptSourceObject::initFromOptions(cx, sso, options))
return false;
if (!sso->source()->tryCompressOffThread(cx))
return false;
}
return true;
@@ -363,78 +365,91 @@ ParseTask::trace(JSTracer* trc)
return;
Zone* zone = MaybeForwarded(parseGlobal)->zoneFromAnyThread();
if (zone->usedByHelperThread()) {
MOZ_ASSERT(!zone->isCollecting());
return;
}
TraceManuallyBarrieredEdge(trc, &parseGlobal, "ParseTask::parseGlobal");
- if (script)
- TraceManuallyBarrieredEdge(trc, &script, "ParseTask::script");
- if (sourceObject)
- TraceManuallyBarrieredEdge(trc, &sourceObject, "ParseTask::sourceObject");
+ for (auto& script : scripts)
+ TraceManuallyBarrieredEdge(trc, &script, "ParseTask::scripts[]");
+ for (auto& sourceObject : sourceObjects)
+ TraceManuallyBarrieredEdge(trc, &sourceObject, "ParseTask::sourceObjects[]");
}
ScriptParseTask::ScriptParseTask(JSContext* cx, JSObject* parseGlobal,
const char16_t* chars, size_t length,
JS::OffThreadCompileCallback callback, void* callbackData)
: ParseTask(ParseTaskKind::Script, cx, parseGlobal, chars, length, callback,
callbackData)
{
}
void
ScriptParseTask::parse(JSContext* cx)
{
auto& range = data.as<TwoByteChars>();
SourceBufferHolder srcBuf(range.begin().get(), range.length(), SourceBufferHolder::NoOwnership);
- script = frontend::CompileGlobalScript(cx, alloc, ScopeKind::Global,
- options, srcBuf,
- /* sourceObjectOut = */ &sourceObject);
+ Rooted<ScriptSourceObject*> sourceObject(cx);
+
+ JSScript* script = frontend::CompileGlobalScript(cx, alloc, ScopeKind::Global,
+ options, srcBuf,
+ /* sourceObjectOut = */ &sourceObject.get());
+ if (script)
+ scripts.infallibleAppend(script);
+ if (sourceObject)
+ sourceObjects.infallibleAppend(sourceObject);
}
ModuleParseTask::ModuleParseTask(JSContext* cx, JSObject* parseGlobal,
const char16_t* chars, size_t length,
JS::OffThreadCompileCallback callback, void* callbackData)
: ParseTask(ParseTaskKind::Module, cx, parseGlobal, chars, length, callback,
callbackData)
{
}
void
ModuleParseTask::parse(JSContext* cx)
{
auto& range = data.as<TwoByteChars>();
SourceBufferHolder srcBuf(range.begin().get(), range.length(), SourceBufferHolder::NoOwnership);
- ModuleObject* module = frontend::CompileModule(cx, options, srcBuf, alloc, &sourceObject);
- if (module)
- script = module->script();
+ Rooted<ScriptSourceObject*> sourceObject(cx);
+
+ ModuleObject* module = frontend::CompileModule(cx, options, srcBuf, alloc, &sourceObject.get());
+ if (module) {
+ scripts.infallibleAppend(module->script());
+ if (sourceObject)
+ sourceObjects.infallibleAppend(sourceObject);
+ }
}
ScriptDecodeTask::ScriptDecodeTask(JSContext* cx, JSObject* parseGlobal,
const JS::TranscodeRange& range,
JS::OffThreadCompileCallback callback, void* callbackData)
: ParseTask(ParseTaskKind::ScriptDecode, cx, parseGlobal,
range, callback, callbackData)
{
}
void
ScriptDecodeTask::parse(JSContext* cx)
{
RootedScript resultScript(cx);
- XDROffThreadDecoder decoder(cx, alloc, &options, /* sourceObjectOut = */ &sourceObject,
+ Rooted<ScriptSourceObject*> sourceObject(cx);
+
+ XDROffThreadDecoder decoder(cx, alloc, &options, /* sourceObjectOut = */ &sourceObject.get(),
data.as<const JS::TranscodeRange>());
decoder.codeScript(&resultScript);
MOZ_ASSERT(bool(resultScript) == (decoder.resultCode() == JS::TranscodeResult_Ok));
if (decoder.resultCode() == JS::TranscodeResult_Ok) {
- script = resultScript.get();
- } else {
- sourceObject = nullptr;
+ scripts.infallibleAppend(resultScript);
+ if (sourceObject)
+ sourceObjects.infallibleAppend(sourceObject);
}
}
void
js::CancelOffThreadParses(JSRuntime* rt)
{
AutoLockHelperThreadState lock;
@@ -1310,18 +1325,24 @@ GlobalHelperThreadState::finishParseTask
Rooted<GlobalObject*> global(cx, &cx->global()->as<GlobalObject>());
if (!EnsureParserCreatedClasses(cx, kind)) {
LeaveParseTaskZone(cx->runtime(), parseTask);
return nullptr;
}
mergeParseTaskCompartment(cx, parseTask, global, cx->compartment());
- RootedScript script(cx, parseTask->script);
- releaseAssertSameCompartment(cx, script);
+ MOZ_RELEASE_ASSERT(parseTask->scripts.length() <= 1);
+
+ JS::RootedScript script(cx);
+ if (parseTask->scripts.length() > 0)
+ script = parseTask->scripts[0];
+
+ for (auto& script : parseTask->scripts)
+ releaseAssertSameCompartment(cx, script);
if (!parseTask->finish(cx))
return nullptr;
// Report out of memory errors eagerly, or errors could be malformed.
if (parseTask->outOfMemory) {
ReportOutOfMemory(cx);
return nullptr;