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 {
static const int kEmbedderDataSlotRawPayloadOffset = kApiTaggedSize;
#endif
static const int kNativeContextEmbedderDataOffset = 6 * kApiTaggedSize;
static const int kFullStringRepresentationMask = 0x0f;
static const int kStringRepresentationAndEncodingMask = 0x0f;
static const int kStringEncodingMask = 0x8;
static const int kExternalTwoByteRepresentationTag = 0x02;
static const int kExternalOneByteRepresentationTag = 0x0a;
......@@ -337,7 +337,7 @@ class Internals {
}
V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
int representation = (instance_type & kFullStringRepresentationMask);
int representation = (instance_type & kStringRepresentationAndEncodingMask);
return representation == kExternalTwoByteRepresentationTag;
}
......
......@@ -806,7 +806,7 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBase(
using A = internal::Address;
using I = internal::Internals;
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);
ExternalStringResourceBase* resource;
if (type == I::kExternalOneByteRepresentationTag ||
......
......@@ -5870,7 +5870,8 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBaseSlow(
}
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);
if (i::StringShape(str).IsExternalOneByte() ||
i::StringShape(str).IsExternalTwoByte()) {
......
......@@ -85,6 +85,9 @@ const uint32_t kInternalizedTag = 0;
const uint32_t kSharedStringMask = 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
// for being shortcut by the garbage collector. We don't allocate any
// non-flat internalized strings, so we do not shortcut them thereby
......
......@@ -179,6 +179,24 @@ bool StringShape::IsShared() const {
(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 {
uint32_t tag = (type_ & kStringRepresentationMask);
return static_cast<StringRepresentationTag>(tag);
......@@ -188,26 +206,30 @@ uint32_t StringShape::encoding_tag() const {
return type_ & kStringEncodingMask;
}
uint32_t StringShape::full_representation_tag() const {
uint32_t StringShape::representation_and_encoding_tag() const {
return (type_ & (kStringRepresentationAndEncodingMask));
}
uint32_t StringShape::representation_encoding_and_shared_tag() const {
return (type_ & (kStringRepresentationEncodingAndSharedMask));
}
STATIC_ASSERT((kStringRepresentationAndEncodingMask) ==
Internals::kFullStringRepresentationMask);
Internals::kStringRepresentationAndEncodingMask);
STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
Internals::kStringEncodingMask);
bool StringShape::IsSequentialOneByte() const {
return full_representation_tag() == kSeqOneByteStringTag;
return representation_and_encoding_tag() == kSeqOneByteStringTag;
}
bool StringShape::IsSequentialTwoByte() const {
return full_representation_tag() == kSeqTwoByteStringTag;
return representation_and_encoding_tag() == kSeqTwoByteStringTag;
}
bool StringShape::IsExternalOneByte() const {
return full_representation_tag() == kExternalOneByteStringTag;
return representation_and_encoding_tag() == kExternalOneByteStringTag;
}
STATIC_ASSERT(kExternalOneByteStringTag ==
......@@ -216,7 +238,7 @@ STATIC_ASSERT(kExternalOneByteStringTag ==
STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
bool StringShape::IsExternalTwoByte() const {
return full_representation_tag() == kExternalTwoByteStringTag;
return representation_and_encoding_tag() == kExternalTwoByteStringTag;
}
STATIC_ASSERT(kExternalTwoByteStringTag ==
......@@ -226,7 +248,7 @@ STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
template <typename TDispatcher, typename TResult, typename... TArgs>
inline TResult StringShape::DispatchToSpecificTypeWithoutCast(TArgs&&... args) {
switch (full_representation_tag()) {
switch (representation_and_encoding_tag()) {
case kSeqStringTag | kOneByteStringTag:
return TDispatcher::HandleSeqOneByteString(std::forward<TArgs>(args)...);
case kSeqStringTag | kTwoByteStringTag:
......@@ -655,7 +677,7 @@ base::Optional<String::FlatContent> String::TryGetFlatContentFromDirectString(
DCHECK_GE(offset, 0);
DCHECK_GE(length, 0);
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:
return FlatContent(
SeqOneByteString::cast(string).GetChars(no_gc, access_guard) + offset,
......@@ -825,7 +847,8 @@ ConsString String::VisitFlat(
DCHECK(offset <= length);
PtrComprCageBase cage_base = GetPtrComprCageBase(string);
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) {
case kSeqOneByteStringTag:
visitor->VisitOneByteString(
......
......@@ -711,7 +711,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int start, int length,
DCHECK_LT(0, length);
DCHECK_LE(0, start);
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:
CopyChars(
sink,
......@@ -1815,7 +1815,7 @@ const byte* String::AddressOfCharacterAt(
}
CHECK_LE(0, start_index);
CHECK_LE(start_index, subject.length());
switch (shape.full_representation_tag()) {
switch (shape.representation_and_encoding_tag()) {
case kOneByteStringTag | kSeqStringTag:
return reinterpret_cast<const byte*>(
SeqOneByteString::cast(subject).GetChars(no_gc) + start_index);
......
......@@ -60,9 +60,11 @@ class StringShape {
V8_INLINE bool IsSequentialTwoByte() const;
V8_INLINE bool IsInternalized() const;
V8_INLINE bool IsShared() const;
V8_INLINE bool CanMigrateInParallel() const;
V8_INLINE StringRepresentationTag representation_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
inline uint32_t type() const { return type_; }
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