diff --git a/src/heap/factory.cc b/src/heap/factory.cc index 3baa5fdfc8..6b5d320737 100644 --- a/src/heap/factory.cc +++ b/src/heap/factory.cc @@ -736,8 +736,16 @@ Handle Factory::InternalizeOneByteString( } Handle Factory::InternalizeTwoByteString( - const Vector& string) { - TwoByteStringKey key(string, HashSeed(isolate())); + Handle string, int from, int length, + bool convert_to_one_byte) { + SeqTwoByteSubStringKey key(isolate(), string, from, length, + convert_to_one_byte); + return InternalizeStringWithKey(&key); +} + +Handle Factory::InternalizeTwoByteString( + const Vector& string, bool convert_to_one_byte) { + TwoByteStringKey key(string, HashSeed(isolate()), convert_to_one_byte); return InternalizeStringWithKey(&key); } @@ -924,22 +932,29 @@ Handle Factory::AllocateRawOneByteInternalizedString( Handle Factory::AllocateTwoByteInternalizedString( const Vector& str, uint32_t hash_field) { - CHECK_GE(String::kMaxLength, str.length()); - DCHECK_NE(0, str.length()); // Use Heap::empty_string() instead. - - Map map = *internalized_string_map(); - int size = SeqTwoByteString::SizeFor(str.length()); - HeapObject result = - AllocateRawWithImmortalMap(size, AllocationType::kOld, map); - Handle answer(SeqTwoByteString::cast(result), isolate()); - answer->set_length(str.length()); - answer->set_hash_field(hash_field); - DCHECK_EQ(size, answer->Size()); + Handle result = + AllocateRawTwoByteInternalizedString(str.length(), hash_field); DisallowHeapAllocation no_gc; // Fill in the characters. - MemCopy(answer->GetChars(no_gc), str.begin(), str.length() * kUC16Size); + MemCopy(result->GetChars(no_gc), str.begin(), str.length() * kUC16Size); + return result; +} + +Handle Factory::AllocateRawTwoByteInternalizedString( + int length, uint32_t hash_field) { + CHECK_GE(String::kMaxLength, length); + DCHECK_NE(0, length); // Use Heap::empty_string() instead. + + Map map = *internalized_string_map(); + int size = SeqTwoByteString::SizeFor(length); + HeapObject result = + AllocateRawWithImmortalMap(size, AllocationType::kOld, map); + Handle answer(SeqTwoByteString::cast(result), isolate()); + answer->set_length(length); + answer->set_hash_field(hash_field); + DCHECK_EQ(size, result.Size()); return answer; } @@ -991,17 +1006,6 @@ Handle Factory::NewOneByteInternalizedString( return result; } -Handle Factory::NewOneByteInternalizedSubString( - Handle string, int offset, int length, - uint32_t hash_field) { - Handle result = - AllocateRawOneByteInternalizedString(length, hash_field); - DisallowHeapAllocation no_allocation; - MemCopy(result->GetChars(no_allocation), - string->GetChars(no_allocation) + offset, length); - return result; -} - Handle Factory::NewTwoByteInternalizedString( const Vector& str, uint32_t hash_field) { return AllocateTwoByteInternalizedString(str, hash_field); diff --git a/src/heap/factory.h b/src/heap/factory.h index bc8cd14b94..59d8f52e6d 100644 --- a/src/heap/factory.h +++ b/src/heap/factory.h @@ -245,8 +245,12 @@ class V8_EXPORT_PRIVATE Factory { Handle InternalizeOneByteString(const Vector& str); Handle InternalizeOneByteString(Handle, int from, int length); + Handle InternalizeTwoByteString(Handle, int from, + int length, + bool convert_to_one_byte = false); - Handle InternalizeTwoByteString(const Vector& str); + Handle InternalizeTwoByteString(const Vector& str, + bool convert_to_one_byte = false); template Handle InternalizeStringWithKey(StringTableKey* key); @@ -318,13 +322,15 @@ class V8_EXPORT_PRIVATE Factory { Handle NewOneByteInternalizedString(const Vector& str, uint32_t hash_field); - Handle NewOneByteInternalizedSubString( - Handle string, int offset, int length, - uint32_t hash_field); + Handle AllocateRawOneByteInternalizedString( + int length, uint32_t hash_field); Handle NewTwoByteInternalizedString(const Vector& str, uint32_t hash_field); + Handle AllocateRawTwoByteInternalizedString( + int length, uint32_t hash_field); + Handle NewInternalizedStringImpl(Handle string, int chars, uint32_t hash_field); @@ -1068,9 +1074,6 @@ class V8_EXPORT_PRIVATE Factory { Handle AllocateInternalizedStringImpl(T t, int chars, uint32_t hash_field); - Handle AllocateRawOneByteInternalizedString( - int length, uint32_t hash_field); - Handle AllocateTwoByteInternalizedString( const Vector& str, uint32_t hash_field); diff --git a/src/json/json-parser.cc b/src/json/json-parser.cc index ea8837423e..0949e18bdf 100644 --- a/src/json/json-parser.cc +++ b/src/json/json-parser.cc @@ -964,15 +964,16 @@ namespace { template bool Matches(const Vector& chars, Handle string) { - if (string.is_null()) return false; + DCHECK(!string.is_null()); - // Only supports internalized strings in their canonical representation (one - // byte encoded as two-byte will return false here). - if ((sizeof(Char) == 1) != string->IsOneByteRepresentation()) return false; if (chars.length() != string->length()) return false; DisallowHeapAllocation no_gc; - const Char* string_data = string->GetChars(no_gc); + if (string->IsOneByteRepresentation()) { + const uint8_t* string_data = string->GetChars(no_gc); + return CompareChars(chars.begin(), string_data, chars.length()) == 0; + } + const uint16_t* string_data = string->GetChars(no_gc); return CompareChars(chars.begin(), string_data, chars.length()) == 0; } @@ -991,7 +992,7 @@ Handle JsonParser::DecodeString( DecodeString(dest, string.start(), string.length()); } else { DCHECK_IMPLIES(string.internalize(), string.needs_conversion()); - i::CopyChars(dest, chars_ + string.start(), string.length()); + CopyChars(dest, chars_ + string.start(), string.length()); } Vector data(dest, string.length()); @@ -1013,13 +1014,6 @@ Handle JsonParser::MakeString(const JsonString& string, if (string.length() == 0) return factory()->empty_string(); if (sizeof(Char) == 1) { - if (V8_UNLIKELY(string.needs_conversion())) { - DCHECK(string.has_escape()); - Handle intermediate = - factory()->NewRawTwoByteString(string.length()).ToHandleChecked(); - return DecodeString(string, intermediate, hint); - } - if (string.internalize() && !string.has_escape()) { if (!hint.is_null()) { Vector data(chars_ + string.start(), string.length()); @@ -1035,12 +1029,13 @@ Handle JsonParser::MakeString(const JsonString& string, Vector::cast(chars)); } - Handle intermediate = - factory()->NewRawOneByteString(string.length()).ToHandleChecked(); - return DecodeString(string, intermediate, hint); - } + if (V8_UNLIKELY(string.needs_conversion())) { + DCHECK(string.has_escape()); + Handle intermediate = + factory()->NewRawTwoByteString(string.length()).ToHandleChecked(); + return DecodeString(string, intermediate, hint); + } - if (string.needs_conversion()) { Handle intermediate = factory()->NewRawOneByteString(string.length()).ToHandleChecked(); return DecodeString(string, intermediate, hint); @@ -1052,13 +1047,19 @@ Handle JsonParser::MakeString(const JsonString& string, if (Matches(data, hint)) return hint; } if (chars_may_relocate_) { - Handle substring = factory()->NewProperSubString( - source_, string.start(), string.start() + string.length()); - return factory()->InternalizeString(substring); + return factory()->InternalizeTwoByteString( + Handle::cast(source_), string.start(), + string.length(), string.needs_conversion()); } Vector chars(chars_ + string.start(), string.length()); return factory()->InternalizeTwoByteString( - Vector::cast(chars)); + Vector::cast(chars), string.needs_conversion()); + } + + if (string.needs_conversion()) { + Handle intermediate = + factory()->NewRawOneByteString(string.length()).ToHandleChecked(); + return DecodeString(string, intermediate, hint); } Handle intermediate = diff --git a/src/objects.cc b/src/objects.cc index fab575b646..8042a6e399 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -6790,6 +6790,8 @@ template Handle StringTable::LookupKey(Isolate* isolate, TwoByteStringKey* key); template Handle StringTable::LookupKey(Isolate* isolate, SeqOneByteSubStringKey* key); +template Handle StringTable::LookupKey(Isolate* isolate, + SeqTwoByteSubStringKey* key); Handle StringTable::AddKeyNoResize(Isolate* isolate, StringTableKey* key) { diff --git a/src/objects/string-inl.h b/src/objects/string-inl.h index 7868575772..47e79ff2c5 100644 --- a/src/objects/string-inl.h +++ b/src/objects/string-inl.h @@ -197,13 +197,17 @@ Char FlatStringReader::Get(int index) { template class SequentialStringKey final : public StringTableKey { public: - SequentialStringKey(const Vector& chars, uint64_t seed) + SequentialStringKey(const Vector& chars, uint64_t seed, + bool convert = false) : SequentialStringKey(StringHasher::HashSequentialString( chars.begin(), chars.length(), seed), - chars) {} + chars, convert) {} - SequentialStringKey(int hash, const Vector& chars) - : StringTableKey(hash, chars.length()), chars_(chars) {} + SequentialStringKey(int hash, const Vector& chars, + bool convert = false) + : StringTableKey(hash, chars.length()), + chars_(chars), + convert_(convert) {} bool IsMatch(String s) override { DisallowHeapAllocation no_gc; @@ -226,12 +230,14 @@ class SequentialStringKey final : public StringTableKey { private: Vector chars_; + bool convert_; }; using OneByteStringKey = SequentialStringKey; using TwoByteStringKey = SequentialStringKey; -class SeqOneByteSubStringKey final : public StringTableKey { +template +class SeqSubStringKey final : public StringTableKey { public: // VS 2017 on official builds gives this spurious warning: // warning C4789: buffer 'key' of size 16 bytes will be overrun; 4 bytes will @@ -241,9 +247,13 @@ class SeqOneByteSubStringKey final : public StringTableKey { #pragma warning(push) #pragma warning(disable : 4789) #endif - SeqOneByteSubStringKey(Isolate* isolate, Handle string, - int from, int len) - : StringTableKey(0, len), string_(string), from_(from) { + SeqSubStringKey(Isolate* isolate, + Handle::String> string, int from, + int len, bool convert = false) + : StringTableKey(0, len), + string_(string), + from_(from), + convert_(convert) { // We have to set the hash later. DisallowHeapAllocation no_gc; uint32_t hash = StringHasher::HashSequentialString( @@ -252,7 +262,8 @@ class SeqOneByteSubStringKey final : public StringTableKey { DCHECK_LE(0, length()); DCHECK_LE(from_ + length(), string_->length()); - DCHECK(string_->IsSeqOneByteString()); + DCHECK_EQ(string_->IsSeqOneByteString(), sizeof(Char) == 1); + DCHECK_EQ(string_->IsSeqTwoByteString(), sizeof(Char) == 2); } #if defined(V8_CC_MSVC) #pragma warning(pop) @@ -270,15 +281,33 @@ class SeqOneByteSubStringKey final : public StringTableKey { } Handle AsHandle(Isolate* isolate) override { - return isolate->factory()->NewOneByteInternalizedSubString( - string_, from_, length(), hash_field()); + if (sizeof(Char) == 1 || (sizeof(Char) == 2 && convert_)) { + Handle result = + isolate->factory()->AllocateRawOneByteInternalizedString( + length(), hash_field()); + DisallowHeapAllocation no_gc; + CopyChars(result->GetChars(no_gc), string_->GetChars(no_gc) + from_, + length()); + return result; + } + Handle result = + isolate->factory()->AllocateRawTwoByteInternalizedString(length(), + hash_field()); + DisallowHeapAllocation no_gc; + CopyChars(result->GetChars(no_gc), string_->GetChars(no_gc) + from_, + length()); + return result; } private: - Handle string_; + Handle::String> string_; int from_; + bool convert_; }; +using SeqOneByteSubStringKey = SeqSubStringKey; +using SeqTwoByteSubStringKey = SeqSubStringKey; + bool String::Equals(String other) { if (other == *this) return true; if (this->IsInternalizedString() && other->IsInternalizedString()) {