зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 428f1770d076 (bug 1357012) for Assertion failure: missing call to js::ReportOutOfMemory()
This commit is contained in:
Родитель
981bde9d05
Коммит
37eb3d6689
|
@ -57,6 +57,7 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
JSScript* compileScript(HandleObject environment, SharedContext* sc);
|
||||
bool checkLength();
|
||||
bool createScriptSource(const Maybe<uint32_t>& parameterListEnd);
|
||||
bool enqueueOffThreadSourceCompression();
|
||||
bool canLazilyParse();
|
||||
bool createParser();
|
||||
bool createSourceAndParser(const Maybe<uint32_t>& parameterListEnd = Nothing());
|
||||
|
@ -82,6 +83,7 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
|
||||
RootedScriptSource sourceObject;
|
||||
ScriptSource* scriptSource;
|
||||
SourceCompressionTask* sourceCompressionTask_;
|
||||
|
||||
Maybe<UsedNameTracker> usedNames;
|
||||
Maybe<Parser<SyntaxParseHandler>> syntaxParser;
|
||||
|
@ -171,6 +173,7 @@ BytecodeCompiler::BytecodeCompiler(JSContext* cx,
|
|||
enclosingScope(cx, enclosingScope),
|
||||
sourceObject(cx),
|
||||
scriptSource(nullptr),
|
||||
sourceCompressionTask_(nullptr),
|
||||
directives(options.strictOption),
|
||||
startPosition(keepAtoms),
|
||||
script(cx)
|
||||
|
@ -216,6 +219,40 @@ BytecodeCompiler::createScriptSource(const Maybe<uint32_t>& parameterListEnd)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::enqueueOffThreadSourceCompression()
|
||||
{
|
||||
// There are several cases where source compression is not a good idea:
|
||||
// - If the script is tiny, then compression will save little or no space.
|
||||
// - If there is only one core, then compression will contend with JS
|
||||
// execution (which hurts benchmarketing).
|
||||
//
|
||||
// Otherwise, enqueue a compression task to be processed when a major
|
||||
// GC is requested.
|
||||
|
||||
if (!scriptSource->hasUncompressedSource())
|
||||
return true;
|
||||
|
||||
bool canCompressOffThread =
|
||||
HelperThreadState().cpuCount > 1 &&
|
||||
HelperThreadState().threadCount >= 2 &&
|
||||
CanUseExtraThreads();
|
||||
const size_t TINY_SCRIPT = 256;
|
||||
if (TINY_SCRIPT <= sourceBuffer.length() && canCompressOffThread) {
|
||||
// Heap allocate the task. It will be freed upon compression
|
||||
// completing in AttachFinishedCompressedSources.
|
||||
SourceCompressionTask* task = cx->new_<SourceCompressionTask>(cx->runtime(),
|
||||
scriptSource);
|
||||
if (!task)
|
||||
return false;
|
||||
if (!EnqueueOffThreadCompression(cx, task))
|
||||
return false;
|
||||
sourceCompressionTask_ = task;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::canLazilyParse()
|
||||
{
|
||||
|
@ -379,7 +416,7 @@ BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
|
|||
script->scriptSource()->recordParseEnded();
|
||||
|
||||
// Enqueue an off-thread source compression task after finishing parsing.
|
||||
if (!scriptSource->tryCompressOffThread(cx))
|
||||
if (!enqueueOffThreadSourceCompression())
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
|
||||
|
@ -444,7 +481,7 @@ BytecodeCompiler::compileModule()
|
|||
module->setInitialEnvironment(env);
|
||||
|
||||
// Enqueue an off-thread source compression task after finishing parsing.
|
||||
if (!scriptSource->tryCompressOffThread(cx))
|
||||
if (!enqueueOffThreadSourceCompression())
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
|
||||
|
@ -500,7 +537,7 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
|||
return false;
|
||||
|
||||
// Enqueue an off-thread source compression task after finishing parsing.
|
||||
if (!scriptSource->tryCompressOffThread(cx))
|
||||
if (!enqueueOffThreadSourceCompression())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -512,6 +549,12 @@ BytecodeCompiler::sourceObjectPtr() const
|
|||
return sourceObject.get();
|
||||
}
|
||||
|
||||
SourceCompressionTask*
|
||||
BytecodeCompiler::sourceCompressionTask() const
|
||||
{
|
||||
return sourceCompressionTask_;
|
||||
}
|
||||
|
||||
ScriptSourceObject*
|
||||
frontend::CreateScriptSourceObject(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const Maybe<uint32_t>& parameterListEnd /* = Nothing() */)
|
||||
|
@ -563,17 +606,22 @@ class MOZ_STACK_CLASS AutoInitializeSourceObject
|
|||
{
|
||||
BytecodeCompiler& compiler_;
|
||||
ScriptSourceObject** sourceObjectOut_;
|
||||
SourceCompressionTask** sourceCompressionTaskOut_;
|
||||
|
||||
public:
|
||||
AutoInitializeSourceObject(BytecodeCompiler& compiler,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
ScriptSourceObject** sourceObjectOut,
|
||||
SourceCompressionTask** sourceCompressionTaskOut)
|
||||
: compiler_(compiler),
|
||||
sourceObjectOut_(sourceObjectOut)
|
||||
sourceObjectOut_(sourceObjectOut),
|
||||
sourceCompressionTaskOut_(sourceCompressionTaskOut)
|
||||
{ }
|
||||
|
||||
~AutoInitializeSourceObject() {
|
||||
if (sourceObjectOut_)
|
||||
*sourceObjectOut_ = compiler_.sourceObjectPtr();
|
||||
if (sourceCompressionTaskOut_)
|
||||
*sourceCompressionTaskOut_ = compiler_.sourceCompressionTask();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -581,11 +629,12 @@ JSScript*
|
|||
frontend::CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
ScriptSourceObject** sourceObjectOut,
|
||||
SourceCompressionTask** sourceCompressionTaskOut)
|
||||
{
|
||||
MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, /* enclosingScope = */ nullptr);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut, sourceCompressionTaskOut);
|
||||
return compiler.compileGlobalScript(scopeKind);
|
||||
}
|
||||
|
||||
|
@ -594,17 +643,19 @@ frontend::CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
|
|||
HandleObject environment, HandleScope enclosingScope,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
ScriptSourceObject** sourceObjectOut,
|
||||
SourceCompressionTask** sourceCompressionTaskOut)
|
||||
{
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, enclosingScope);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut, sourceCompressionTaskOut);
|
||||
return compiler.compileEvalScript(environment, enclosingScope);
|
||||
}
|
||||
|
||||
ModuleObject*
|
||||
frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInput,
|
||||
SourceBufferHolder& srcBuf, LifoAlloc& alloc,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
ScriptSourceObject** sourceObjectOut,
|
||||
SourceCompressionTask** sourceCompressionTaskOut)
|
||||
{
|
||||
MOZ_ASSERT(srcBuf.get());
|
||||
MOZ_ASSERT_IF(sourceObjectOut, *sourceObjectOut == nullptr);
|
||||
|
@ -616,7 +667,7 @@ frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInpu
|
|||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, emptyGlobalScope);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut, sourceCompressionTaskOut);
|
||||
return compiler.compileModule();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ class LazyScript;
|
|||
class LifoAlloc;
|
||||
class ModuleObject;
|
||||
class ScriptSourceObject;
|
||||
class SourceCompressionTask;
|
||||
|
||||
namespace frontend {
|
||||
|
||||
|
@ -34,14 +35,16 @@ JSScript*
|
|||
CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
ScriptSourceObject** sourceObjectOut = nullptr,
|
||||
SourceCompressionTask** sourceCompressionTaskOut = nullptr);
|
||||
|
||||
JSScript*
|
||||
CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
|
||||
HandleObject scopeChain, HandleScope enclosingScope,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
ScriptSourceObject** sourceObjectOut = nullptr,
|
||||
SourceCompressionTask** sourceCompressionTaskOut = nullptr);
|
||||
|
||||
ModuleObject*
|
||||
CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
|
@ -50,7 +53,8 @@ CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|||
ModuleObject*
|
||||
CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, LifoAlloc& alloc,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
ScriptSourceObject** sourceObjectOut = nullptr,
|
||||
SourceCompressionTask** sourceCompressionTaskOut = nullptr);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);
|
||||
|
|
|
@ -5053,18 +5053,22 @@ SweepCompressionTasksTask::run()
|
|||
// Attach finished compression tasks.
|
||||
auto& finished = HelperThreadState().compressionFinishedList(lock);
|
||||
for (size_t i = 0; i < finished.length(); i++) {
|
||||
if (finished[i]->runtimeMatches(runtime())) {
|
||||
UniquePtr<SourceCompressionTask> task(Move(finished[i]));
|
||||
SourceCompressionTask* task = finished[i];
|
||||
if (task->runtimeMatches(runtime())) {
|
||||
HelperThreadState().remove(finished, &i);
|
||||
task->complete();
|
||||
js_delete(task);
|
||||
}
|
||||
}
|
||||
|
||||
// Sweep pending tasks that are holding onto should-be-dead ScriptSources.
|
||||
auto& pending = HelperThreadState().compressionPendingList(lock);
|
||||
for (size_t i = 0; i < pending.length(); i++) {
|
||||
if (pending[i]->shouldCancel())
|
||||
SourceCompressionTask* task = pending[i];
|
||||
if (task->shouldCancel()) {
|
||||
HelperThreadState().remove(pending, &i);
|
||||
js_delete(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1821,48 +1821,6 @@ ScriptSource::setSource(SharedImmutableTwoByteString&& string)
|
|||
data = SourceType(Uncompressed(mozilla::Move(string)));
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptSource::tryCompressOffThread(JSContext* cx)
|
||||
{
|
||||
if (!data.is<Uncompressed>())
|
||||
return true;
|
||||
|
||||
// There are several cases where source compression is not a good idea:
|
||||
// - If the script is tiny, then compression will save little or no space.
|
||||
// - If there is only one core, then compression will contend with JS
|
||||
// execution (which hurts benchmarketing).
|
||||
//
|
||||
// Otherwise, enqueue a compression task to be processed when a major
|
||||
// GC is requested.
|
||||
|
||||
bool canCompressOffThread =
|
||||
HelperThreadState().cpuCount > 1 &&
|
||||
HelperThreadState().threadCount >= 2 &&
|
||||
CanUseExtraThreads();
|
||||
const size_t TINY_SCRIPT = 256;
|
||||
if (TINY_SCRIPT > length() || !canCompressOffThread)
|
||||
return true;
|
||||
|
||||
// The SourceCompressionTask needs to record the major GC number for
|
||||
// scheduling. If we're parsing off thread, this number is not safe to
|
||||
// access.
|
||||
//
|
||||
// When parsing on the main thread, the attempts made to compress off
|
||||
// thread in BytecodeCompiler will succeed.
|
||||
//
|
||||
// When parsing off-thread, the above attempts will fail and the attempt
|
||||
// made in ParseTask::finish will succeed.
|
||||
if (!CurrentThreadCanAccessRuntime(cx->runtime()))
|
||||
return true;
|
||||
|
||||
// Heap allocate the task. It will be freed upon compression
|
||||
// completing in AttachFinishedCompressedSources.
|
||||
auto task = MakeUnique<SourceCompressionTask>(cx->runtime(), this);
|
||||
if (!task)
|
||||
return false;
|
||||
return EnqueueOffThreadCompression(cx, Move(task));
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
ScriptSource::setCompressedSource(JSContext* cx,
|
||||
mozilla::UniquePtr<char[], JS::FreePolicy>&& raw,
|
||||
|
|
|
@ -573,8 +573,6 @@ class ScriptSource
|
|||
size_t length);
|
||||
void setSource(SharedImmutableTwoByteString&& string);
|
||||
|
||||
MOZ_MUST_USE bool tryCompressOffThread(JSContext* cx);
|
||||
|
||||
MOZ_MUST_USE bool setCompressedSource(JSContext* cx,
|
||||
UniqueChars&& raw,
|
||||
size_t rawLength,
|
||||
|
|
|
@ -301,7 +301,7 @@ ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal,
|
|||
alloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
parseGlobal(parseGlobal),
|
||||
callback(callback), callbackData(callbackData),
|
||||
script(nullptr), sourceObject(nullptr),
|
||||
script(nullptr), sourceObject(nullptr), sourceCompressionTask(nullptr),
|
||||
overRecursed(false), outOfMemory(false)
|
||||
{
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal,
|
|||
alloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
parseGlobal(parseGlobal),
|
||||
callback(callback), callbackData(callbackData),
|
||||
script(nullptr), sourceObject(nullptr),
|
||||
script(nullptr), sourceObject(nullptr), sourceCompressionTask(nullptr),
|
||||
overRecursed(false), outOfMemory(false)
|
||||
{
|
||||
}
|
||||
|
@ -340,8 +340,8 @@ ParseTask::finish(JSContext* cx)
|
|||
RootedScriptSource sso(cx, sourceObject);
|
||||
if (!ScriptSourceObject::initFromOptions(cx, sso, options))
|
||||
return false;
|
||||
if (!sso->source()->tryCompressOffThread(cx))
|
||||
return false;
|
||||
if (sourceCompressionTask)
|
||||
sourceCompressionTask->fixupMajorGCNumber(cx->runtime());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -385,7 +385,8 @@ ScriptParseTask::parse(JSContext* cx)
|
|||
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
|
||||
script = frontend::CompileGlobalScript(cx, alloc, ScopeKind::Global,
|
||||
options, srcBuf,
|
||||
/* sourceObjectOut = */ &sourceObject);
|
||||
/* sourceObjectOut = */ &sourceObject,
|
||||
/* sourceCompressionTaskOut = */ &sourceCompressionTask);
|
||||
}
|
||||
|
||||
ModuleParseTask::ModuleParseTask(JSContext* cx, JSObject* parseGlobal,
|
||||
|
@ -400,7 +401,8 @@ void
|
|||
ModuleParseTask::parse(JSContext* cx)
|
||||
{
|
||||
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
|
||||
ModuleObject* module = frontend::CompileModule(cx, options, srcBuf, alloc, &sourceObject);
|
||||
ModuleObject* module = frontend::CompileModule(cx, options, srcBuf, alloc, &sourceObject,
|
||||
&sourceCompressionTask);
|
||||
if (module)
|
||||
script = module->script();
|
||||
}
|
||||
|
@ -1121,13 +1123,13 @@ GlobalHelperThreadState::scheduleCompressionTasks(const AutoLockHelperThreadStat
|
|||
{
|
||||
auto& pending = compressionPendingList(lock);
|
||||
auto& worklist = compressionWorklist(lock);
|
||||
MOZ_ASSERT(worklist.capacity() >= pending.length());
|
||||
|
||||
for (size_t i = 0; i < pending.length(); i++) {
|
||||
if (pending[i]->shouldStart()) {
|
||||
// OOMing during appending results in the task not being scheduled
|
||||
// and deleted.
|
||||
Unused << worklist.append(Move(pending[i]));
|
||||
SourceCompressionTask* task = pending[i];
|
||||
if (task->shouldStart()) {
|
||||
remove(pending, &i);
|
||||
worklist.infallibleAppend(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1728,13 +1730,8 @@ HelperThread::handleCompressionWorkload(AutoLockHelperThreadState& locked)
|
|||
MOZ_ASSERT(HelperThreadState().canStartCompressionTask(locked));
|
||||
MOZ_ASSERT(idle());
|
||||
|
||||
UniquePtr<SourceCompressionTask> task;
|
||||
{
|
||||
auto& worklist = HelperThreadState().compressionWorklist(locked);
|
||||
task = Move(worklist.back());
|
||||
worklist.popBack();
|
||||
currentTask.emplace(task.get());
|
||||
}
|
||||
currentTask.emplace(HelperThreadState().compressionWorklist(locked).popCopy());
|
||||
SourceCompressionTask* task = compressionTask();
|
||||
|
||||
{
|
||||
AutoUnlockHelperThreadState unlock(locked);
|
||||
|
@ -1747,7 +1744,7 @@ HelperThread::handleCompressionWorkload(AutoLockHelperThreadState& locked)
|
|||
|
||||
{
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
if (!HelperThreadState().compressionFinishedList(locked).append(Move(task)))
|
||||
if (!HelperThreadState().compressionFinishedList(locked).append(task))
|
||||
oomUnsafe.crash("handleCompressionWorkload");
|
||||
}
|
||||
|
||||
|
@ -1758,14 +1755,22 @@ HelperThread::handleCompressionWorkload(AutoLockHelperThreadState& locked)
|
|||
}
|
||||
|
||||
bool
|
||||
js::EnqueueOffThreadCompression(JSContext* cx, UniquePtr<SourceCompressionTask> task)
|
||||
js::EnqueueOffThreadCompression(JSContext* cx, SourceCompressionTask* task)
|
||||
{
|
||||
AutoLockHelperThreadState lock;
|
||||
|
||||
auto& pending = HelperThreadState().compressionPendingList(lock);
|
||||
if (!pending.append(Move(task))) {
|
||||
auto& worklist = HelperThreadState().compressionWorklist(lock);
|
||||
if (!pending.append(task)) {
|
||||
if (!cx->helperThread())
|
||||
ReportOutOfMemory(cx);
|
||||
js_delete(task);
|
||||
return false;
|
||||
}
|
||||
if (!worklist.reserve(pending.length())) {
|
||||
if (!cx->helperThread())
|
||||
ReportOutOfMemory(cx);
|
||||
pending.popBack();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1777,8 +1782,11 @@ static void
|
|||
ClearCompressionTaskList(T& list, JSRuntime* runtime)
|
||||
{
|
||||
for (size_t i = 0; i < list.length(); i++) {
|
||||
if (list[i]->runtimeMatches(runtime))
|
||||
SourceCompressionTask* task = list[i];
|
||||
if (task->runtimeMatches(runtime)) {
|
||||
HelperThreadState().remove(list, &i);
|
||||
js_delete(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ class GlobalHelperThreadState
|
|||
|
||||
typedef Vector<jit::IonBuilder*, 0, SystemAllocPolicy> IonBuilderVector;
|
||||
typedef Vector<ParseTask*, 0, SystemAllocPolicy> ParseTaskVector;
|
||||
typedef Vector<UniquePtr<SourceCompressionTask>, 0, SystemAllocPolicy> SourceCompressionTaskVector;
|
||||
typedef Vector<SourceCompressionTask*, 0, SystemAllocPolicy> SourceCompressionTaskVector;
|
||||
typedef Vector<GCHelperState*, 0, SystemAllocPolicy> GCHelperStateVector;
|
||||
typedef Vector<GCParallelTask*, 0, SystemAllocPolicy> GCParallelTaskVector;
|
||||
typedef Vector<PromiseTask*, 0, SystemAllocPolicy> PromiseTaskVector;
|
||||
|
@ -165,10 +165,7 @@ class GlobalHelperThreadState
|
|||
template <typename T>
|
||||
void remove(T& vector, size_t* index)
|
||||
{
|
||||
// Self-moving is undefined behavior.
|
||||
if (*index != vector.length() - 1)
|
||||
vector[*index] = mozilla::Move(vector.back());
|
||||
(*index)--;
|
||||
vector[(*index)--] = vector.back();
|
||||
vector.popBack();
|
||||
}
|
||||
|
||||
|
@ -553,7 +550,7 @@ struct AutoEnqueuePendingParseTasksAfterGC {
|
|||
|
||||
// Enqueue a compression job to be processed if there's a major GC.
|
||||
bool
|
||||
EnqueueOffThreadCompression(JSContext* cx, UniquePtr<SourceCompressionTask> task);
|
||||
EnqueueOffThreadCompression(JSContext* cx, SourceCompressionTask* task);
|
||||
|
||||
// Cancel all scheduled, in progress, or finished compression tasks for
|
||||
// runtime.
|
||||
|
@ -626,6 +623,10 @@ struct ParseTask
|
|||
// Holds the ScriptSourceObject generated for the script compilation.
|
||||
ScriptSourceObject* sourceObject;
|
||||
|
||||
// Holds the SourceCompressionTask, if any were enqueued for the
|
||||
// ScriptSource of sourceObject.
|
||||
SourceCompressionTask* sourceCompressionTask;
|
||||
|
||||
// Any errors or warnings produced during compilation. These are reported
|
||||
// when finishing the script.
|
||||
Vector<CompileError*, 0, SystemAllocPolicy> errors;
|
||||
|
@ -703,6 +704,7 @@ class SourceCompressionTask
|
|||
JSRuntime* runtime_;
|
||||
|
||||
// The major GC number of the runtime when the task was enqueued.
|
||||
static const uint64_t MajorGCNumberWaitingForFixup = UINT64_MAX;
|
||||
uint64_t majorGCNumber_;
|
||||
|
||||
// The source to be compressed.
|
||||
|
@ -715,19 +717,31 @@ class SourceCompressionTask
|
|||
mozilla::Maybe<SharedImmutableString> resultString_;
|
||||
|
||||
public:
|
||||
// The majorGCNumber is used for scheduling tasks.
|
||||
// The majorGCNumber is used for scheduling tasks. If the task is being
|
||||
// enqueued from an off-thread parsing task, leave the GC number
|
||||
// UINT64_MAX to be fixed up when the parse task finishes.
|
||||
SourceCompressionTask(JSRuntime* rt, ScriptSource* source)
|
||||
: runtime_(rt),
|
||||
majorGCNumber_(rt->gc.majorGCCount()),
|
||||
majorGCNumber_(CurrentThreadCanAccessRuntime(rt)
|
||||
? rt->gc.majorGCCount()
|
||||
: MajorGCNumberWaitingForFixup),
|
||||
sourceHolder_(source)
|
||||
{ }
|
||||
|
||||
bool runtimeMatches(JSRuntime* runtime) const {
|
||||
return runtime == runtime_;
|
||||
}
|
||||
|
||||
void fixupMajorGCNumber(JSRuntime* runtime) {
|
||||
MOZ_ASSERT(majorGCNumber_ == MajorGCNumberWaitingForFixup);
|
||||
majorGCNumber_ = runtime->gc.majorGCCount();
|
||||
}
|
||||
|
||||
bool shouldStart() const {
|
||||
// We wait 2 major GCs to start compressing, in order to avoid
|
||||
// immediate compression.
|
||||
if (majorGCNumber_ == MajorGCNumberWaitingForFixup)
|
||||
return false;
|
||||
return runtime_->gc.majorGCCount() > majorGCNumber_ + 1;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче