author | André Bargull <andre.bargull@gmail.com> |
Tue, 16 Nov 2021 16:54:31 +0000 | |
changeset 599338 | 33a125a2e7122a3e3993b5175c3672623a67e40c |
parent 599337 | 5aa4d866a171d9cb0502678028667d987cb3d534 |
child 599339 | fa867b130b44d07b9cc8565583a5a5cd5ec6ddc0 |
push id | 38984 |
push user | malexandru@mozilla.com |
push date | Wed, 17 Nov 2021 03:41:08 +0000 |
treeherder | mozilla-central@a6342e8bac71 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | arai, tcampbell |
bugs | 1696774 |
milestone | 96.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.h +++ b/js/src/frontend/ParserAtom.h @@ -563,18 +563,17 @@ class WellKnownParserAtoms { TaggedParserAtomIndex lookupChar16Seq( const SpecificParserAtomLookup<CharT>& lookup) const; template <typename CharsT> TaggedParserAtomIndex lookupTinyIndex(CharsT chars, size_t length) const { static_assert(std::is_same_v<CharsT, const Latin1Char*> || std::is_same_v<CharsT, const char16_t*> || std::is_same_v<CharsT, const char*> || - std::is_same_v<CharsT, char16_t*> || - std::is_same_v<CharsT, LittleEndianChars>, + std::is_same_v<CharsT, char16_t*>, "This assert mostly explicitly documents the calling types, " "and forces that to be updated if new types show up."); switch (length) { case 0: return TaggedParserAtomIndex::WellKnown::empty(); case 1: { if (char16_t(chars[0]) < TaggedParserAtomIndex::Length1StaticLimit) {
--- a/js/src/jsapi-tests/testParserAtom.cpp +++ b/js/src/jsapi-tests/testParserAtom.cpp @@ -23,19 +23,16 @@ BEGIN_TEST(testParserAtom_empty) { js::LifoAlloc alloc(512); ParserAtomsTable atomTable(cx->runtime(), alloc); const char ascii[] = {}; const JS::Latin1Char latin1[] = {}; const mozilla::Utf8Unit utf8[] = {}; const char16_t char16[] = {}; - const uint8_t bytes[] = {}; - const js::LittleEndianChars leTwoByte(bytes); - // Check that the well-known empty atom matches for different entry points. auto refIndex = TaggedParserAtomIndex::WellKnown::empty(); CHECK(atomTable.internAscii(cx, ascii, 0) == refIndex); CHECK(atomTable.internLatin1(cx, latin1, 0) == refIndex); CHECK(atomTable.internUtf8(cx, utf8, 0) == refIndex); CHECK(atomTable.internChar16(cx, char16, 0) == refIndex); return true; @@ -52,19 +49,16 @@ BEGIN_TEST(testParserAtom_tiny1) { ParserAtomsTable atomTable(cx->runtime(), alloc); 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}; - const js::LittleEndianChars leTwoByte(bytes); - auto refIndex = cx->runtime()->commonParserNames->lookupTinyIndex(&a, 1); CHECK(refIndex); CHECK(atomTable.internAscii(cx, ascii, 1) == refIndex); CHECK(atomTable.internLatin1(cx, latin1, 1) == refIndex); CHECK(atomTable.internUtf8(cx, utf8, 1) == refIndex); CHECK(atomTable.internChar16(cx, char16, 1) == refIndex); // Note: If Latin1-Extended characters become supported, then UTF-8 behaviour @@ -86,19 +80,16 @@ BEGIN_TEST(testParserAtom_tiny2) { ParserAtomsTable atomTable(cx->runtime(), alloc); 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}; - const js::LittleEndianChars leTwoByte(bytes); - auto refIndex = cx->runtime()->commonParserNames->lookupTinyIndex(ascii, 2); CHECK(refIndex); CHECK(atomTable.internAscii(cx, ascii, 2) == refIndex); CHECK(atomTable.internLatin1(cx, latin1, 2) == refIndex); CHECK(atomTable.internUtf8(cx, utf8, 2) == refIndex); CHECK(atomTable.internChar16(cx, char16, 2) == refIndex); // Note: If Latin1-Extended characters become supported, then UTF-8 behaviour
--- a/js/src/vm/AtomsTable.h +++ b/js/src/vm/AtomsTable.h @@ -6,18 +6,16 @@ /* * Implementation details of the atoms table. */ #ifndef vm_AtomsTable_h #define vm_AtomsTable_h -#include <type_traits> // std::{enable_if_t,is_const_v} - #include "js/GCHashTable.h" #include "js/TypeDecls.h" #include "vm/JSAtom.h" /* * The atoms table is a mapping from strings to JSAtoms that supports concurrent * access and incremental sweeping. * @@ -157,32 +155,22 @@ class AtomsTable { AtomStateEntry front() const; void removeFront(); void popFront(); }; ~AtomsTable(); bool init(); - template <typename Chars> + template <typename CharT> MOZ_ALWAYS_INLINE JSAtom* atomizeAndCopyChars( - JSContext* cx, Chars chars, size_t length, PinningBehavior pin, + JSContext* cx, const CharT* chars, size_t length, PinningBehavior pin, const mozilla::Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup); - template <typename CharT, - typename = std::enable_if_t<!std::is_const_v<CharT>>> - MOZ_ALWAYS_INLINE JSAtom* atomizeAndCopyChars( - JSContext* cx, CharT* chars, size_t length, PinningBehavior pin, - const mozilla::Maybe<uint32_t>& indexValue, - const AtomHasher::Lookup& lookup) { - return atomizeAndCopyChars(cx, const_cast<const CharT*>(chars), length, pin, - indexValue, lookup); - } - bool atomIsPinned(JSRuntime* rt, JSAtom* atom); void maybePinExistingAtom(JSContext* cx, JSAtom* atom); void tracePinnedAtoms(JSTracer* trc, const AutoAccessAtomsZone& access); // Sweep all atoms non-incrementally. void traceWeak(JSTracer* trc);
--- a/js/src/vm/JSAtom.cpp +++ b/js/src/vm/JSAtom.cpp @@ -55,20 +55,19 @@ extern bool GetUTF8AtomizationData(JSCon size_t* outlen, JS::SmallestEncoding* encoding, HashNumber* hashNum); struct js::AtomHasher::Lookup { union { const JS::Latin1Char* latin1Chars; const char16_t* twoByteChars; - LittleEndianChars littleEndianChars; const char* utf8Bytes; }; - enum { TwoByteChar, LittleEndianTwoByte, Latin1, UTF8 } type; + enum { TwoByteChar, Latin1, UTF8 } type; size_t length; size_t byteLength; const JSAtom* atom; /* Optional. */ JS::AutoCheckCannotGC nogc; HashNumber hash; MOZ_ALWAYS_INLINE Lookup(const char* utf8Bytes, size_t byteLen, size_t length, @@ -123,70 +122,50 @@ struct js::AtomHasher::Lookup { latin1Chars = atom->latin1Chars(nogc); MOZ_ASSERT(mozilla::HashString(latin1Chars, length) == hash); } else { MOZ_ASSERT(type == TwoByteChar); twoByteChars = atom->twoByteChars(nogc); MOZ_ASSERT(mozilla::HashString(twoByteChars, length) == hash); } } - - MOZ_ALWAYS_INLINE Lookup(LittleEndianChars chars, size_t length) - : littleEndianChars(chars), - type(LittleEndianTwoByte), - length(length), - atom(nullptr), - hash(mozilla::HashStringKnownLength(chars, length)) {} }; inline HashNumber js::AtomHasher::hash(const Lookup& l) { return l.hash; } MOZ_ALWAYS_INLINE bool js::AtomHasher::match(const AtomStateEntry& entry, const Lookup& lookup) { JSAtom* key = entry.asPtrUnbarriered(); if (lookup.atom) { return lookup.atom == key; } if (key->length() != lookup.length || key->hash() != lookup.hash) { return false; } - auto EqualsLittleEndianChars = [&lookup](auto keyChars) { - for (size_t i = 0, len = lookup.length; i < len; i++) { - if (keyChars[i] != lookup.littleEndianChars[i]) { - return false; - } - } - return true; - }; - if (key->hasLatin1Chars()) { const Latin1Char* keyChars = key->latin1Chars(lookup.nogc); switch (lookup.type) { case Lookup::Latin1: return mozilla::ArrayEqual(keyChars, lookup.latin1Chars, lookup.length); case Lookup::TwoByteChar: return EqualChars(keyChars, lookup.twoByteChars, lookup.length); - case Lookup::LittleEndianTwoByte: - return EqualsLittleEndianChars(keyChars); case Lookup::UTF8: { JS::UTF8Chars utf8(lookup.utf8Bytes, lookup.byteLength); return UTF8EqualsChars(utf8, keyChars); } } } const char16_t* keyChars = key->twoByteChars(lookup.nogc); switch (lookup.type) { case Lookup::Latin1: return EqualChars(lookup.latin1Chars, keyChars, lookup.length); case Lookup::TwoByteChar: return mozilla::ArrayEqual(keyChars, lookup.twoByteChars, lookup.length); - case Lookup::LittleEndianTwoByte: - return EqualsLittleEndianChars(keyChars); case Lookup::UTF8: { JS::UTF8Chars utf8(lookup.utf8Bytes, lookup.byteLength); return UTF8EqualsChars(utf8, keyChars); } } MOZ_ASSERT_UNREACHABLE("AtomHasher::match unknown type"); return false; @@ -634,47 +613,33 @@ bool JSRuntime::initMainAtomsTables(JSCo permanentAtomsDuringInit_ = nullptr; // Initialize the main atoms table. MOZ_ASSERT(!atoms_); atoms_ = js_new<AtomsTable>(); return atoms_ && atoms_->init(); } -template <typename Chars> +template <typename CharT> static MOZ_ALWAYS_INLINE JSAtom* AtomizeAndCopyCharsFromLookup( - JSContext* cx, Chars chars, size_t length, const AtomHasher::Lookup& lookup, - PinningBehavior pin, const Maybe<uint32_t>& indexValue); + JSContext* cx, const CharT* chars, size_t length, + const AtomHasher::Lookup& lookup, PinningBehavior pin, + const Maybe<uint32_t>& indexValue); -template <typename CharT, typename = std::enable_if_t<!std::is_const_v<CharT>>> +template <typename CharT> +static MOZ_NEVER_INLINE JSAtom* PermanentlyAtomizeAndCopyChars( + JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, const CharT* chars, + size_t length, const Maybe<uint32_t>& indexValue, + const AtomHasher::Lookup& lookup); + +template <typename CharT> static MOZ_ALWAYS_INLINE JSAtom* AtomizeAndCopyCharsFromLookup( - JSContext* cx, CharT* chars, size_t length, + JSContext* cx, const CharT* chars, size_t length, const AtomHasher::Lookup& lookup, PinningBehavior pin, const Maybe<uint32_t>& indexValue) { - return AtomizeAndCopyCharsFromLookup(cx, const_cast<const CharT*>(chars), - length, lookup, pin, indexValue); -} - -template <typename Chars> -static MOZ_NEVER_INLINE JSAtom* PermanentlyAtomizeAndCopyChars( - JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, Chars chars, size_t length, - const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup); - -template <typename CharT, typename = std::enable_if_t<!std::is_const_v<CharT>>> -static JSAtom* PermanentlyAtomizeAndCopyChars( - JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, CharT* chars, size_t length, - const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) { - return PermanentlyAtomizeAndCopyChars( - cx, zonePtr, const_cast<const CharT*>(chars), length, indexValue, lookup); -} - -template <typename Chars> -static MOZ_ALWAYS_INLINE JSAtom* AtomizeAndCopyCharsFromLookup( - JSContext* cx, Chars chars, size_t length, const AtomHasher::Lookup& lookup, - PinningBehavior pin, const Maybe<uint32_t>& indexValue) { // Try the per-Zone cache first. If we find the atom there we can avoid the // atoms lock, the markAtom call, and the multiple HashSet lookups below. // We don't use the per-Zone cache if we want a pinned atom: handling that // is more complicated and pinning atoms is relatively uncommon. Zone* zone = cx->zone(); Maybe<AtomSet::AddPtr> zonePtr; if (MOZ_LIKELY(zone && pin == DoNotPinAtom)) { zonePtr.emplace(zone->atomCache().lookupForAdd(lookup)); @@ -729,32 +694,24 @@ static MOZ_ALWAYS_INLINE JSAtom* Atomize *zonePtr, AtomStateEntry(atom, false)))) { ReportOutOfMemory(cx); return nullptr; } return atom; } -template <typename Chars> +template <typename CharT> static MOZ_ALWAYS_INLINE JSAtom* AllocateNewAtom( - JSContext* cx, Chars chars, size_t length, + JSContext* cx, const CharT* chars, size_t length, const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup); -template <typename CharT, typename = std::enable_if_t<!std::is_const_v<CharT>>> -static MOZ_ALWAYS_INLINE JSAtom* AllocateNewAtom( - JSContext* cx, CharT* chars, size_t length, - const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) { - return AllocateNewAtom(cx, const_cast<const CharT*>(chars), length, - indexValue, lookup); -} - -template <typename Chars> +template <typename CharT> MOZ_ALWAYS_INLINE JSAtom* AtomsTable::atomizeAndCopyChars( - JSContext* cx, Chars chars, size_t length, PinningBehavior pin, + JSContext* cx, const CharT* chars, size_t length, PinningBehavior pin, const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) { Partition& part = *partitions[getPartitionIndex(lookup)]; AutoLock lock(cx->runtime(), part.lock); AtomSet& atoms = part.atoms; AtomSet* atomsAddedWhileSweeping = part.atomsAddedWhileSweeping; AtomSet::AddPtr p; @@ -812,20 +769,21 @@ static MOZ_ALWAYS_INLINE JSAtom* Atomize return s; } AtomHasher::Lookup lookup(chars, length); return AtomizeAndCopyCharsFromLookup(cx, chars, length, lookup, pin, indexValue); } -template <typename Chars> +template <typename CharT> static MOZ_NEVER_INLINE JSAtom* PermanentlyAtomizeAndCopyChars( - JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, Chars chars, size_t length, - const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) { + JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, const CharT* chars, + size_t length, const Maybe<uint32_t>& indexValue, + const AtomHasher::Lookup& lookup) { MOZ_ASSERT(!cx->permanentAtomsPopulated()); MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); JSRuntime* rt = cx->runtime(); AtomSet& atoms = *rt->permanentAtomsDuringInit(); AtomSet::AddPtr p = atoms.lookupForAdd(lookup); if (p) { return p->asPtr(cx); @@ -913,19 +871,19 @@ static MOZ_ALWAYS_INLINE JSLinearString* } if (chars->encoding == JS::SmallestEncoding::UTF16) { return MakeUTF8AtomHelper<char16_t>(cx, chars, length); } return MakeUTF8AtomHelper<JS::Latin1Char>(cx, chars, length); } -template <typename Chars> +template <typename CharT> static MOZ_ALWAYS_INLINE JSAtom* AllocateNewAtom( - JSContext* cx, Chars chars, size_t length, + JSContext* cx, const CharT* chars, size_t length, const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) { AutoAllocInAtomsZone ac(cx); JSLinearString* linear = MakeLinearStringForAtomization(cx, chars, length); if (!linear) { // Grudgingly forgo last-ditch GC. The alternative would be to release // the lock, manually GC here, and retry from the top. ReportOutOfMemory(cx);
--- a/js/src/vm/StringType-inl.h +++ b/js/src/vm/StringType-inl.h @@ -82,43 +82,35 @@ static MOZ_ALWAYS_INLINE JSInlineString* return nullptr; } JS::AutoCheckCannotGC nogc; mozilla::PodCopy(chars, base->chars<CharT>(nogc) + start, length); return s; } -template <typename Chars> -static MOZ_ALWAYS_INLINE JSLinearString* TryEmptyOrStaticString(JSContext* cx, - Chars chars, - size_t n) { +template <typename CharT> +static MOZ_ALWAYS_INLINE JSLinearString* TryEmptyOrStaticString( + JSContext* cx, const CharT* chars, size_t n) { // Measurements on popular websites indicate empty strings are pretty common // and most strings with length 1 or 2 are in the StaticStrings table. For // length 3 strings that's only about 1%, so we check n <= 2. if (n <= 2) { if (n == 0) { return cx->emptyString(); } if (JSLinearString* str = cx->staticStrings().lookup(chars, n)) { return str; } } return nullptr; } -template <typename CharT, typename = std::enable_if_t<!std::is_const_v<CharT>>> -static MOZ_ALWAYS_INLINE JSLinearString* TryEmptyOrStaticString(JSContext* cx, - CharT* chars, - size_t n) { - return TryEmptyOrStaticString(cx, const_cast<const CharT*>(chars), n); -} - } /* namespace js */ MOZ_ALWAYS_INLINE bool JSString::validateLength(JSContext* maybecx, size_t length) { if (MOZ_UNLIKELY(length > JSString::MAX_LENGTH)) { js::ReportAllocationOverflow(maybecx); return false; }
--- a/js/src/vm/StringType.cpp +++ b/js/src/vm/StringType.cpp @@ -2,19 +2,17 @@ * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "vm/StringType-inl.h" #include "mozilla/ArrayUtils.h" -#include "mozilla/Casting.h" #include "mozilla/DebugOnly.h" -#include "mozilla/EndianUtils.h" #include "mozilla/HashFunctions.h" #include "mozilla/Latin1.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/MemoryReporting.h" #include "mozilla/PodOperations.h" #include "mozilla/RangedPtr.h" #include "mozilla/TextUtils.h" #include "mozilla/Utf8.h" @@ -46,17 +44,16 @@ #include "vm/GeckoProfiler-inl.h" #include "vm/JSContext-inl.h" #include "vm/JSObject-inl.h" #include "vm/Realm-inl.h" using namespace js; using mozilla::ArrayEqual; -using mozilla::AssertedCast; using mozilla::AsWritableChars; using mozilla::ConvertLatin1toUtf16; using mozilla::IsAsciiDigit; using mozilla::IsUtf16Latin1; using mozilla::LossyConvertUtf16toLatin1; using mozilla::PodCopy; using mozilla::RangedPtr; using mozilla::RoundUpPow2; @@ -1000,45 +997,27 @@ static inline void FillChars(char16_t* d PodCopy(dest, src, length); } static inline void FillChars(unsigned char* dest, const unsigned char* src, size_t length) { PodCopy(dest, src, length); } -static inline void FillChars(char16_t* dest, LittleEndianChars src, - size_t length) { -#if MOZ_LITTLE_ENDIAN() - memcpy(dest, src.get(), length * sizeof(char16_t)); -#else - for (size_t i = 0; i < length; ++i) { - dest[i] = src[i]; - } -#endif -} - /** * Copy |src[0..length]| to |dest[0..length]| when copying *does* narrow, but * the user guarantees every runtime |src[i]| value can be stored without change * of value in |dest[i]|. */ static inline void FillFromCompatible(unsigned char* dest, const char16_t* src, size_t length) { LossyConvertUtf16toLatin1(Span(src, length), AsWritableChars(Span(dest, length))); } -static inline void FillFromCompatible(unsigned char* dest, - LittleEndianChars src, size_t length) { - for (size_t i = 0; i < length; ++i) { - dest[i] = AssertedCast<unsigned char>(src[i]); - } -} - #if defined(DEBUG) || defined(JS_JITSPEW) || defined(JS_CACHEIR_SPEW) void JSDependentString::dumpRepresentation(js::GenericPrinter& out, int indent) const { dumpRepresentationHeader(out, "JSDependentString"); indent += 2; out.printf("%*soffset: %zu\n", indent, "", baseOffset()); out.printf("%*sbase: ", indent, ""); base()->dumpRepresentation(out, indent); @@ -1596,26 +1575,16 @@ JSLinearString* js::NewDependentString(J return JSDependentString::new_(cx, base, start, length, heap); } static inline bool CanStoreCharsAsLatin1(const char16_t* s, size_t length) { return IsUtf16Latin1(Span(s, length)); } -static bool CanStoreCharsAsLatin1(LittleEndianChars chars, size_t length) { - for (size_t i = 0; i < length; i++) { - if (chars[i] > JSString::MAX_LATIN1_CHAR) { - return false; - } - } - - return true; -} - template <AllowGC allowGC> static MOZ_ALWAYS_INLINE JSInlineString* NewInlineStringDeflated( JSContext* cx, const mozilla::Range<const char16_t>& chars, gc::InitialHeap heap = gc::DefaultHeap) { size_t len = chars.length(); Latin1Char* storage; JSInlineString* str = AllocateInlineString<allowGC>(cx, len, &storage, heap); if (!str) { @@ -1648,45 +1617,16 @@ static JSLinearString* NewStringDeflated } MOZ_ASSERT(CanStoreCharsAsLatin1(s, n)); FillFromCompatible(news.get(), s, n); return JSLinearString::new_<allowGC>(cx, std::move(news), n, heap); } -static JSLinearString* NewStringDeflatedFromLittleEndianNoGC( - JSContext* cx, LittleEndianChars chars, size_t length, - gc::InitialHeap heap) { - MOZ_ASSERT(CanStoreCharsAsLatin1(chars, length)); - - if (JSInlineString::lengthFits<Latin1Char>(length)) { - Latin1Char* storage; - JSInlineString* str = - AllocateInlineString<NoGC>(cx, length, &storage, heap); - if (!str) { - return nullptr; - } - - FillFromCompatible(storage, chars, length); - return str; - } - - auto news = - cx->make_pod_arena_array<Latin1Char>(js::StringBufferArena, length); - if (!news) { - cx->recoverFromOutOfMemory(); - return nullptr; - } - - FillFromCompatible(news.get(), chars, length); - - return JSLinearString::new_<NoGC>(cx, std::move(news), length, heap); -} - template <AllowGC allowGC, typename CharT> JSLinearString* js::NewStringDontDeflate( JSContext* cx, UniquePtr<CharT[], JS::FreePolicy> chars, size_t length, gc::InitialHeap heap) { if (JSLinearString* str = TryEmptyOrStaticString(cx, chars.get(), length)) { return str; } @@ -1794,42 +1734,16 @@ template JSLinearString* NewStringCopyND size_t n, gc::InitialHeap heap); template JSLinearString* NewStringCopyNDontDeflate<NoGC>(JSContext* cx, const Latin1Char* s, size_t n, gc::InitialHeap heap); -static JSLinearString* NewUndeflatedStringFromLittleEndianNoGC( - JSContext* cx, LittleEndianChars chars, size_t length, - gc::InitialHeap heap) { - if (JSInlineString::lengthFits<char16_t>(length)) { - char16_t* storage; - JSInlineString* str = - AllocateInlineString<NoGC>(cx, length, &storage, heap); - if (!str) { - return nullptr; - } - - FillChars(storage, chars, length); - return str; - } - - auto news = cx->make_pod_arena_array<char16_t>(js::StringBufferArena, length); - if (!news) { - cx->recoverFromOutOfMemory(); - return nullptr; - } - - FillChars(news.get(), chars, length); - - return JSLinearString::new_<NoGC>(cx, std::move(news), length, heap); -} - JSLinearString* NewLatin1StringZ(JSContext* cx, UniqueChars chars, gc::InitialHeap heap) { size_t length = strlen(chars.get()); UniqueLatin1Chars latin1(reinterpret_cast<Latin1Char*>(chars.release())); return NewString<CanGC>(cx, std::move(latin1), length, heap); } template <AllowGC allowGC, typename CharT> @@ -1853,31 +1767,16 @@ template JSLinearString* NewStringCopyN< template JSLinearString* NewStringCopyN<CanGC>(JSContext* cx, const Latin1Char* s, size_t n, gc::InitialHeap heap); template JSLinearString* NewStringCopyN<NoGC>(JSContext* cx, const Latin1Char* s, size_t n, gc::InitialHeap heap); -JSLinearString* NewStringFromLittleEndianNoGC(JSContext* cx, - LittleEndianChars chars, - size_t length, - gc::InitialHeap heap) { - if (JSLinearString* str = TryEmptyOrStaticString(cx, chars, length)) { - return str; - } - - if (CanStoreCharsAsLatin1(chars, length)) { - return NewStringDeflatedFromLittleEndianNoGC(cx, chars, length, heap); - } - - return NewUndeflatedStringFromLittleEndianNoGC(cx, chars, length, heap); -} - template <js::AllowGC allowGC> JSLinearString* NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars utf8, gc::InitialHeap heap) { JS::SmallestEncoding encoding = JS::FindSmallestEncoding(utf8); if (encoding == JS::SmallestEncoding::ASCII) { return NewStringCopyN<allowGC>(cx, utf8.begin().get(), utf8.length(), heap); }
--- a/js/src/vm/StringType.h +++ b/js/src/vm/StringType.h @@ -1275,36 +1275,16 @@ MOZ_ALWAYS_INLINE JSAtom* JSLinearString setFlagBit(PERMANENT_ATOM_MASK); JSAtom* atom = &asAtom(); atom->initHash(hash); return atom; } namespace js { -/** - * An indexable characters class exposing unaligned, little-endian encoded - * char16_t data. - */ -class LittleEndianChars { - public: - explicit constexpr LittleEndianChars(const uint8_t* leTwoByte) - : current(leTwoByte) {} - - constexpr char16_t operator[](size_t index) const { - size_t offset = index * sizeof(char16_t); - return (current[offset + 1] << 8) | current[offset]; - } - - constexpr const uint8_t* get() { return current; } - - private: - const uint8_t* current; -}; - class StaticStrings { // NOTE: The WellKnownParserAtoms rely on these tables and may need to be // update if these tables are changed. friend class js::frontend::ParserAtomsTable; friend class js::frontend::TaggedParserAtomIndex; friend class js::frontend::WellKnownParserAtoms; friend struct js::frontend::CompilationAtomCache; @@ -1360,23 +1340,22 @@ class StaticStrings { /* May not return atom, returns null on (reported) failure. */ inline JSLinearString* getUnitStringForElement(JSContext* cx, JSString* str, size_t index); template <typename CharT> static bool isStatic(const CharT* chars, size_t len); /* Return null if no static atom exists for the given (chars, length). */ - template <typename Chars> - MOZ_ALWAYS_INLINE JSAtom* lookup(Chars chars, size_t length) { - static_assert(std::is_same_v<Chars, const Latin1Char*> || - std::is_same_v<Chars, const char16_t*> || - std::is_same_v<Chars, LittleEndianChars>, - "for understandability, |chars| must be one of a few " - "identified types"); + template <typename CharT> + MOZ_ALWAYS_INLINE JSAtom* lookup(const CharT* chars, size_t length) { + static_assert( + std::is_same_v<CharT, Latin1Char> || std::is_same_v<CharT, char16_t>, + "for understandability, |chars| must be one of a few " + "identified types"); switch (length) { case 1: { char16_t c = chars[0]; if (c < UNIT_STATIC_LIMIT) { return getUnit(c); } return nullptr; @@ -1413,24 +1392,16 @@ class StaticStrings { } MOZ_ALWAYS_INLINE JSAtom* lookup(const char* chars, size_t length) { // Collapse calls for |const char*| into |const Latin1Char char*| to avoid // excess instantiations. return lookup(reinterpret_cast<const Latin1Char*>(chars), length); } - template <typename CharT, - typename = std::enable_if_t<!std::is_const_v<CharT>>> - MOZ_ALWAYS_INLINE JSAtom* lookup(CharT* chars, size_t length) { - // Collapse the remaining |CharT*| to |const CharT*| to avoid excess - // instantiations. - return lookup(const_cast<const CharT*>(chars), length); - } - private: using SmallChar = uint8_t; struct SmallCharTable { SmallChar storage[SMALL_CHAR_TABLE_SIZE]; constexpr SmallChar& operator[](size_t idx) { return storage[idx]; } constexpr const SmallChar& operator[](size_t idx) const { @@ -1658,23 +1629,16 @@ inline JSLinearString* NewStringCopyUTF8 cx, JS::UTF8Chars(utf8.c_str(), strlen(utf8.c_str())), heap); } JSString* NewMaybeExternalString( JSContext* cx, const char16_t* s, size_t n, const JSExternalStringCallbacks* callbacks, bool* allocatedExternal, js::gc::InitialHeap heap = js::gc::DefaultHeap); -/** - * Allocate a new string consisting of |chars[0..length]| characters. - */ -extern JSLinearString* NewStringFromLittleEndianNoGC( - JSContext* cx, LittleEndianChars chars, size_t length, - js::gc::InitialHeap heap = js::gc::DefaultHeap); - static_assert(sizeof(HashNumber) == 4); template <AllowGC allowGC> extern JSString* ConcatStrings( JSContext* cx, typename MaybeRooted<JSString*, allowGC>::HandleType left, typename MaybeRooted<JSString*, allowGC>::HandleType right, js::gc::InitialHeap heap = js::gc::DefaultHeap);