diff options
Diffstat (limited to 'deps/v8/src/objects/string-inl.h')
-rw-r--r-- | deps/v8/src/objects/string-inl.h | 113 |
1 files changed, 90 insertions, 23 deletions
diff --git a/deps/v8/src/objects/string-inl.h b/deps/v8/src/objects/string-inl.h index 9a75dd2d06..b4e28bd832 100644 --- a/deps/v8/src/objects/string-inl.h +++ b/deps/v8/src/objects/string-inl.h @@ -15,8 +15,8 @@ #include "src/objects/smi-inl.h" #include "src/objects/string-table-inl.h" #include "src/objects/string.h" -#include "src/security/external-pointer-inl.h" -#include "src/security/external-pointer.h" +#include "src/sandbox/external-pointer-inl.h" +#include "src/sandbox/external-pointer.h" #include "src/strings/string-hasher-inl.h" #include "src/utils/utils.h" @@ -190,9 +190,12 @@ bool StringShape::CanMigrateInParallel() const { // Shared ThinStrings do not migrate. return false; default: + // TODO(v8:12007): Set is_shared to true on internalized string when + // FLAG_shared_string_table is removed. + // // If you crashed here, you probably added a new shared string // type. Explicitly handle all shared string cases above. - DCHECK(!IsShared()); + DCHECK((FLAG_shared_string_table && IsInternalized()) || !IsShared()); return false; } } @@ -372,27 +375,26 @@ class SequentialStringKey final : public StringTableKey { return s.IsEqualTo<String::EqualityType::kNoLengthCheck>(chars_, isolate); } - Handle<String> AsHandle(Isolate* isolate) { + template <typename IsolateT> + void PrepareForInsertion(IsolateT* isolate) { if (sizeof(Char) == 1) { - return isolate->factory()->NewOneByteInternalizedString( + internalized_string_ = isolate->factory()->NewOneByteInternalizedString( base::Vector<const uint8_t>::cast(chars_), raw_hash_field()); + } else { + internalized_string_ = isolate->factory()->NewTwoByteInternalizedString( + base::Vector<const uint16_t>::cast(chars_), raw_hash_field()); } - return isolate->factory()->NewTwoByteInternalizedString( - base::Vector<const uint16_t>::cast(chars_), raw_hash_field()); } - Handle<String> AsHandle(LocalIsolate* isolate) { - if (sizeof(Char) == 1) { - return isolate->factory()->NewOneByteInternalizedString( - base::Vector<const uint8_t>::cast(chars_), raw_hash_field()); - } - return isolate->factory()->NewTwoByteInternalizedString( - base::Vector<const uint16_t>::cast(chars_), raw_hash_field()); + Handle<String> GetHandleForInsertion() { + DCHECK(!internalized_string_.is_null()); + return internalized_string_; } private: base::Vector<const Char> chars_; bool convert_; + Handle<String> internalized_string_; }; using OneByteStringKey = SequentialStringKey<uint8_t>; @@ -440,7 +442,7 @@ class SeqSubStringKey final : public StringTableKey { isolate); } - Handle<String> AsHandle(Isolate* isolate) { + void PrepareForInsertion(Isolate* isolate) { if (sizeof(Char) == 1 || (sizeof(Char) == 2 && convert_)) { Handle<SeqOneByteString> result = isolate->factory()->AllocateRawOneByteInternalizedString( @@ -448,7 +450,7 @@ class SeqSubStringKey final : public StringTableKey { DisallowGarbageCollection no_gc; CopyChars(result->GetChars(no_gc), string_->GetChars(no_gc) + from_, length()); - return result; + internalized_string_ = result; } Handle<SeqTwoByteString> result = isolate->factory()->AllocateRawTwoByteInternalizedString( @@ -456,13 +458,19 @@ class SeqSubStringKey final : public StringTableKey { DisallowGarbageCollection no_gc; CopyChars(result->GetChars(no_gc), string_->GetChars(no_gc) + from_, length()); - return result; + internalized_string_ = result; + } + + Handle<String> GetHandleForInsertion() { + DCHECK(!internalized_string_.is_null()); + return internalized_string_; } private: Handle<typename CharTraits<Char>::String> string_; int from_; bool convert_; + Handle<String> internalized_string_; }; using SeqOneByteSubStringKey = SeqSubStringKey<SeqOneByteString>; @@ -633,6 +641,7 @@ const Char* String::GetChars( access_guard); } +// static Handle<String> String::Flatten(Isolate* isolate, Handle<String> string, AllocationType allocation) { DisallowGarbageCollection no_gc; // Unhandlified code. @@ -662,6 +671,7 @@ Handle<String> String::Flatten(Isolate* isolate, Handle<String> string, return handle(s, isolate); } +// static Handle<String> String::Flatten(LocalIsolate* isolate, Handle<String> string, AllocationType allocation) { // We should never pass non-flat strings to String::Flatten when off-thread. @@ -707,7 +717,10 @@ String::FlatContent String::GetFlatContent( { Isolate* isolate; // We don't have to check read only strings as those won't move. - DCHECK_IMPLIES(GetIsolateFromHeapObject(*this, &isolate), + // + // TODO(v8:12007): Currently character data is never overwritten for + // shared strings. + DCHECK_IMPLIES(GetIsolateFromHeapObject(*this, &isolate) && !InSharedHeap(), ThreadId::Current() == isolate->thread_id()); } #endif @@ -715,6 +728,51 @@ String::FlatContent String::GetFlatContent( return GetFlatContent(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded()); } +String::FlatContent::FlatContent(const uint8_t* start, int length, + const DisallowGarbageCollection& no_gc) + : onebyte_start(start), length_(length), state_(ONE_BYTE), no_gc_(no_gc) { +#ifdef ENABLE_SLOW_DCHECKS + checksum_ = ComputeChecksum(); +#endif +} + +String::FlatContent::FlatContent(const base::uc16* start, int length, + const DisallowGarbageCollection& no_gc) + : twobyte_start(start), length_(length), state_(TWO_BYTE), no_gc_(no_gc) { +#ifdef ENABLE_SLOW_DCHECKS + checksum_ = ComputeChecksum(); +#endif +} + +String::FlatContent::~FlatContent() { + // When ENABLE_SLOW_DCHECKS, check the string contents did not change during + // the lifetime of the FlatContent. To avoid extra memory use, only the hash + // is checked instead of snapshotting the full character data. + // + // If you crashed here, it means something changed the character data of this + // FlatContent during its lifetime (e.g. GC relocated the string). This is + // almost always a bug. If you are certain it is not a bug, you can disable + // the checksum verification in the caller by calling + // UnsafeDisableChecksumVerification(). + SLOW_DCHECK(checksum_ == kChecksumVerificationDisabled || + checksum_ == ComputeChecksum()); +} + +#ifdef ENABLE_SLOW_DCHECKS +uint32_t String::FlatContent::ComputeChecksum() const { + constexpr uint64_t hashseed = 1; + uint32_t hash; + if (state_ == ONE_BYTE) { + hash = StringHasher::HashSequentialString(onebyte_start, length_, hashseed); + } else { + DCHECK_EQ(TWO_BYTE, state_); + hash = StringHasher::HashSequentialString(twobyte_start, length_, hashseed); + } + DCHECK_NE(kChecksumVerificationDisabled, hash); + return hash; +} +#endif + String::FlatContent String::GetFlatContent( const DisallowGarbageCollection& no_gc, const SharedStringAccessGuardIfNeeded& access_guard) { @@ -1046,13 +1104,15 @@ bool ExternalString::is_uncached() const { } void ExternalString::AllocateExternalPointerEntries(Isolate* isolate) { - InitExternalPointerField(kResourceOffset, isolate); + InitExternalPointerField(kResourceOffset, isolate, + kExternalStringResourceTag); if (is_uncached()) return; - InitExternalPointerField(kResourceDataOffset, isolate); + InitExternalPointerField(kResourceDataOffset, isolate, + kExternalStringResourceDataTag); } DEF_GETTER(ExternalString, resource_as_address, Address) { - Isolate* isolate = GetIsolateForHeapSandbox(*this); + Isolate* isolate = GetIsolateForSandbox(*this); return ReadExternalPointerField(kResourceOffset, isolate, kExternalStringResourceTag); } @@ -1348,7 +1408,7 @@ bool String::AsArrayIndex(uint32_t* index) { *index = ArrayIndexValueBits::decode(field); return true; } - if (IsHashFieldComputed(field) && (field & kIsNotIntegerIndexMask)) { + if (IsHashFieldComputed(field) && !IsIntegerIndex(field)) { return false; } return SlowAsArrayIndex(index); @@ -1360,7 +1420,7 @@ bool String::AsIntegerIndex(size_t* index) { *index = ArrayIndexValueBits::decode(field); return true; } - if (IsHashFieldComputed(field) && (field & kIsNotIntegerIndexMask)) { + if (IsHashFieldComputed(field) && !IsIntegerIndex(field)) { return false; } return SlowAsIntegerIndex(index); @@ -1434,6 +1494,13 @@ bool String::IsInPlaceInternalizable(InstanceType instance_type) { } } +// static +bool String::IsInPlaceInternalizableExcludingExternal( + InstanceType instance_type) { + return IsInPlaceInternalizable(instance_type) && + !InstanceTypeChecker::IsExternalString(instance_type); +} + } // namespace internal } // namespace v8 |