Commit 6e2078d6 authored by Shu-yu Guo's avatar Shu-yu Guo Committed by V8 LUCI CQ

[string] Extend StringShape to query the shared bit

Rename StringShape::full_representation_tag to
StringShape::representation_and_encoding_tag, since the full
representation tag now includes the shared bit.

There are no users of the new method in this CL; this is split out to
make subsequent shared string CLs smaller.

Bug: v8:12007
Change-Id: Ic4ac0241fd9846241e85b4a094dfee6d201ba42b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3313428Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarPatrick Thier <pthier@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78253}
parent b8bc9b23
...@@ -218,7 +218,7 @@ class Internals { ...@@ -218,7 +218,7 @@ class Internals {
static const int kEmbedderDataSlotRawPayloadOffset = kApiTaggedSize; static const int kEmbedderDataSlotRawPayloadOffset = kApiTaggedSize;
#endif #endif
static const int kNativeContextEmbedderDataOffset = 6 * kApiTaggedSize; static const int kNativeContextEmbedderDataOffset = 6 * kApiTaggedSize;
static const int kFullStringRepresentationMask = 0x0f; static const int kStringRepresentationAndEncodingMask = 0x0f;
static const int kStringEncodingMask = 0x8; static const int kStringEncodingMask = 0x8;
static const int kExternalTwoByteRepresentationTag = 0x02; static const int kExternalTwoByteRepresentationTag = 0x02;
static const int kExternalOneByteRepresentationTag = 0x0a; static const int kExternalOneByteRepresentationTag = 0x0a;
...@@ -337,7 +337,7 @@ class Internals { ...@@ -337,7 +337,7 @@ class Internals {
} }
V8_INLINE static bool IsExternalTwoByteString(int instance_type) { V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
int representation = (instance_type & kFullStringRepresentationMask); int representation = (instance_type & kStringRepresentationAndEncodingMask);
return representation == kExternalTwoByteRepresentationTag; return representation == kExternalTwoByteRepresentationTag;
} }
......
...@@ -806,7 +806,7 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBase( ...@@ -806,7 +806,7 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBase(
using A = internal::Address; using A = internal::Address;
using I = internal::Internals; using I = internal::Internals;
A obj = *reinterpret_cast<const A*>(this); A obj = *reinterpret_cast<const A*>(this);
int type = I::GetInstanceType(obj) & I::kFullStringRepresentationMask; int type = I::GetInstanceType(obj) & I::kStringRepresentationAndEncodingMask;
*encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask); *encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
ExternalStringResourceBase* resource; ExternalStringResourceBase* resource;
if (type == I::kExternalOneByteRepresentationTag || if (type == I::kExternalOneByteRepresentationTag ||
......
...@@ -5870,7 +5870,8 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBaseSlow( ...@@ -5870,7 +5870,8 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBaseSlow(
} }
internal::Address string = str.ptr(); internal::Address string = str.ptr();
int type = I::GetInstanceType(string) & I::kFullStringRepresentationMask; int type =
I::GetInstanceType(string) & I::kStringRepresentationAndEncodingMask;
*encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask); *encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
if (i::StringShape(str).IsExternalOneByte() || if (i::StringShape(str).IsExternalOneByte() ||
i::StringShape(str).IsExternalTwoByte()) { i::StringShape(str).IsExternalTwoByte()) {
......
...@@ -85,6 +85,9 @@ const uint32_t kInternalizedTag = 0; ...@@ -85,6 +85,9 @@ const uint32_t kInternalizedTag = 0;
const uint32_t kSharedStringMask = 1 << 6; const uint32_t kSharedStringMask = 1 << 6;
const uint32_t kSharedStringTag = 1 << 6; const uint32_t kSharedStringTag = 1 << 6;
constexpr uint32_t kStringRepresentationEncodingAndSharedMask =
kStringRepresentationAndEncodingMask | kSharedStringMask;
// A ConsString with an empty string as the right side is a candidate // A ConsString with an empty string as the right side is a candidate
// for being shortcut by the garbage collector. We don't allocate any // for being shortcut by the garbage collector. We don't allocate any
// non-flat internalized strings, so we do not shortcut them thereby // non-flat internalized strings, so we do not shortcut them thereby
......
...@@ -179,6 +179,24 @@ bool StringShape::IsShared() const { ...@@ -179,6 +179,24 @@ bool StringShape::IsShared() const {
(FLAG_shared_string_table && IsInternalized()); (FLAG_shared_string_table && IsInternalized());
} }
bool StringShape::CanMigrateInParallel() const {
switch (representation_encoding_and_shared_tag()) {
case kSeqOneByteStringTag | kSharedStringTag:
case kSeqTwoByteStringTag | kSharedStringTag:
// Shared SeqStrings can migrate to ThinStrings.
return true;
case kThinStringTag | kOneByteStringTag | kSharedStringTag:
case kThinStringTag | kTwoByteStringTag | kSharedStringTag:
// Shared ThinStrings do not migrate.
return false;
default:
// If you crashed here, you probably added a new shared string
// type. Explicitly handle all shared string cases above.
DCHECK(!IsShared());
return false;
}
}
StringRepresentationTag StringShape::representation_tag() const { StringRepresentationTag StringShape::representation_tag() const {
uint32_t tag = (type_ & kStringRepresentationMask); uint32_t tag = (type_ & kStringRepresentationMask);
return static_cast<StringRepresentationTag>(tag); return static_cast<StringRepresentationTag>(tag);
...@@ -188,26 +206,30 @@ uint32_t StringShape::encoding_tag() const { ...@@ -188,26 +206,30 @@ uint32_t StringShape::encoding_tag() const {
return type_ & kStringEncodingMask; return type_ & kStringEncodingMask;
} }
uint32_t StringShape::full_representation_tag() const { uint32_t StringShape::representation_and_encoding_tag() const {
return (type_ & (kStringRepresentationAndEncodingMask)); return (type_ & (kStringRepresentationAndEncodingMask));
} }
uint32_t StringShape::representation_encoding_and_shared_tag() const {
return (type_ & (kStringRepresentationEncodingAndSharedMask));
}
STATIC_ASSERT((kStringRepresentationAndEncodingMask) == STATIC_ASSERT((kStringRepresentationAndEncodingMask) ==
Internals::kFullStringRepresentationMask); Internals::kStringRepresentationAndEncodingMask);
STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) == STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
Internals::kStringEncodingMask); Internals::kStringEncodingMask);
bool StringShape::IsSequentialOneByte() const { bool StringShape::IsSequentialOneByte() const {
return full_representation_tag() == kSeqOneByteStringTag; return representation_and_encoding_tag() == kSeqOneByteStringTag;
} }
bool StringShape::IsSequentialTwoByte() const { bool StringShape::IsSequentialTwoByte() const {
return full_representation_tag() == kSeqTwoByteStringTag; return representation_and_encoding_tag() == kSeqTwoByteStringTag;
} }
bool StringShape::IsExternalOneByte() const { bool StringShape::IsExternalOneByte() const {
return full_representation_tag() == kExternalOneByteStringTag; return representation_and_encoding_tag() == kExternalOneByteStringTag;
} }
STATIC_ASSERT(kExternalOneByteStringTag == STATIC_ASSERT(kExternalOneByteStringTag ==
...@@ -216,7 +238,7 @@ STATIC_ASSERT(kExternalOneByteStringTag == ...@@ -216,7 +238,7 @@ STATIC_ASSERT(kExternalOneByteStringTag ==
STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag); STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
bool StringShape::IsExternalTwoByte() const { bool StringShape::IsExternalTwoByte() const {
return full_representation_tag() == kExternalTwoByteStringTag; return representation_and_encoding_tag() == kExternalTwoByteStringTag;
} }
STATIC_ASSERT(kExternalTwoByteStringTag == STATIC_ASSERT(kExternalTwoByteStringTag ==
...@@ -226,7 +248,7 @@ STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag); ...@@ -226,7 +248,7 @@ STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
template <typename TDispatcher, typename TResult, typename... TArgs> template <typename TDispatcher, typename TResult, typename... TArgs>
inline TResult StringShape::DispatchToSpecificTypeWithoutCast(TArgs&&... args) { inline TResult StringShape::DispatchToSpecificTypeWithoutCast(TArgs&&... args) {
switch (full_representation_tag()) { switch (representation_and_encoding_tag()) {
case kSeqStringTag | kOneByteStringTag: case kSeqStringTag | kOneByteStringTag:
return TDispatcher::HandleSeqOneByteString(std::forward<TArgs>(args)...); return TDispatcher::HandleSeqOneByteString(std::forward<TArgs>(args)...);
case kSeqStringTag | kTwoByteStringTag: case kSeqStringTag | kTwoByteStringTag:
...@@ -655,7 +677,7 @@ base::Optional<String::FlatContent> String::TryGetFlatContentFromDirectString( ...@@ -655,7 +677,7 @@ base::Optional<String::FlatContent> String::TryGetFlatContentFromDirectString(
DCHECK_GE(offset, 0); DCHECK_GE(offset, 0);
DCHECK_GE(length, 0); DCHECK_GE(length, 0);
DCHECK_LE(offset + length, string.length()); DCHECK_LE(offset + length, string.length());
switch (StringShape{string, cage_base}.full_representation_tag()) { switch (StringShape{string, cage_base}.representation_and_encoding_tag()) {
case kSeqOneByteStringTag: case kSeqOneByteStringTag:
return FlatContent( return FlatContent(
SeqOneByteString::cast(string).GetChars(no_gc, access_guard) + offset, SeqOneByteString::cast(string).GetChars(no_gc, access_guard) + offset,
...@@ -825,7 +847,8 @@ ConsString String::VisitFlat( ...@@ -825,7 +847,8 @@ ConsString String::VisitFlat(
DCHECK(offset <= length); DCHECK(offset <= length);
PtrComprCageBase cage_base = GetPtrComprCageBase(string); PtrComprCageBase cage_base = GetPtrComprCageBase(string);
while (true) { while (true) {
int32_t tag = StringShape(string, cage_base).full_representation_tag(); int32_t tag =
StringShape(string, cage_base).representation_and_encoding_tag();
switch (tag) { switch (tag) {
case kSeqOneByteStringTag: case kSeqOneByteStringTag:
visitor->VisitOneByteString( visitor->VisitOneByteString(
......
...@@ -711,7 +711,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int start, int length, ...@@ -711,7 +711,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int start, int length,
DCHECK_LT(0, length); DCHECK_LT(0, length);
DCHECK_LE(0, start); DCHECK_LE(0, start);
DCHECK_LE(length, source.length()); DCHECK_LE(length, source.length());
switch (StringShape(source, cage_base).full_representation_tag()) { switch (StringShape(source, cage_base).representation_and_encoding_tag()) {
case kOneByteStringTag | kExternalStringTag: case kOneByteStringTag | kExternalStringTag:
CopyChars( CopyChars(
sink, sink,
...@@ -1815,7 +1815,7 @@ const byte* String::AddressOfCharacterAt( ...@@ -1815,7 +1815,7 @@ const byte* String::AddressOfCharacterAt(
} }
CHECK_LE(0, start_index); CHECK_LE(0, start_index);
CHECK_LE(start_index, subject.length()); CHECK_LE(start_index, subject.length());
switch (shape.full_representation_tag()) { switch (shape.representation_and_encoding_tag()) {
case kOneByteStringTag | kSeqStringTag: case kOneByteStringTag | kSeqStringTag:
return reinterpret_cast<const byte*>( return reinterpret_cast<const byte*>(
SeqOneByteString::cast(subject).GetChars(no_gc) + start_index); SeqOneByteString::cast(subject).GetChars(no_gc) + start_index);
......
...@@ -60,9 +60,11 @@ class StringShape { ...@@ -60,9 +60,11 @@ class StringShape {
V8_INLINE bool IsSequentialTwoByte() const; V8_INLINE bool IsSequentialTwoByte() const;
V8_INLINE bool IsInternalized() const; V8_INLINE bool IsInternalized() const;
V8_INLINE bool IsShared() const; V8_INLINE bool IsShared() const;
V8_INLINE bool CanMigrateInParallel() const;
V8_INLINE StringRepresentationTag representation_tag() const; V8_INLINE StringRepresentationTag representation_tag() const;
V8_INLINE uint32_t encoding_tag() const; V8_INLINE uint32_t encoding_tag() const;
V8_INLINE uint32_t full_representation_tag() const; V8_INLINE uint32_t representation_and_encoding_tag() const;
V8_INLINE uint32_t representation_encoding_and_shared_tag() const;
#ifdef DEBUG #ifdef DEBUG
inline uint32_t type() const { return type_; } inline uint32_t type() const { return type_; }
inline void invalidate() { valid_ = false; } inline void invalidate() { valid_ = false; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment