From b430e79e18bb48806269f88eb99780f7e1bceecd Mon Sep 17 00:00:00 2001 From: Kannan Vijayan Date: Wed, 12 Aug 2020 03:23:06 +0000 Subject: [PATCH] Bug 1658593 - Bugfixes in ParserAtoms implementation. r=tcampbell Differential Revision: https://phabricator.services.mozilla.com/D86734 --- js/src/frontend/ParserAtom.cpp | 76 +++++++++++++++++++++++----------- js/src/frontend/ParserAtom.h | 14 +++---- 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/js/src/frontend/ParserAtom.cpp b/js/src/frontend/ParserAtom.cpp index 34f80d556be9..875debd1c52a 100644 --- a/js/src/frontend/ParserAtom.cpp +++ b/js/src/frontend/ParserAtom.cpp @@ -101,26 +101,28 @@ bool ParserAtomEntry::equalsJSAtom(JSAtom* other) const { : EqualChars(latin1Chars(), other->twoByteChars(nogc), length_); } -UniqueChars ParserAtomToPrintableString(JSContext* cx, const ParserAtom* atom) { +template +UniqueChars ToPrintableStringImpl(JSContext* cx, mozilla::Range str) { Sprinter sprinter(cx); if (!sprinter.init()) { return nullptr; } - size_t length = atom->length(); - if (atom->hasLatin1Chars()) { - if (!QuoteString( - &sprinter, mozilla::Range(atom->latin1Chars(), length))) { - return nullptr; - } - } else { - if (!QuoteString( - &sprinter, mozilla::Range(atom->twoByteChars(), length))) { - return nullptr; - } + if (!QuoteString(&sprinter, str)) { + return nullptr; } return sprinter.release(); } +UniqueChars ParserAtomToPrintableString(JSContext* cx, const ParserAtom* atom) { + size_t length = atom->length(); + + return atom->hasLatin1Chars() + ? ToPrintableStringImpl( + cx, mozilla::Range(atom->latin1Chars(), length)) + : ToPrintableStringImpl( + cx, mozilla::Range(atom->twoByteChars(), length)); +} + bool ParserAtomEntry::isIndex(uint32_t* indexp) const { size_t len = length(); if (len == 0 || len > UINT32_CHAR_BUFFER_LENGTH) { @@ -155,6 +157,16 @@ bool ParserAtomEntry::toNumber(JSContext* cx, double* result) const { : CharsToNumber(cx, twoByteChars(), length(), result); } +#if defined(DEBUG) || defined(JS_JITSPEW) +void ParserAtomEntry::dumpCharsNoQuote(js::GenericPrinter& out) const { + if (hasLatin1Chars()) { + JSString::dumpCharsNoQuote(latin1Chars(), length(), out); + } else { + JSString::dumpCharsNoQuote(twoByteChars(), length(), out); + } +} +#endif + ParserAtomsTable::ParserAtomsTable(JSContext* cx) : entrySet_(cx), wellKnownTable_(*cx->runtime()->commonParserNames) {} @@ -425,21 +437,37 @@ bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name, MOZ_ASSERT(FindSmallestEncoding(UTF8Chars(str, len)) == JS::SmallestEncoding::ASCII); - UniqueLatin1Chars copy(cx->pod_malloc(len)); - if (!copy) { - return false; - } - mozilla::PodCopy(copy.get(), reinterpret_cast(str), len); - - InflatedChar16Sequence seq(copy.get(), len); + InflatedChar16Sequence seq( + reinterpret_cast(str), len); SpecificParserAtomLookup lookup(seq); + HashNumber hash = lookup.hash(); - auto maybeEntry = - ParserAtomEntry::allocate(cx, std::move(copy), len, lookup.hash()); - if (maybeEntry.isErr()) { - return false; + UniquePtr entry = nullptr; + + // Check for inline allocation. + if (len <= ParserAtomEntry::MaxInline()) { + auto maybeEntry = + ParserAtomEntry::allocateInline(cx, seq, len, hash); + if (maybeEntry.isErr()) { + return false; + } + entry = maybeEntry.unwrap(); + + // Do heap-allocation of contents. + } else { + UniqueLatin1Chars copy(cx->pod_malloc(len)); + if (!copy) { + return false; + } + mozilla::PodCopy(copy.get(), reinterpret_cast(str), len); + auto maybeEntry = ParserAtomEntry::allocate(cx, std::move(copy), len, hash); + if (maybeEntry.isErr()) { + return false; + } + entry = maybeEntry.unwrap(); } - UniquePtr entry = maybeEntry.unwrap(); + + // Save name for returning after moving entry into set. const ParserName* nm = entry.get()->asName(); if (!entrySet_.putNew(lookup, std::move(entry))) { return false; diff --git a/js/src/frontend/ParserAtom.h b/js/src/frontend/ParserAtom.h index c8a7bb8bc4dc..bde758aee770 100644 --- a/js/src/frontend/ParserAtom.h +++ b/js/src/frontend/ParserAtom.h @@ -43,6 +43,7 @@ mozilla::GenericErrorResult RaiseParserAtomsOOMError(JSContext* cx); */ class alignas(alignof(void*)) ParserAtomEntry { friend class ParserAtomsTable; + friend class WellKnownParserAtoms; template static constexpr uint32_t MaxInline() { @@ -279,6 +280,10 @@ class alignas(alignof(void*)) ParserAtomEntry { // Convert this entry to a number. bool toNumber(JSContext* cx, double* result) const; + +#if defined(DEBUG) || defined(JS_JITSPEW) + void dumpCharsNoQuote(js::GenericPrinter& out) const; +#endif }; class ParserAtom : public ParserAtomEntry { @@ -483,10 +488,6 @@ inline bool ParserAtomEntry::equalsSeq( return false; } } - if (seq.hasMore()) { - return false; - } - } else { const Latin1Char* chars = latin1Chars(); for (uint32_t i = 0; i < length_; i++) { @@ -494,11 +495,8 @@ inline bool ParserAtomEntry::equalsSeq( return false; } } - if (seq.hasMore()) { - return false; - } } - return true; + return !seq.hasMore(); } } /* namespace frontend */