author | Tooru Fujisawa <arai_a@mac.com> |
Thu, 05 Nov 2020 15:55:57 +0000 | |
changeset 556066 | e4312f01e2d6a3b6478cf81ae92357ce145da689 |
parent 556065 | 6f1bf8c8117fa09123eaf86c59fba05fcc600f54 |
child 556067 | f0df0bb8123db84dc77fb7d32fdf9e5045e4f0e7 |
push id | 37925 |
push user | apavel@mozilla.com |
push date | Fri, 06 Nov 2020 04:14:34 +0000 |
treeherder | mozilla-central@81a3ef82469b [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/frontend/ParserAtom.cpp +++ b/js/src/frontend/ParserAtom.cpp @@ -343,38 +343,16 @@ JS::Result<const ParserAtom*, OOM> Parse MOZ_ASSERT(!addPtr); ParserAtomEntry* entry; 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, - 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. - auto addPtr = entryMap_.lookupForAdd(lookup); - MOZ_ASSERT(!addPtr); - if (!entryMap_.add(addPtr, entry, index)) { - return RaiseParserAtomsOOMError(cx); - } - return entry->asAtom(); -} - static const uint16_t MAX_LATIN1_CHAR = 0xff; JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internAscii( JSContext* cx, const char* asciiPtr, uint32_t length) { // ASCII strings are strict subsets of Latin1 strings. const Latin1Char* latin1Ptr = reinterpret_cast<const Latin1Char*>(asciiPtr); return internLatin1(cx, latin1Ptr, length); } @@ -397,41 +375,67 @@ JS::Result<const ParserAtom*, OOM> Parse auto addPtr = entryMap_.lookupForAdd(lookup); if (addPtr) { return addPtr->key()->asAtom(); } return internChar16Seq<Latin1Char>(cx, addPtr, lookup.hash(), seq, length); } -// For XDR we should only need to intern user strings so skip checks for tiny -// and well-known atoms. As well, the atoms are unique already. -JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internLatin1ForXDR( +ParserAtomVectorBuilder::ParserAtomVectorBuilder(JSRuntime* rt, + LifoAlloc& alloc, + ParserAtomVector& entries) + : wellKnownTable_(*rt->commonParserNames), + alloc_(&alloc), + entries_(entries) {} + +JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internLatin1( JSContext* cx, const Latin1Char* latin1Ptr, HashNumber hash, uint32_t length) { - InflatedChar16Sequence<Latin1Char> seq(latin1Ptr, length); - SpecificParserAtomLookup<Latin1Char> lookup(seq, hash); - - MOZ_ASSERT(wellKnownTable_.lookupTiny(latin1Ptr, length) == nullptr); - MOZ_ASSERT(wellKnownTable_.lookupChar16Seq(lookup) == nullptr); - - return internChar16Seq<Latin1Char>(cx, hash, seq, length); + return intern<Latin1Char, Latin1Char>(cx, latin1Ptr, hash, length); } -// Similar to internLatin1ForXDR, but char16_t is needed to represent. -JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internChar16ForXDR( +JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internChar16( JSContext* cx, LittleEndianChars twoByteLE, HashNumber hash, uint32_t length) { +#ifdef DEBUG InflatedChar16Sequence<LittleEndianChars> seq(twoByteLE, length); - SpecificParserAtomLookup<LittleEndianChars> lookup(seq, hash); + bool wide = false; + while (seq.hasMore()) { + char16_t ch = seq.next(); + if (ch > MAX_LATIN1_CHAR) { + wide = true; + break; + } + } + MOZ_ASSERT(wide); +#endif + + return intern<char16_t, LittleEndianChars>(cx, twoByteLE, hash, length); +} - MOZ_ASSERT(wellKnownTable_.lookupTiny(twoByteLE, length) == nullptr); +template <typename CharT, typename SeqCharT, typename InputCharsT> +JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::intern( + JSContext* cx, InputCharsT chars, HashNumber hash, uint32_t length) { + InflatedChar16Sequence<SeqCharT> seq(chars, length); + +#ifdef DEBUG + SpecificParserAtomLookup<SeqCharT> lookup(seq); + + MOZ_ASSERT(wellKnownTable_.lookupTiny(chars, length) == nullptr); MOZ_ASSERT(wellKnownTable_.lookupChar16Seq(lookup) == nullptr); +#endif - return internChar16Seq<char16_t>(cx, hash, seq, length); + ParserAtomEntry* entry; + MOZ_TRY_VAR(entry, + ParserAtomEntry::allocate<CharT>(cx, *alloc_, seq, length, hash)); + if (!entries_.append(entry)) { + return RaiseParserAtomsOOMError(cx); + } + return entry->asAtom(); } JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internUtf8( JSContext* cx, const mozilla::Utf8Unit* utf8Ptr, uint32_t nbyte) { // Check for tiny strings which are abundant in minified code. // NOTE: The tiny atoms are all ASCII-only so we can directly look at the // UTF-8 data without worrying about surrogates. if (const ParserAtom* tiny = wellKnownTable_.lookupTiny( @@ -594,17 +598,18 @@ JS::Result<const ParserAtom*, OOM> Parse // Otherwise, add new entry. return catLatin1 ? internChar16Seq<Latin1Char>(cx, addPtr, lookup.hash(), seq, catLen) : internChar16Seq<char16_t>(cx, addPtr, lookup.hash(), seq, catLen); } -const ParserAtom* ParserAtomsTable::getWellKnown(WellKnownAtomId atomId) const { +const ParserAtom* ParserAtomVectorBuilder::getWellKnown( + WellKnownAtomId atomId) const { #define ASSERT_OFFSET_(idpart, id, text) \ static_assert(offsetof(WellKnownParserAtoms, id) == \ int32_t(WellKnownAtomId::id) * sizeof(ParserAtom*)); FOR_EACH_COMMON_PROPERTYNAME(ASSERT_OFFSET_); #undef ASSERT_OFFSET_ #define ASSERT_OFFSET_(name, clasp) \ static_assert(offsetof(WellKnownParserAtoms, name) == \ @@ -613,21 +618,23 @@ const ParserAtom* ParserAtomsTable::getW #undef ASSERT_OFFSET_ static_assert(int32_t(WellKnownAtomId::abort) == 0, "Unexpected order of WellKnownAtom"); return (&wellKnownTable_.abort)[int32_t(atomId)]; } -const ParserAtom* ParserAtomsTable::getStatic1(StaticParserString1 s) const { +const ParserAtom* ParserAtomVectorBuilder::getStatic1( + StaticParserString1 s) const { return WellKnownParserAtoms::rom_.length1Table[size_t(s)].asAtom(); } -const ParserAtom* ParserAtomsTable::getStatic2(StaticParserString2 s) const { +const ParserAtom* ParserAtomVectorBuilder::getStatic2( + StaticParserString2 s) const { return WellKnownParserAtoms::rom_.length2Table[size_t(s)].asAtom(); } size_t RequiredNonStaticAtomCount(const ParserAtomVector& entries) { size_t count = 0; for (const auto& entry : entries) { if (entry->isNotInstantiatedAndMarked() || entry->isAtomIndex()) { count++; @@ -857,25 +864,24 @@ XDRResult XDRParserAtomData(XDRState<mod JS::Result<const ParserAtom*, JS::OOM> mbAtom(nullptr); if (latin1) { const Latin1Char* chars = nullptr; if (length) { const uint8_t* ptr = nullptr; MOZ_TRY(xdr->peekData(&ptr, length * sizeof(Latin1Char))); chars = reinterpret_cast<const Latin1Char*>(ptr); } - mbAtom = xdr->frontendAtoms().internLatin1ForXDR(cx, chars, hash, length); + mbAtom = xdr->frontendAtoms().internLatin1(cx, chars, hash, length); } else { const uint8_t* twoByteCharsLE = nullptr; if (length) { MOZ_TRY(xdr->peekData(&twoByteCharsLE, length * sizeof(char16_t))); } LittleEndianChars leTwoByte(twoByteCharsLE); - mbAtom = - xdr->frontendAtoms().internChar16ForXDR(cx, leTwoByte, hash, length); + mbAtom = xdr->frontendAtoms().internChar16(cx, leTwoByte, hash, length); } const ParserAtom* atom = mbAtom.unwrapOr(nullptr); if (!atom) { return xdr->fail(JS::TranscodeResult_Throw); } // We only transcoded ParserAtoms used for Stencils so on decode, all
--- a/js/src/frontend/ParserAtom.h +++ b/js/src/frontend/ParserAtom.h @@ -533,52 +533,68 @@ class ParserAtomsTable { // 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( JSContext* cx, EntryMap::AddPtr& addPtr, HashNumber hash, InflatedChar16Sequence<SeqCharT> seq, uint32_t length); - 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(); } 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( - JSContext* cx, const JS::Latin1Char* latin1Ptr, HashNumber hash, - uint32_t length); - JS::Result<const ParserAtom*, OOM> internUtf8( JSContext* cx, const mozilla::Utf8Unit* utf8Ptr, uint32_t nbyte); JS::Result<const ParserAtom*, OOM> internChar16(JSContext* cx, const char16_t* char16Ptr, uint32_t length); - JS::Result<const ParserAtom*, OOM> internChar16ForXDR( - JSContext* cx, LittleEndianChars twoByteLE, HashNumber hash, - uint32_t length); - JS::Result<const ParserAtom*, OOM> internJSAtom( JSContext* cx, CompilationInfo& compilationInfo, JSAtom* atom); JS::Result<const ParserAtom*, OOM> concatAtoms( JSContext* cx, mozilla::Range<const ParserAtom*> atoms); +}; +// Lightweight version of ParserAtomsTable. +// This doesn't support deduplication. +// Used while decoding XDR. +class ParserAtomVectorBuilder { + private: + const WellKnownParserAtoms& wellKnownTable_; + LifoAlloc* alloc_; + ParserAtomVector& entries_; + + public: + ParserAtomVectorBuilder(JSRuntime* rt, LifoAlloc& alloc, + ParserAtomVector& entries); + + JS::Result<const ParserAtom*, OOM> internLatin1( + JSContext* cx, const JS::Latin1Char* latin1Ptr, HashNumber hash, + uint32_t length); + + JS::Result<const ParserAtom*, OOM> internChar16( + JSContext* cx, const LittleEndianChars twoByteLE, HashNumber hash, + uint32_t length); + + private: + template <typename CharT, typename SeqCharT, typename InputCharsT> + JS::Result<const ParserAtom*, OOM> intern(JSContext* cx, InputCharsT chars, + HashNumber hash, uint32_t length); + + public: const ParserAtom* getWellKnown(WellKnownAtomId atomId) const; const ParserAtom* getStatic1(StaticParserString1 s) const; const ParserAtom* getStatic2(StaticParserString2 s) const; }; template <typename CharT> class SpecificParserAtomLookup : public ParserAtomLookup { // The sequence of characters to look up.
--- a/js/src/vm/Xdr.cpp +++ b/js/src/vm/Xdr.cpp @@ -747,20 +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); - frontend::ParserAtomsTable parserAtoms( + frontend::ParserAtomVectorBuilder parserAtomBuilder( cx()->runtime(), compilationInfos.initial.stencil.alloc, compilationInfos.initial.stencil.parserAtomData); - parserAtoms_ = &parserAtoms; + parserAtomBuilder_ = &parserAtomBuilder; stencilAlloc_ = &compilationInfos.initial.stencil.alloc; MOZ_TRY(codeStencil(compilationInfos.initial)); if (!compilationInfos.delazifications.reserve(nchunks_ - 1)) { ReportOutOfMemory(cx()); return fail(JS::TranscodeResult_Throw); } @@ -768,19 +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; - frontend::ParserAtomsTable parserAtoms( + frontend::ParserAtomVectorBuilder parserAtomBuilder( cx()->runtime(), funInfo.stencil.alloc, funInfo.stencil.parserAtomData); - parserAtoms_ = &parserAtoms; + parserAtomBuilder_ = &parserAtomBuilder; stencilAlloc_ = &funInfo.stencil.alloc; MOZ_TRY(codeFunctionStencil(funInfo.stencil)); } return Ok(); }
--- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -270,17 +270,17 @@ class XDRState : public XDRCoderBase { } virtual uint32_t& natoms() { MOZ_CRASH("does not have atomMap."); } // The number of chunks (CompilationStencils) in the buffer. virtual uint32_t& nchunks() { MOZ_CRASH("does not have atomMap."); } virtual bool hasAtomTable() const { return false; } virtual XDRAtomTable& atomTable() { MOZ_CRASH("does not have atomTable"); } - virtual frontend::ParserAtomsTable& frontendAtoms() { + virtual frontend::ParserAtomVectorBuilder& frontendAtoms() { MOZ_CRASH("does not have frontendAtoms"); } virtual LifoAlloc& stencilAlloc() { MOZ_CRASH("does not have stencilAlloc"); } virtual XDRParserAtomTable& parserAtomTable() { // This accessor is only used when encoding stencils. MOZ_CRASH("does not have parserAtomTable"); } virtual void finishAtomTable() { MOZ_CRASH("does not have atomTable"); } @@ -533,31 +533,33 @@ class XDRStencilDecoder : public XDRDeco MOZ_ASSERT(options_); } uint32_t& nchunks() override { return nchunks_; } bool isForStencil() const override { return true; } bool hasAtomTable() const override { return hasFinishedAtomTable_; } - frontend::ParserAtomsTable& frontendAtoms() override { return *parserAtoms_; } + frontend::ParserAtomVectorBuilder& frontendAtoms() override { + return *parserAtomBuilder_; + } LifoAlloc& stencilAlloc() override { return *stencilAlloc_; } XDRParserAtomTable& parserAtomTable() override { return parserAtomTable_; } void finishAtomTable() override { hasFinishedAtomTable_ = true; } bool hasOptions() const override { return true; } const JS::ReadOnlyCompileOptions& options() override { return *options_; } XDRResult codeStencils(frontend::CompilationInfoVector& compilationInfos); private: const JS::ReadOnlyCompileOptions* options_; XDRParserAtomTable parserAtomTable_; bool hasFinishedAtomTable_ = false; - frontend::ParserAtomsTable* parserAtoms_ = nullptr; + frontend::ParserAtomVectorBuilder* parserAtomBuilder_ = nullptr; LifoAlloc* stencilAlloc_ = nullptr; }; class XDROffThreadDecoder : public XDRDecoder { ScriptSourceObject** sourceObjectOut_; bool isMultiDecode_; public: