author | Tooru Fujisawa <arai_a@mac.com> |
Thu, 05 Nov 2020 15:32:44 +0000 | |
changeset 556082 | 6f1bf8c8117fa09123eaf86c59fba05fcc600f54 |
parent 556081 | 7a4ce0db75ba7d9d36d61479ae71b42b7440f217 |
child 556083 | e4312f01e2d6a3b6478cf81ae92357ce145da689 |
push id | 130313 |
push user | arai_a@mac.com |
push date | Thu, 05 Nov 2020 20:22:51 +0000 |
treeherder | autoland@f0df0bb8123d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | tcampbell |
bugs | 1674351 |
milestone | 84.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -3777,18 +3777,18 @@ static bool reflect_parse(JSContext* cx, } } else { if (!compilationInfo.get().input.initForModule(cx)) { return false; } } LifoAllocScope allocScope(&cx->tempLifoAlloc()); - frontend::CompilationState compilationState( - cx, allocScope, options, compilationInfo.get().stencil.parserAtoms); + frontend::CompilationState compilationState(cx, allocScope, options, + compilationInfo.get().stencil); Parser<FullParseHandler, char16_t> parser( cx, options, chars.begin().get(), chars.length(), /* foldConstants = */ false, compilationInfo.get(), compilationState, nullptr, nullptr); if (!parser.checkOptions()) { return false; }
--- a/js/src/debugger/Debugger.cpp +++ b/js/src/debugger/Debugger.cpp @@ -6024,18 +6024,18 @@ bool Debugger::isCompilableUnit(JSContex CompileOptions options(cx); Rooted<frontend::CompilationInfo> compilationInfo( cx, frontend::CompilationInfo(cx, options)); if (!compilationInfo.get().input.initForGlobal(cx)) { return false; } LifoAllocScope allocScope(&cx->tempLifoAlloc()); - frontend::CompilationState compilationState( - cx, allocScope, options, compilationInfo.get().stencil.parserAtoms); + frontend::CompilationState compilationState(cx, allocScope, options, + compilationInfo.get().stencil); JS::AutoSuppressWarningReporter suppressWarnings(cx); frontend::Parser<frontend::FullParseHandler, char16_t> parser( cx, options, chars.twoByteChars(), length, /* foldConstants = */ true, compilationInfo.get(), compilationState, nullptr, nullptr); if (!parser.checkOptions() || !parser.parse()) { // We ran into an error. If it was because we ran out of memory we report
--- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -95,22 +95,22 @@ class MOZ_STACK_CLASS frontend::SourceAw Maybe<Parser<SyntaxParseHandler, Unit>> syntaxParser; Maybe<Parser<FullParseHandler, Unit>> parser; using TokenStreamPosition = frontend::TokenStreamPosition<Unit>; protected: explicit SourceAwareCompiler(JSContext* cx, LifoAllocScope& allocScope, const JS::ReadOnlyCompileOptions& options, - ParserAtomsTable& parserAtoms, + CompilationStencil& stencil, SourceText<Unit>& sourceBuffer, js::Scope* enclosingScope = nullptr, JSObject* enclosingEnv = nullptr) : sourceBuffer_(sourceBuffer), - compilationState_(cx, allocScope, options, parserAtoms, enclosingScope, + compilationState_(cx, allocScope, options, stencil, enclosingScope, enclosingEnv) { MOZ_ASSERT(sourceBuffer_.get() != nullptr); } // Call this before calling compile{Global,Eval}Script. MOZ_MUST_USE bool createSourceAndParser(JSContext* cx, CompilationInfo& compilationInfo); @@ -156,21 +156,21 @@ class MOZ_STACK_CLASS frontend::ScriptCo using Base::emplaceEmitter; using Base::handleParseFailure; using typename Base::TokenStreamPosition; public: explicit ScriptCompiler(JSContext* cx, LifoAllocScope& allocScope, const JS::ReadOnlyCompileOptions& options, - ParserAtomsTable& parserAtoms, + CompilationStencil& stencil, SourceText<Unit>& sourceBuffer, js::Scope* enclosingScope = nullptr, JSObject* enclosingEnv = nullptr) - : Base(cx, allocScope, options, parserAtoms, sourceBuffer, enclosingScope, + : Base(cx, allocScope, options, stencil, sourceBuffer, enclosingScope, enclosingEnv) {} using Base::createSourceAndParser; bool compileScriptToStencil(JSContext* cx, CompilationInfo& compilationInfo, SharedContext* sc); }; @@ -245,19 +245,19 @@ static bool CompileGlobalScriptToStencil if (!fallback) { return true; } #endif // JS_ENABLE_SMOOSH AutoAssertReportedException assertException(cx); LifoAllocScope allocScope(&cx->tempLifoAlloc()); - frontend::ScriptCompiler<Unit> compiler( - cx, allocScope, compilationInfo.input.options, - compilationInfo.stencil.parserAtoms, srcBuf); + frontend::ScriptCompiler<Unit> compiler(cx, allocScope, + compilationInfo.input.options, + compilationInfo.stencil, srcBuf); if (!compiler.createSourceAndParser(cx, compilationInfo)) { return false; } SourceExtent extent = SourceExtent::makeGlobalExtent( srcBuf.length(), compilationInfo.input.options.lineno, compilationInfo.input.options.column); @@ -445,18 +445,17 @@ static JSScript* CompileEvalScriptImpl( if (!compilationInfo.get().input.initForEval(cx, enclosingScope)) { return nullptr; } LifoAllocScope allocScope(&cx->tempLifoAlloc()); frontend::ScriptCompiler<Unit> compiler( cx, allocScope, compilationInfo.get().input.options, - compilationInfo.get().stencil.parserAtoms, srcBuf, enclosingScope, - enclosingEnv); + compilationInfo.get().stencil, srcBuf, enclosingScope, enclosingEnv); if (!compiler.createSourceAndParser(cx, compilationInfo.get())) { return nullptr; } uint32_t len = srcBuf.length(); SourceExtent extent = SourceExtent::makeGlobalExtent( len, compilationInfo.get().input.options.lineno, compilationInfo.get().input.options.column); @@ -493,21 +492,21 @@ class MOZ_STACK_CLASS frontend::ModuleCo using Base::compilationState_; using Base::createSourceAndParser; using Base::emplaceEmitter; using Base::parser; public: explicit ModuleCompiler(JSContext* cx, LifoAllocScope& allocScope, const JS::ReadOnlyCompileOptions& options, - ParserAtomsTable& parserAtoms, + CompilationStencil& stencil, SourceText<Unit>& sourceBuffer, js::Scope* enclosingScope = nullptr, JSObject* enclosingEnv = nullptr) - : Base(cx, allocScope, options, parserAtoms, sourceBuffer, enclosingScope, + : Base(cx, allocScope, options, stencil, sourceBuffer, enclosingScope, enclosingEnv) {} bool compile(JSContext* cx, CompilationInfo& compilationInfo); }; template <typename Unit> class MOZ_STACK_CLASS frontend::StandaloneFunctionCompiler final : public SourceAwareCompiler<Unit> { @@ -521,21 +520,21 @@ class MOZ_STACK_CLASS frontend::Standalo using Base::parser; using Base::sourceBuffer_; using typename Base::TokenStreamPosition; public: explicit StandaloneFunctionCompiler(JSContext* cx, LifoAllocScope& allocScope, const JS::ReadOnlyCompileOptions& options, - ParserAtomsTable& parserAtoms, + CompilationStencil& stencil, SourceText<Unit>& sourceBuffer, js::Scope* enclosingScope = nullptr, JSObject* enclosingEnv = nullptr) - : Base(cx, allocScope, options, parserAtoms, sourceBuffer, enclosingScope, + : Base(cx, allocScope, options, stencil, sourceBuffer, enclosingScope, enclosingEnv) {} using Base::createSourceAndParser; FunctionNode* parse(JSContext* cx, CompilationInfo& compilationInfo, FunctionSyntaxKind syntaxKind, GeneratorKind generatorKind, FunctionAsyncKind asyncKind, const Maybe<uint32_t>& parameterListEnd); @@ -889,17 +888,17 @@ static bool ParseModuleToStencilImpl(JSC CompilationInfo& compilationInfo, SourceText<Unit>& srcBuf) { MOZ_ASSERT(srcBuf.get()); AutoAssertReportedException assertException(cx); LifoAllocScope allocScope(&cx->tempLifoAlloc()); ModuleCompiler<Unit> compiler(cx, allocScope, compilationInfo.input.options, - compilationInfo.stencil.parserAtoms, srcBuf); + compilationInfo.stencil, srcBuf); if (!compiler.compile(cx, compilationInfo)) { return false; } assertException.reset(); return true; } @@ -1015,18 +1014,18 @@ static bool CompileLazyFunctionToStencil MOZ_ASSERT(lazy->isReadyForDelazification()); AutoAssertReportedException assertException(cx); Rooted<JSFunction*> fun(cx, lazy->function()); LifoAllocScope allocScope(&cx->tempLifoAlloc()); frontend::CompilationState compilationState( - cx, allocScope, compilationInfo.input.options, - compilationInfo.stencil.parserAtoms, fun->enclosingScope()); + cx, allocScope, compilationInfo.input.options, compilationInfo.stencil, + fun->enclosingScope()); Parser<FullParseHandler, Unit> parser( cx, compilationInfo.input.options, units, length, /* foldConstants = */ true, compilationInfo, compilationState, nullptr, lazy); if (!parser.checkOptions()) { return false; } @@ -1115,17 +1114,17 @@ static JSFunction* CompileStandaloneFunc Rooted<CompilationInfo> compilationInfo(cx, CompilationInfo(cx, options)); if (!compilationInfo.get().input.initForStandaloneFunction(cx, scope)) { return nullptr; } LifoAllocScope allocScope(&cx->tempLifoAlloc()); StandaloneFunctionCompiler<char16_t> compiler( cx, allocScope, compilationInfo.get().input.options, - compilationInfo.get().stencil.parserAtoms, srcBuf, enclosingScope); + compilationInfo.get().stencil, srcBuf, enclosingScope); if (!compiler.createSourceAndParser(cx, compilationInfo.get())) { return nullptr; } FunctionNode* parsedFunction = compiler.parse(cx, compilationInfo.get(), syntaxKind, generatorKind, asyncKind, parameterListEnd); if (!parsedFunction) {
--- a/js/src/frontend/CompilationInfo.h +++ b/js/src/frontend/CompilationInfo.h @@ -88,17 +88,17 @@ struct ScopeContext { void computeInWith(Scope* scope); void computeExternalInitializers(Scope* scope); void computeInClass(Scope* scope); static Scope* determineEffectiveScope(Scope* scope, JSObject* environment); }; struct CompilationAtomCache { - // Atoms lowered into or converted from CompilationStencil.parserAtoms. + // Atoms lowered into or converted from CompilationStencil.parserAtomData. // // This field is here instead of in CompilationGCOutput because atoms lowered // from JSAtom is part of input (enclosing scope bindings, lazy function name, // etc), and having 2 vectors in both input/output is error prone. JS::GCVector<JSAtom*, 0, js::SystemAllocPolicy> atoms; void trace(JSTracer* trc); } JS_HAZ_GC_POINTER; @@ -189,38 +189,35 @@ struct CompilationInput { MOZ_MUST_USE bool assignSource(JSContext* cx, JS::SourceText<Unit>& sourceBuffer) { return source()->assignSource(cx, options, sourceBuffer); } void trace(JSTracer* trc); } JS_HAZ_GC_POINTER; +struct CompilationStencil; + struct MOZ_RAII CompilationState { // Until we have dealt with Atoms in the front end, we need to hold // onto them. Directives directives; ScopeContext scopeContext; UsedNameTracker usedNames; LifoAllocScope& allocScope; - ParserAtomsTable& parserAtoms; + // Table of parser atoms for this compilation. + ParserAtomsTable parserAtoms; - CompilationState(JSContext* cx, LifoAllocScope& alloc, + CompilationState(JSContext* cx, LifoAllocScope& frontendAllocScope, const JS::ReadOnlyCompileOptions& options, - ParserAtomsTable& parserAtoms, - Scope* enclosingScope = nullptr, - JSObject* enclosingEnv = nullptr) - : directives(options.forceStrictMode()), - scopeContext(cx, enclosingScope, enclosingEnv), - usedNames(cx), - allocScope(alloc), - parserAtoms(parserAtoms) {} + CompilationStencil& stencil, Scope* enclosingScope = nullptr, + JSObject* enclosingEnv = nullptr); }; // The top level struct of stencil. struct CompilationStencil { // This holds allocations that do not require destructors to be run but are // live until the stencil is released. LifoAlloc alloc; @@ -249,41 +246,38 @@ struct CompilationStencil { // Module metadata if this is a module compile. StencilModuleMetadata moduleMetadata; // AsmJS modules generated by parsing. HashMap<FunctionIndex, RefPtr<const JS::WasmModule>, mozilla::DefaultHasher<FunctionIndex>, js::SystemAllocPolicy> asmJS; - // Table of parser atoms for this compilation. - ParserAtomsTable parserAtoms; + // List of parser atoms for this compilation. + ParserAtomVector parserAtomData; // Parameterized chunk size to use for LifoAlloc. static constexpr size_t LifoAllocChunkSize = 512; - explicit CompilationStencil(JSRuntime* rt) - : alloc(LifoAllocChunkSize), parserAtoms(rt, alloc) {} + CompilationStencil() : alloc(LifoAllocChunkSize) {} // We need a move-constructor to work with Rooted, but must be explicit in // order to steal the LifoAlloc data. CompilationStencil(CompilationStencil&& other) noexcept : alloc(LifoAllocChunkSize), regExpData(std::move(other.regExpData)), bigIntData(std::move(other.bigIntData)), objLiteralData(std::move(other.objLiteralData)), scriptData(std::move(other.scriptData)), scopeData(std::move(other.scopeData)), moduleMetadata(std::move(other.moduleMetadata)), asmJS(std::move(other.asmJS)), - parserAtoms(std::move(other.parserAtoms)) { - // Steal the data from the LifoAlloc. Anything that holds a reference to - // this will need to be updated. + parserAtomData(std::move(other.parserAtomData)) { + // Steal the data from the LifoAlloc. alloc.steal(&other.alloc); - parserAtoms.updateLifoAlloc(alloc); } #if defined(DEBUG) || defined(JS_JITSPEW) void dump(); void dump(js::JSONPrinter& json); #endif }; @@ -417,17 +411,17 @@ struct CompilationInfo { size_t asmJSCount = 0; }; RewindToken getRewindToken(); void rewind(const RewindToken& pos); // Construct a CompilationInfo CompilationInfo(JSContext* cx, const JS::ReadOnlyCompileOptions& options) - : input(options), stencil(cx->runtime()) {} + : input(options) {} MOZ_MUST_USE bool prepareInputAndStencilForInstantiate(JSContext* cx); MOZ_MUST_USE bool prepareGCOutputForInstantiate( JSContext* cx, CompilationGCOutput& gcOutput); MOZ_MUST_USE bool prepareForInstantiate(JSContext* cx, CompilationGCOutput& gcOutput); MOZ_MUST_USE bool instantiateStencils(JSContext* cx,
--- a/js/src/frontend/Frontend2.cpp +++ b/js/src/frontend/Frontend2.cpp @@ -14,64 +14,63 @@ #include <stddef.h> // size_t #include <stdint.h> // uint8_t, uint32_t #include "jsapi.h" #include "frontend/AbstractScopePtr.h" // ScopeIndex #include "frontend/BytecodeSection.h" // EmitScriptThingsVector -#include "frontend/CompilationInfo.h" // CompilationInfo +#include "frontend/CompilationInfo.h" // CompilationState, CompilationInfo #include "frontend/Parser.h" // NewEmptyLexicalScopeData, NewEmptyGlobalScopeData, NewEmptyVarScopeData, NewEmptyFunctionScopeData #include "frontend/ParserAtom.h" // ParserAtomsTable #include "frontend/smoosh_generated.h" // CVec, Smoosh*, smoosh_* #include "frontend/SourceNotes.h" // SrcNote #include "frontend/Stencil.h" // ScopeStencil, RegExpIndex, FunctionIndex, NullScriptThing #include "frontend/TokenStream.h" // TokenStreamAnyChars #include "irregexp/RegExpAPI.h" // irregexp::CheckPatternSyntax #include "js/CharacterEncoding.h" // JS::UTF8Chars, UTF8CharsToNewTwoByteCharsZ #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* #include "js/GCAPI.h" // JS::AutoCheckCannotGC #include "js/HeapAPI.h" // JS::GCCellPtr #include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "js/RootingAPI.h" // JS::MutableHandle #include "js/UniquePtr.h" // js::UniquePtr -#include "js/Utility.h" // JS::UniqueTwoByteChars, StringBufferArena -#include "vm/JSScript.h" // JSScript -#include "vm/ScopeKind.h" // ScopeKind +#include "js/Utility.h" // JS::UniqueTwoByteChars, StringBufferArena +#include "vm/JSScript.h" // JSScript +#include "vm/ScopeKind.h" // ScopeKind #include "vm/SharedStencil.h" // ImmutableScriptData, ScopeNote, TryNote, GCThingIndex using mozilla::Utf8Unit; using namespace js::gc; using namespace js::frontend; using namespace js; namespace js { namespace frontend { // Given the result of SmooshMonkey's parser, Convert the list of atoms into // the list of ParserAtoms. bool ConvertAtoms(JSContext* cx, const SmooshResult& result, - CompilationInfo& compilationInfo, + CompilationState& compilationState, Vector<const ParserAtom*>& allAtoms) { size_t numAtoms = result.all_atoms_len; if (!allAtoms.reserve(numAtoms)) { return false; } for (size_t i = 0; i < numAtoms; i++) { auto s = reinterpret_cast<const mozilla::Utf8Unit*>( smoosh_get_atom_at(result, i)); auto len = smoosh_get_atom_len_at(result, i); const ParserAtom* atom = - compilationInfo.stencil.parserAtoms.internUtf8(cx, s, len) - .unwrapOr(nullptr); + compilationState.parserAtoms.internUtf8(cx, s, len).unwrapOr(nullptr); if (!atom) { return false; } atom->markUsedByStencil(); allAtoms.infallibleAppend(atom); } return true; @@ -244,17 +243,18 @@ bool ConvertScopeStencil(JSContext* cx, } return true; } // Given the result of SmooshMonkey's parser, convert a list of RegExp data // into a list of RegExpStencil. bool ConvertRegExpData(JSContext* cx, const SmooshResult& result, - CompilationInfo& compilationInfo) { + CompilationInfo& compilationInfo, + CompilationState& compilationState) { for (size_t i = 0; i < result.regexps.len; i++) { SmooshRegExpItem& item = result.regexps.data[i]; auto s = smoosh_get_slice_at(result, item.pattern); auto len = smoosh_get_slice_len_at(result, item.pattern); JS::RegExpFlags::Flag flags = JS::RegExpFlag::NoFlags; if (item.global) { flags |= JS::RegExpFlag::Global; @@ -295,17 +295,17 @@ bool ConvertRegExpData(JSContext* cx, co LifoAllocScope allocScope(&cx->tempLifoAlloc()); if (!irregexp::CheckPatternSyntax(cx, ts, range, flags)) { return false; } const mozilla::Utf8Unit* sUtf8 = reinterpret_cast<const mozilla::Utf8Unit*>(s); const ParserAtom* atom = - compilationInfo.stencil.parserAtoms.internUtf8(cx, sUtf8, len) + compilationState.parserAtoms.internUtf8(cx, sUtf8, len) .unwrapOr(nullptr); if (!atom) { return false; } atom->markUsedByStencil(); RegExpIndex index(compilationInfo.stencil.regExpData.length()); if (!compilationInfo.stencil.regExpData.emplaceBack( @@ -557,26 +557,30 @@ bool Smoosh::compileGlobalScriptToStenci if (result.unimplemented) { *unimplemented = true; return false; } *unimplemented = false; + LifoAllocScope allocScope(&cx->tempLifoAlloc()); + Vector<const ParserAtom*> allAtoms(cx); - if (!ConvertAtoms(cx, result, compilationInfo, allAtoms)) { + CompilationState compilationState( + cx, allocScope, compilationInfo.input.options, compilationInfo.stencil); + if (!ConvertAtoms(cx, result, compilationState, allAtoms)) { return false; } if (!ConvertScopeStencil(cx, result, allAtoms, compilationInfo)) { return false; } - if (!ConvertRegExpData(cx, result, compilationInfo)) { + if (!ConvertRegExpData(cx, result, compilationInfo, compilationState)) { return false; } if (!compilationInfo.stencil.scriptData.reserve(result.scripts.len)) { js::ReportOutOfMemory(cx); return false; }
--- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -10292,20 +10292,19 @@ RegExpLiteral* Parser<FullParseHandler, // skip this. LifoAllocScope allocScope(&cx_->tempLifoAlloc()); if (!irregexp::CheckPatternSyntax(cx_, anyChars, range, flags, Some(line), Some(column))) { return nullptr; } } - const ParserAtom* atom = - this->getCompilationInfo() - .stencil.parserAtoms.internChar16(cx_, chars.begin(), chars.length()) - .unwrapOr(nullptr); + const ParserAtom* atom = this->compilationState_.parserAtoms + .internChar16(cx_, chars.begin(), chars.length()) + .unwrapOr(nullptr); if (!atom) { return nullptr; } atom->markUsedByStencil(); RegExpIndex index(this->getCompilationInfo().stencil.regExpData.length()); if (!this->getCompilationInfo().stencil.regExpData.emplaceBack(atom, flags)) { js::ReportOutOfMemory(cx_);
--- a/js/src/frontend/ParserAtom.cpp +++ b/js/src/frontend/ParserAtom.cpp @@ -312,18 +312,21 @@ void ParserAtomEntry::dumpCharsNoQuote(j if (hasLatin1Chars()) { JSString::dumpCharsNoQuote<Latin1Char>(latin1Chars(), length(), out); } else { JSString::dumpCharsNoQuote<char16_t>(twoByteChars(), length(), out); } } #endif -ParserAtomsTable::ParserAtomsTable(JSRuntime* rt, LifoAlloc& alloc) - : wellKnownTable_(*rt->commonParserNames), alloc_(&alloc) {} +ParserAtomsTable::ParserAtomsTable(JSRuntime* rt, LifoAlloc& alloc, + ParserAtomVector& entries) + : wellKnownTable_(*rt->commonParserNames), + alloc_(alloc), + entries_(entries) {} JS::Result<const ParserAtom*, OOM> ParserAtomsTable::addEntry( JSContext* cx, EntryMap::AddPtr& addPtr, ParserAtomEntry* entry) { MOZ_ASSERT(!addPtr); ParserAtomIndex index = ParserAtomIndex(entries_.length()); if (!entries_.append(entry)) { return RaiseParserAtomsOOMError(cx); } @@ -335,27 +338,27 @@ JS::Result<const ParserAtom*, OOM> Parse template <typename AtomCharT, typename SeqCharT> JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internChar16Seq( JSContext* cx, EntryMap::AddPtr& addPtr, HashNumber hash, InflatedChar16Sequence<SeqCharT> seq, uint32_t length) { MOZ_ASSERT(!addPtr); ParserAtomEntry* entry; - MOZ_TRY_VAR(entry, ParserAtomEntry::allocate<AtomCharT>(cx, *alloc_, seq, + MOZ_TRY_VAR(entry, ParserAtomEntry::allocate<AtomCharT>(cx, alloc_, seq, length, hash)); return addEntry(cx, addPtr, entry); } template <typename AtomCharT, typename SeqCharT> JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internChar16Seq( JSContext* cx, HashNumber hash, InflatedChar16Sequence<SeqCharT> seq, uint32_t length) { ParserAtomEntry* entry; - MOZ_TRY_VAR(entry, ParserAtomEntry::allocate<AtomCharT>(cx, *alloc_, seq, + MOZ_TRY_VAR(entry, ParserAtomEntry::allocate<AtomCharT>(cx, alloc_, seq, length, hash)); ParserAtomIndex index = ParserAtomIndex(entries_.length()); if (!entries_.append(entry)) { return RaiseParserAtomsOOMError(cx); } SpecificParserAtomLookup<SeqCharT> lookup(seq, hash); // This will be removed in later patch. @@ -618,29 +621,29 @@ const ParserAtom* ParserAtomsTable::getW const ParserAtom* ParserAtomsTable::getStatic1(StaticParserString1 s) const { return WellKnownParserAtoms::rom_.length1Table[size_t(s)].asAtom(); } const ParserAtom* ParserAtomsTable::getStatic2(StaticParserString2 s) const { return WellKnownParserAtoms::rom_.length2Table[size_t(s)].asAtom(); } -size_t ParserAtomsTable::requiredNonStaticAtomCount() const { +size_t RequiredNonStaticAtomCount(const ParserAtomVector& entries) { size_t count = 0; - for (const auto& entry : entries_) { + for (const auto& entry : entries) { if (entry->isNotInstantiatedAndMarked() || entry->isAtomIndex()) { count++; } } return count; } -bool ParserAtomsTable::instantiateMarkedAtoms( - JSContext* cx, CompilationAtomCache& atomCache) const { - for (const auto& entry : entries_) { +bool InstantiateMarkedAtoms(JSContext* cx, const ParserAtomVector& entries, + CompilationAtomCache& atomCache) { + for (const auto& entry : entries) { if (entry->isNotInstantiatedAndMarked()) { if (!entry->instantiate(cx, atomCache)) { return false; } } } return true; }
--- a/js/src/frontend/ParserAtom.h +++ b/js/src/frontend/ParserAtom.h @@ -496,38 +496,43 @@ class WellKnownParserAtoms { const SpecificParserAtomLookup<CharT>& lookup) const; template <typename CharsT> const ParserAtom* lookupTiny(CharsT chars, size_t length) const { return rom_.lookupTiny(chars, length); } }; +// The number of atoms with either NotInstantiatedAndMarked or AtomIndex kind, +// that requires space in CompilationAtomCache.atoms during instantiation. +size_t RequiredNonStaticAtomCount(const ParserAtomVector& entries); + +bool InstantiateMarkedAtoms(JSContext* cx, const ParserAtomVector& entries, + CompilationAtomCache& atomCache); + /** * A ParserAtomsTable owns and manages the vector of ParserAtom entries * associated with a given compile session. */ class ParserAtomsTable { private: const WellKnownParserAtoms& wellKnownTable_; - LifoAlloc* alloc_; + LifoAlloc& alloc_; // The ParserAtomEntry are owned by the LifoAlloc. using EntryMap = HashMap<ParserAtomEntry*, ParserAtomIndex, ParserAtomLookupHasher, js::SystemAllocPolicy>; EntryMap entryMap_; - ParserAtomVector entries_; + ParserAtomVector& entries_; public: - explicit ParserAtomsTable(JSRuntime* rt, LifoAlloc& alloc); + ParserAtomsTable(JSRuntime* rt, LifoAlloc& alloc, ParserAtomVector& entries); ParserAtomsTable(ParserAtomsTable&&) = default; - void updateLifoAlloc(LifoAlloc& alloc) { alloc_ = &alloc; } - private: // Internal APIs for interning to the table after well-known atoms cases have // been tested. JS::Result<const ParserAtom*, OOM> addEntry(JSContext* cx, EntryMap::AddPtr& addPtr, ParserAtomEntry* entry); template <typename AtomCharT, typename SeqCharT> JS::Result<const ParserAtom*, OOM> internChar16Seq( @@ -536,23 +541,16 @@ class ParserAtomsTable { template <typename AtomCharT, typename SeqCharT> JS::Result<const ParserAtom*, OOM> internChar16Seq( JSContext* cx, HashNumber hash, InflatedChar16Sequence<SeqCharT> seq, uint32_t length); public: bool empty() const { return entryMap_.empty(); } - // The number of atoms with either NotInstantiatedAndMarked or AtomIndex kind, - // that requires space in CompilationAtomCache.atoms while instantiation. - size_t requiredNonStaticAtomCount() const; - - bool instantiateMarkedAtoms(JSContext* cx, - CompilationAtomCache& atomCache) const; - JS::Result<const ParserAtom*, OOM> internAscii(JSContext* cx, const char* asciiPtr, uint32_t length); JS::Result<const ParserAtom*, OOM> internLatin1( JSContext* cx, const JS::Latin1Char* latin1Ptr, uint32_t length); JS::Result<const ParserAtom*, OOM> internLatin1ForXDR(
--- a/js/src/frontend/Stencil.cpp +++ b/js/src/frontend/Stencil.cpp @@ -224,18 +224,18 @@ static JSFunction* CreateFunction(JSCont fun->setExtendedSlot(FunctionExtended::ASMJS_MODULE_SLOT, ObjectValue(*moduleObj)); } return fun; } static bool InstantiateAtoms(JSContext* cx, CompilationInfo& compilationInfo) { - return compilationInfo.stencil.parserAtoms.instantiateMarkedAtoms( - cx, compilationInfo.input.atomCache); + return InstantiateMarkedAtoms(cx, compilationInfo.stencil.parserAtomData, + compilationInfo.input.atomCache); } static bool InstantiateScriptSourceObject(JSContext* cx, CompilationInfo& compilationInfo, CompilationGCOutput& gcOutput) { MOZ_ASSERT(compilationInfo.input.source()); gcOutput.sourceObject = @@ -795,17 +795,17 @@ bool CompilationInfoVector::instantiateS } } return true; } bool CompilationInfo::prepareInputAndStencilForInstantiate(JSContext* cx) { if (!input.atomCache.atoms.reserve( - stencil.parserAtoms.requiredNonStaticAtomCount())) { + RequiredNonStaticAtomCount(stencil.parserAtomData))) { ReportOutOfMemory(cx); return false; } preparationIsPerformed = true; return true; } @@ -883,17 +883,17 @@ bool CompilationInfo::serializeStencils( } bool CompilationInfoVector::deserializeStencils(JSContext* cx, const JS::TranscodeRange& range, bool* succeededOut) { if (succeededOut) { *succeededOut = false; } - MOZ_ASSERT(initial.stencil.parserAtoms.empty()); + MOZ_ASSERT(initial.stencil.parserAtomData.empty()); XDRStencilDecoder decoder(cx, &initial.input.options, range); XDRResult res = decoder.codeStencils(*this); if (res.isErr()) { if (res.unwrapErr() & JS::TranscodeResult_Failure) { return true; } MOZ_ASSERT(res.unwrapErr() == JS::TranscodeResult_Throw); @@ -902,16 +902,28 @@ bool CompilationInfoVector::deserializeS } if (succeededOut) { *succeededOut = true; } return true; } +CompilationState::CompilationState(JSContext* cx, + LifoAllocScope& frontendAllocScope, + const JS::ReadOnlyCompileOptions& options, + CompilationStencil& stencil, + Scope* enclosingScope /* = nullptr */, + JSObject* enclosingEnv /* = nullptr */) + : directives(options.forceStrictMode()), + scopeContext(cx, enclosingScope, enclosingEnv), + usedNames(cx), + allocScope(frontendAllocScope), + parserAtoms(cx->runtime(), stencil.alloc, stencil.parserAtomData) {} + #if defined(DEBUG) || defined(JS_JITSPEW) void RegExpStencil::dump() { js::Fprinter out(stderr); js::JSONPrinter json(out); dump(json); }
--- a/js/src/jsapi-tests/testParserAtom.cpp +++ b/js/src/jsapi-tests/testParserAtom.cpp @@ -12,19 +12,21 @@ #include "frontend/ParserAtom.h" // js::frontend::ParserAtomsTable #include "js/TypeDecls.h" // JS::Latin1Char #include "jsapi-tests/tests.h" // Test empty strings behave consistently. BEGIN_TEST(testParserAtom_empty) { using js::frontend::ParserAtom; using js::frontend::ParserAtomsTable; + using js::frontend::ParserAtomVector; js::LifoAlloc alloc(512); - ParserAtomsTable atomTable(cx->runtime(), alloc); + ParserAtomVector atoms; + ParserAtomsTable atomTable(cx->runtime(), alloc, atoms); const char ascii[] = {}; const JS::Latin1Char latin1[] = {}; const mozilla::Utf8Unit utf8[] = {}; const char16_t char16[] = {}; const uint8_t bytes[] = {}; const js::LittleEndianChars leTwoByte(bytes); @@ -48,19 +50,21 @@ BEGIN_TEST(testParserAtom_empty) { return true; } END_TEST(testParserAtom_empty) // Test length-1 fast-path is consistent across entry points. BEGIN_TEST(testParserAtom_tiny1) { using js::frontend::ParserAtom; using js::frontend::ParserAtomsTable; + using js::frontend::ParserAtomVector; js::LifoAlloc alloc(512); - ParserAtomsTable atomTable(cx->runtime(), alloc); + ParserAtomVector atoms; + ParserAtomsTable atomTable(cx->runtime(), alloc, atoms); char16_t a = 'a'; const char ascii[] = {'a'}; JS::Latin1Char latin1[] = {'a'}; const mozilla::Utf8Unit utf8[] = {mozilla::Utf8Unit('a')}; char16_t char16[] = {'a'}; const uint8_t bytes[] = {'a', 0}; @@ -88,19 +92,21 @@ BEGIN_TEST(testParserAtom_tiny1) { return true; } END_TEST(testParserAtom_tiny1) // Test length-2 fast-path is consistent across entry points. BEGIN_TEST(testParserAtom_tiny2) { using js::frontend::ParserAtom; using js::frontend::ParserAtomsTable; + using js::frontend::ParserAtomVector; js::LifoAlloc alloc(512); - ParserAtomsTable atomTable(cx->runtime(), alloc); + ParserAtomVector atoms; + ParserAtomsTable atomTable(cx->runtime(), alloc, atoms); const char ascii[] = {'a', '0'}; JS::Latin1Char latin1[] = {'a', '0'}; const mozilla::Utf8Unit utf8[] = {mozilla::Utf8Unit('a'), mozilla::Utf8Unit('0')}; char16_t char16[] = {'a', '0'}; const uint8_t bytes[] = {'a', 0, '0', 0}; @@ -127,19 +133,21 @@ BEGIN_TEST(testParserAtom_tiny2) { return true; } END_TEST(testParserAtom_tiny2) BEGIN_TEST(testParserAtom_concat) { using js::frontend::ParserAtom; using js::frontend::ParserAtomsTable; + using js::frontend::ParserAtomVector; js::LifoAlloc alloc(512); - ParserAtomsTable atomTable(cx->runtime(), alloc); + ParserAtomVector atoms; + ParserAtomsTable atomTable(cx->runtime(), alloc, atoms); auto CheckConcat = [&](const char16_t* exp, std::initializer_list<const char16_t*> args) -> bool { // Intern each argument literal std::vector<const ParserAtom*> inputs; for (const char16_t* arg : args) { size_t len = std::char_traits<char16_t>::length(arg); const ParserAtom* atom = atomTable.internChar16(cx, arg, len).unwrap();
--- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -5582,18 +5582,18 @@ static bool FrontendTest(JSContext* cx, } } else { if (!compilationInfo.get().input.initForModule(cx)) { return false; } } LifoAllocScope allocScope(&cx->tempLifoAlloc()); - frontend::CompilationState compilationState( - cx, allocScope, options, compilationInfo.get().stencil.parserAtoms); + frontend::CompilationState compilationState(cx, allocScope, options, + compilationInfo.get().stencil); if (isAscii) { const Latin1Char* latin1 = stableChars.latin1Range().begin().get(); auto utf8 = reinterpret_cast<const mozilla::Utf8Unit*>(latin1); if (!DumpAST<mozilla::Utf8Unit>(cx, options, utf8, length, compilationInfo.get(), compilationState, goal)) { return false; @@ -5648,18 +5648,18 @@ static bool SyntaxParse(JSContext* cx, u js::Rooted<frontend::CompilationInfo> compilationInfo( cx, js::frontend::CompilationInfo(cx, options)); if (!compilationInfo.get().input.initForGlobal(cx)) { return false; } LifoAllocScope allocScope(&cx->tempLifoAlloc()); - frontend::CompilationState compilationState( - cx, allocScope, options, compilationInfo.get().stencil.parserAtoms); + frontend::CompilationState compilationState(cx, allocScope, options, + compilationInfo.get().stencil); Parser<frontend::SyntaxParseHandler, char16_t> parser( cx, options, chars, length, false, compilationInfo.get(), compilationState, nullptr, nullptr); if (!parser.checkOptions()) { return false; }
--- a/js/src/vm/CompilationAndEvaluation.cpp +++ b/js/src/vm/CompilationAndEvaluation.cpp @@ -201,18 +201,18 @@ JS_PUBLIC_API bool JS_Utf8BufferIsCompil CompileOptions options(cx); Rooted<frontend::CompilationInfo> compilationInfo( cx, frontend::CompilationInfo(cx, options)); if (!compilationInfo.get().input.initForGlobal(cx)) { return false; } LifoAllocScope allocScope(&cx->tempLifoAlloc()); - frontend::CompilationState compilationState( - cx, allocScope, options, compilationInfo.get().stencil.parserAtoms); + frontend::CompilationState compilationState(cx, allocScope, options, + compilationInfo.get().stencil); JS::AutoSuppressWarningReporter suppressWarnings(cx); Parser<FullParseHandler, char16_t> parser(cx, options, chars.get(), length, /* foldConstants = */ true, compilationInfo.get(), compilationState, nullptr, nullptr); if (!parser.checkOptions() || !parser.parse()) { // We ran into an error. If it was because we ran out of source, we
--- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -11,16 +11,17 @@ #include "mozilla/ScopeExit.h" #include "mozilla/Unused.h" #include "mozilla/Utf8.h" // mozilla::Utf8Unit #include <algorithm> #include "frontend/BytecodeCompilation.h" #include "frontend/CompilationInfo.h" // frontend::CompilationInfo, frontend::CompilationGCOutput +#include "frontend/ParserAtom.h" // frontend::ParserAtomsTable #include "jit/IonCompileTask.h" #include "jit/JitRuntime.h" #include "js/ContextOptions.h" // JS::ContextOptions #include "js/friend/StackLimits.h" // js::ReportOverRecursed #include "js/OffThreadScriptCompilation.h" // JS::OffThreadToken, JS::OffThreadCompileCallback #include "js/SourceText.h" #include "js/UniquePtr.h" #include "js/Utility.h"
--- a/js/src/vm/Xdr.cpp +++ b/js/src/vm/Xdr.cpp @@ -747,17 +747,20 @@ XDRResult XDRIncrementalStencilEncoder:: void XDRDecoder::trace(JSTracer* trc) { atomTable_.trace(trc); } void XDRIncrementalEncoder::trace(JSTracer* trc) { atomMap_.trace(trc); } XDRResult XDRStencilDecoder::codeStencils( frontend::CompilationInfoVector& compilationInfos) { MOZ_ASSERT(compilationInfos.delazifications.length() == 0); - parserAtoms_ = &compilationInfos.initial.stencil.parserAtoms; + frontend::ParserAtomsTable parserAtoms( + cx()->runtime(), compilationInfos.initial.stencil.alloc, + compilationInfos.initial.stencil.parserAtomData); + parserAtoms_ = &parserAtoms; stencilAlloc_ = &compilationInfos.initial.stencil.alloc; MOZ_TRY(codeStencil(compilationInfos.initial)); if (!compilationInfos.delazifications.reserve(nchunks_ - 1)) { ReportOutOfMemory(cx()); return fail(JS::TranscodeResult_Throw); } @@ -765,17 +768,19 @@ XDRResult XDRStencilDecoder::codeStencil for (size_t i = 1; i < nchunks_; i++) { compilationInfos.delazifications.infallibleEmplaceBack( cx(), compilationInfos.initial.input.options); auto& funInfo = compilationInfos.delazifications[i - 1]; parserAtomTable_.clear(); hasFinishedAtomTable_ = false; - parserAtoms_ = &funInfo.stencil.parserAtoms; + frontend::ParserAtomsTable parserAtoms( + cx()->runtime(), funInfo.stencil.alloc, funInfo.stencil.parserAtomData); + parserAtoms_ = &parserAtoms; stencilAlloc_ = &funInfo.stencil.alloc; MOZ_TRY(codeFunctionStencil(funInfo.stencil)); } return Ok(); }