зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1348134 - Stop eagerly compressing ScriptSources. (r=jonco)
This commit is contained in:
Родитель
1196244596
Коммит
8f1a38f1dd
|
@ -43,9 +43,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
SourceBufferHolder& sourceBuffer,
|
||||
HandleScope enclosingScope);
|
||||
|
||||
// Call setters for optional arguments.
|
||||
void maybeSetSourceCompressor(SourceCompressionTask* sourceCompressor);
|
||||
|
||||
JSScript* compileGlobalScript(ScopeKind scopeKind);
|
||||
JSScript* compileEvalScript(HandleObject environment, HandleScope enclosingScope);
|
||||
ModuleObject* compileModule();
|
||||
|
@ -59,7 +56,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
JSScript* compileScript(HandleObject environment, SharedContext* sc);
|
||||
bool checkLength();
|
||||
bool createScriptSource(const Maybe<uint32_t>& parameterListEnd);
|
||||
bool maybeCompressSource();
|
||||
bool canLazilyParse();
|
||||
bool createParser();
|
||||
bool createSourceAndParser(const Maybe<uint32_t>& parameterListEnd = Nothing());
|
||||
|
@ -67,7 +63,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
bool emplaceEmitter(Maybe<BytecodeEmitter>& emitter, SharedContext* sharedContext);
|
||||
bool handleParseFailure(const Directives& newDirectives);
|
||||
bool deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment);
|
||||
bool maybeCompleteCompressSource();
|
||||
|
||||
AutoKeepAtoms keepAtoms;
|
||||
|
||||
|
@ -81,9 +76,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
RootedScriptSource sourceObject;
|
||||
ScriptSource* scriptSource;
|
||||
|
||||
Maybe<SourceCompressionTask> maybeSourceCompressor;
|
||||
SourceCompressionTask* sourceCompressor;
|
||||
|
||||
Maybe<UsedNameTracker> usedNames;
|
||||
Maybe<Parser<SyntaxParseHandler>> syntaxParser;
|
||||
Maybe<Parser<FullParseHandler>> parser;
|
||||
|
@ -172,7 +164,6 @@ BytecodeCompiler::BytecodeCompiler(JSContext* cx,
|
|||
enclosingScope(cx, enclosingScope),
|
||||
sourceObject(cx),
|
||||
scriptSource(nullptr),
|
||||
sourceCompressor(nullptr),
|
||||
directives(options.strictOption),
|
||||
startPosition(keepAtoms),
|
||||
script(cx)
|
||||
|
@ -180,12 +171,6 @@ BytecodeCompiler::BytecodeCompiler(JSContext* cx,
|
|||
MOZ_ASSERT(sourceBuffer.get());
|
||||
}
|
||||
|
||||
void
|
||||
BytecodeCompiler::maybeSetSourceCompressor(SourceCompressionTask* sourceCompressor)
|
||||
{
|
||||
this->sourceCompressor = sourceCompressor;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::checkLength()
|
||||
{
|
||||
|
@ -212,23 +197,12 @@ BytecodeCompiler::createScriptSource(const Maybe<uint32_t>& parameterListEnd)
|
|||
return false;
|
||||
|
||||
scriptSource = sourceObject->source();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::maybeCompressSource()
|
||||
{
|
||||
if (!sourceCompressor) {
|
||||
maybeSourceCompressor.emplace(cx);
|
||||
sourceCompressor = maybeSourceCompressor.ptr();
|
||||
}
|
||||
|
||||
if (!cx->compartment()->behaviors().discardSource()) {
|
||||
if (options.sourceIsLazy) {
|
||||
if (options.sourceIsLazy)
|
||||
scriptSource->setSourceRetrievable();
|
||||
} else if (!scriptSource->setSourceCopy(cx, sourceBuffer, sourceCompressor)) {
|
||||
else if (!scriptSource->setSourceCopy(cx, sourceBuffer))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -263,7 +237,6 @@ BytecodeCompiler::createParser()
|
|||
|
||||
parser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
|
||||
/* foldConstants = */ true, *usedNames, syntaxParser.ptrOr(nullptr), nullptr);
|
||||
parser->sct = sourceCompressor;
|
||||
parser->ss = scriptSource;
|
||||
if (!parser->checkOptions())
|
||||
return false;
|
||||
|
@ -276,7 +249,6 @@ bool
|
|||
BytecodeCompiler::createSourceAndParser(const Maybe<uint32_t>& parameterListEnd /* = Nothing() */)
|
||||
{
|
||||
return createScriptSource(parameterListEnd) &&
|
||||
maybeCompressSource() &&
|
||||
createParser();
|
||||
}
|
||||
|
||||
|
@ -341,12 +313,6 @@ BytecodeCompiler::deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObj
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::maybeCompleteCompressSource()
|
||||
{
|
||||
return !maybeSourceCompressor || maybeSourceCompressor->complete();
|
||||
}
|
||||
|
||||
JSScript*
|
||||
BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
|
||||
{
|
||||
|
@ -394,9 +360,6 @@ BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
|
|||
usedNames->reset();
|
||||
}
|
||||
|
||||
if (!maybeCompleteCompressSource())
|
||||
return nullptr;
|
||||
|
||||
// We have just finished parsing the source. Inform the source so that we
|
||||
// can compute statistics (e.g. how much time our functions remain lazy).
|
||||
script->scriptSource()->recordParseEnded();
|
||||
|
@ -462,9 +425,6 @@ BytecodeCompiler::compileModule()
|
|||
|
||||
module->setInitialEnvironment(env);
|
||||
|
||||
if (!maybeCompleteCompressSource())
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
|
||||
return module;
|
||||
}
|
||||
|
@ -517,9 +477,6 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
|||
if (!NameFunctions(cx, fn))
|
||||
return false;
|
||||
|
||||
if (!maybeCompleteCompressSource())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -597,13 +554,11 @@ JSScript*
|
|||
frontend::CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* extraSct,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
{
|
||||
MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, /* enclosingScope = */ nullptr);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
compiler.maybeSetSourceCompressor(extraSct);
|
||||
return compiler.compileGlobalScript(scopeKind);
|
||||
}
|
||||
|
||||
|
@ -612,12 +567,10 @@ frontend::CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
|
|||
HandleObject environment, HandleScope enclosingScope,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* extraSct,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
{
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, enclosingScope);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
compiler.maybeSetSourceCompressor(extraSct);
|
||||
return compiler.compileEvalScript(environment, enclosingScope);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ class LazyScript;
|
|||
class LifoAlloc;
|
||||
class ModuleObject;
|
||||
class ScriptSourceObject;
|
||||
struct SourceCompressionTask;
|
||||
|
||||
namespace frontend {
|
||||
|
||||
|
@ -35,7 +34,6 @@ JSScript*
|
|||
CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* extraSct = nullptr,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
|
||||
JSScript*
|
||||
|
@ -43,7 +41,6 @@ CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
|
|||
HandleObject scopeChain, HandleScope enclosingScope,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* extraSct = nullptr,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
|
||||
ModuleObject*
|
||||
|
|
|
@ -782,7 +782,6 @@ ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
|
|||
traceListHead(nullptr),
|
||||
pc(nullptr),
|
||||
usedNames(usedNames),
|
||||
sct(nullptr),
|
||||
ss(nullptr),
|
||||
keepAtoms(cx),
|
||||
foldConstants(foldConstants),
|
||||
|
@ -9169,7 +9168,7 @@ template <typename ParseHandler>
|
|||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::stringLiteral()
|
||||
{
|
||||
return handler.newStringLiteral(stopStringCompression(), pos());
|
||||
return handler.newStringLiteral(tokenStream.currentToken().atom(), pos());
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
@ -9181,7 +9180,7 @@ Parser<ParseHandler>::noSubstitutionTaggedTemplate()
|
|||
return handler.newRawUndefinedLiteral(pos());
|
||||
}
|
||||
|
||||
return handler.newTemplateStringLiteral(stopStringCompression(), pos());
|
||||
return handler.newTemplateStringLiteral(tokenStream.currentToken().atom(), pos());
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
@ -9191,20 +9190,7 @@ Parser<ParseHandler>::noSubstitutionUntaggedTemplate()
|
|||
if (!tokenStream.checkForInvalidTemplateEscapeError())
|
||||
return null();
|
||||
|
||||
return handler.newTemplateStringLiteral(stopStringCompression(), pos());
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
JSAtom * Parser<ParseHandler>::stopStringCompression() {
|
||||
JSAtom* atom = tokenStream.currentToken().atom();
|
||||
|
||||
// Large strings are fast to parse but slow to compress. Stop compression on
|
||||
// them, so we don't wait for a long time for compression to finish at the
|
||||
// end of compilation.
|
||||
const size_t HUGE_STRING = 50000;
|
||||
if (sct && sct->active() && atom->length() >= HUGE_STRING)
|
||||
sct->abort();
|
||||
return atom;
|
||||
return handler.newTemplateStringLiteral(tokenStream.currentToken().atom(), pos());
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
|
|
@ -770,9 +770,6 @@ class ParserBase : public StrictModeGetter
|
|||
// For tracking used names in this parsing session.
|
||||
UsedNameTracker& usedNames;
|
||||
|
||||
/* Compression token for aborting. */
|
||||
SourceCompressionTask* sct;
|
||||
|
||||
ScriptSource* ss;
|
||||
|
||||
/* Root atoms and objects allocated for the parsed tree. */
|
||||
|
@ -1087,8 +1084,6 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
private:
|
||||
Parser* thisForCtor() { return this; }
|
||||
|
||||
JSAtom* stopStringCompression();
|
||||
|
||||
Node stringLiteral();
|
||||
Node noSubstitutionTaggedTemplate();
|
||||
Node noSubstitutionUntaggedTemplate();
|
||||
|
|
|
@ -4589,9 +4589,8 @@ Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
|
|||
MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(env), scopeKind == ScopeKind::NonSyntactic);
|
||||
|
||||
options.setIsRunOnce(true);
|
||||
SourceCompressionTask sct(cx);
|
||||
RootedScript script(cx, frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(),
|
||||
scopeKind, options, srcBuf, &sct));
|
||||
scopeKind, options, srcBuf));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
@ -4599,8 +4598,6 @@ Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
|
|||
|
||||
bool result = Execute(cx, script, *env,
|
||||
options.noScriptRval ? nullptr : rval.address());
|
||||
if (!sct.complete())
|
||||
result = false;
|
||||
|
||||
// After evaluation, the compiled script will not be run again.
|
||||
// script->ensureRanAnalysis allocated 1 analyze::Bytecode for every opcode
|
||||
|
|
|
@ -1789,8 +1789,7 @@ ScriptSource::setCompressedSource(SharedImmutableString&& raw, size_t uncompress
|
|||
}
|
||||
|
||||
bool
|
||||
ScriptSource::setSourceCopy(JSContext* cx, SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* task)
|
||||
ScriptSource::setSourceCopy(JSContext* cx, SourceBufferHolder& srcBuf)
|
||||
{
|
||||
MOZ_ASSERT(!hasSourceData());
|
||||
|
||||
|
@ -1806,35 +1805,6 @@ ScriptSource::setSourceCopy(JSContext* cx, SourceBufferHolder& srcBuf,
|
|||
}
|
||||
setSource(mozilla::Move(*deduped));
|
||||
|
||||
// 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).
|
||||
// - If the source contains a giant string, then parsing will finish much
|
||||
// faster than compression which increases latency (this case is handled
|
||||
// in Parser::stringLiteral).
|
||||
//
|
||||
// Lastly, since the parsing thread will eventually perform a blocking wait
|
||||
// on the compression task's thread, require that there are at least 2
|
||||
// helper threads:
|
||||
// - If we are on a helper thread, there must be another helper thread to
|
||||
// execute our compression task.
|
||||
// - If we are on the active thread, there must be at least two helper
|
||||
// threads since at most one helper thread can be blocking on the active
|
||||
// thread (see HelperThreadState::canStartParseTask) which would cause a
|
||||
// deadlock if there wasn't a second helper thread that could make
|
||||
// progress on our compression task.
|
||||
bool canCompressOffThread =
|
||||
HelperThreadState().cpuCount > 1 &&
|
||||
HelperThreadState().threadCount >= 2 &&
|
||||
CanUseExtraThreads();
|
||||
const size_t TINY_SCRIPT = 256;
|
||||
if (TINY_SCRIPT <= srcBuf.length() && canCompressOffThread) {
|
||||
task->ss = this;
|
||||
if (!StartOffThreadCompression(cx, task))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1874,9 +1844,6 @@ SourceCompressionTask::work()
|
|||
bool cont = true;
|
||||
bool reallocated = false;
|
||||
while (cont) {
|
||||
if (abort_)
|
||||
return Aborted;
|
||||
|
||||
switch (comp.compressMore()) {
|
||||
case Compressor::CONTINUE:
|
||||
break;
|
||||
|
|
|
@ -485,9 +485,7 @@ class ScriptSource
|
|||
MOZ_MUST_USE bool initFromOptions(JSContext* cx,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
const mozilla::Maybe<uint32_t>& parameterListEnd = mozilla::Nothing());
|
||||
MOZ_MUST_USE bool setSourceCopy(JSContext* cx,
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* tok);
|
||||
MOZ_MUST_USE bool setSourceCopy(JSContext* cx, JS::SourceBufferHolder& srcBuf);
|
||||
void setSourceRetrievable() { sourceRetrievable_ = true; }
|
||||
bool sourceRetrievable() const { return sourceRetrievable_; }
|
||||
bool hasSourceData() const { return !data.is<Missing>(); }
|
||||
|
|
|
@ -380,7 +380,6 @@ ScriptParseTask::parse(JSContext* cx)
|
|||
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
|
||||
script = frontend::CompileGlobalScript(cx, alloc, ScopeKind::Global,
|
||||
options, srcBuf,
|
||||
/* extraSct = */ nullptr,
|
||||
/* sourceObjectOut = */ &sourceObject);
|
||||
}
|
||||
|
||||
|
|
|
@ -674,10 +674,6 @@ struct SourceCompressionTask
|
|||
|
||||
ScriptSource* ss;
|
||||
|
||||
// Atomic flag to indicate to a helper thread that it should abort
|
||||
// compression on the source.
|
||||
mozilla::Atomic<bool, mozilla::Relaxed> abort_;
|
||||
|
||||
// Stores the result of the compression.
|
||||
enum ResultType {
|
||||
OOM,
|
||||
|
@ -692,7 +688,6 @@ struct SourceCompressionTask
|
|||
: helperThread(nullptr)
|
||||
, cx(cx)
|
||||
, ss(nullptr)
|
||||
, abort_(false)
|
||||
, result(OOM)
|
||||
{}
|
||||
|
||||
|
@ -703,7 +698,6 @@ struct SourceCompressionTask
|
|||
|
||||
ResultType work();
|
||||
bool complete();
|
||||
void abort() { abort_ = true; }
|
||||
bool active() const { return !!ss; }
|
||||
ScriptSource* source() { return ss; }
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче