[string] Add PtrComprCageBase to WriteToFlat, HashString, and Get
Also a couple of microoptimizations and consistent formatting in WriteToFlat. Change-Id: Ie642a4b8e0819b04603ee5c5d12eebccf6a2d59c Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3151963 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/main@{#76799}
This commit is contained in:
parent
c6bb56302c
commit
fbf51c7ad9
@ -645,9 +645,10 @@ MaybeHandle<String> FactoryBase<Impl>::NewConsString(
|
|||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
SharedStringAccessGuardIfNeeded access_guard(isolate());
|
SharedStringAccessGuardIfNeeded access_guard(isolate());
|
||||||
base::uc16* sink = result->GetChars(no_gc, access_guard);
|
base::uc16* sink = result->GetChars(no_gc, access_guard);
|
||||||
String::WriteToFlat(*left, sink, 0, left->length(), access_guard);
|
String::WriteToFlat(*left, sink, 0, left->length(), isolate(),
|
||||||
String::WriteToFlat(*right, sink + left->length(), 0, right->length(),
|
|
||||||
access_guard);
|
access_guard);
|
||||||
|
String::WriteToFlat(*right, sink + left->length(), 0, right->length(),
|
||||||
|
isolate(), access_guard);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1425,7 +1425,7 @@ base::Optional<double> TryStringToDouble(LocalIsolate* isolate,
|
|||||||
const int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
|
const int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
|
||||||
auto buffer = std::make_unique<base::uc16[]>(max_length_for_conversion);
|
auto buffer = std::make_unique<base::uc16[]>(max_length_for_conversion);
|
||||||
SharedStringAccessGuardIfNeeded access_guard(isolate);
|
SharedStringAccessGuardIfNeeded access_guard(isolate);
|
||||||
String::WriteToFlat(*object, buffer.get(), 0, length, access_guard);
|
String::WriteToFlat(*object, buffer.get(), 0, length, isolate, access_guard);
|
||||||
base::Vector<const base::uc16> v(buffer.get(), length);
|
base::Vector<const base::uc16> v(buffer.get(), length);
|
||||||
return StringToDouble(v, flags);
|
return StringToDouble(v, flags);
|
||||||
}
|
}
|
||||||
|
@ -1507,7 +1507,8 @@ ConcurrentLookupIterator::Result ConcurrentLookupIterator::TryGetOwnChar(
|
|||||||
uint16_t charcode;
|
uint16_t charcode;
|
||||||
{
|
{
|
||||||
SharedStringAccessGuardIfNeeded access_guard(local_isolate);
|
SharedStringAccessGuardIfNeeded access_guard(local_isolate);
|
||||||
charcode = string.Get(static_cast<int>(index));
|
charcode = string.Get(static_cast<int>(index), PtrComprCageBase(isolate),
|
||||||
|
access_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (charcode > unibrow::Latin1::kMaxChar) return kGaveUp;
|
if (charcode > unibrow::Latin1::kMaxChar) return kGaveUp;
|
||||||
|
@ -119,6 +119,12 @@ StringShape::StringShape(const String str)
|
|||||||
DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
|
DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringShape::StringShape(const String str, PtrComprCageBase cage_base)
|
||||||
|
: type_(str.map(cage_base, kAcquireLoad).instance_type()) {
|
||||||
|
set_valid();
|
||||||
|
DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
|
||||||
|
}
|
||||||
|
|
||||||
StringShape::StringShape(Map map) : type_(map.instance_type()) {
|
StringShape::StringShape(Map map) : type_(map.instance_type()) {
|
||||||
set_valid();
|
set_valid();
|
||||||
DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
|
DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
|
||||||
@ -617,45 +623,53 @@ Handle<String> String::Flatten(LocalIsolate* isolate, Handle<String> string,
|
|||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t String::Get(int index) const {
|
||||||
|
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
|
||||||
|
return GetImpl(index, GetPtrComprCageBase(*this),
|
||||||
|
SharedStringAccessGuardIfNeeded::NotNeeded());
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t String::Get(int index, Isolate* isolate) const {
|
uint16_t String::Get(int index, Isolate* isolate) const {
|
||||||
SharedStringAccessGuardIfNeeded scope(isolate);
|
SharedStringAccessGuardIfNeeded scope(isolate);
|
||||||
return GetImpl(index, scope);
|
return GetImpl(index, isolate, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t String::Get(int index, LocalIsolate* local_isolate) const {
|
uint16_t String::Get(int index, LocalIsolate* local_isolate) const {
|
||||||
SharedStringAccessGuardIfNeeded scope(local_isolate);
|
SharedStringAccessGuardIfNeeded scope(local_isolate);
|
||||||
return GetImpl(index, scope);
|
return GetImpl(index, local_isolate, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t String::Get(
|
uint16_t String::Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
int index, PtrComprCageBase cage_base,
|
||||||
return GetImpl(index, access_guard);
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
|
return GetImpl(index, cage_base, access_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t String::GetImpl(
|
uint16_t String::GetImpl(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
DCHECK(index >= 0 && index < length());
|
DCHECK(index >= 0 && index < length());
|
||||||
|
|
||||||
class StringGetDispatcher : public AllStatic {
|
class StringGetDispatcher : public AllStatic {
|
||||||
public:
|
public:
|
||||||
#define DEFINE_METHOD(Type) \
|
#define DEFINE_METHOD(Type) \
|
||||||
static inline uint16_t Handle##Type( \
|
static inline uint16_t Handle##Type( \
|
||||||
Type str, int index, \
|
Type str, int index, PtrComprCageBase cage_base, \
|
||||||
const SharedStringAccessGuardIfNeeded& access_guard) { \
|
const SharedStringAccessGuardIfNeeded& access_guard) { \
|
||||||
return str.Get(index, access_guard); \
|
return str.Get(index, cage_base, access_guard); \
|
||||||
}
|
}
|
||||||
STRING_CLASS_TYPES(DEFINE_METHOD)
|
STRING_CLASS_TYPES(DEFINE_METHOD)
|
||||||
#undef DEFINE_METHOD
|
#undef DEFINE_METHOD
|
||||||
static inline uint16_t HandleInvalidString(
|
static inline uint16_t HandleInvalidString(
|
||||||
String str, int index,
|
String str, int index, PtrComprCageBase cage_base,
|
||||||
const SharedStringAccessGuardIfNeeded& access_guard) {
|
const SharedStringAccessGuardIfNeeded& access_guard) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return StringShape(*this)
|
return StringShape(*this)
|
||||||
.DispatchToSpecificType<StringGetDispatcher, uint16_t>(*this, index,
|
.DispatchToSpecificType<StringGetDispatcher, uint16_t>(
|
||||||
access_guard);
|
*this, index, cage_base, access_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void String::Set(int index, uint16_t value) {
|
void String::Set(int index, uint16_t value) {
|
||||||
@ -667,9 +681,11 @@ void String::Set(int index, uint16_t value) {
|
|||||||
: SeqTwoByteString::cast(*this).SeqTwoByteStringSet(index, value);
|
: SeqTwoByteString::cast(*this).SeqTwoByteStringSet(index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool String::IsFlat() const {
|
bool String::IsFlat() const { return IsFlat(GetPtrComprCageBase(*this)); }
|
||||||
if (!StringShape(*this).IsCons()) return true;
|
|
||||||
return ConsString::cast(*this).second().length() == 0;
|
bool String::IsFlat(PtrComprCageBase cage_base) const {
|
||||||
|
if (!StringShape(*this, cage_base).IsCons()) return true;
|
||||||
|
return ConsString::cast(*this).second(cage_base).length() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String String::GetUnderlying() const {
|
String String::GetUnderlying() const {
|
||||||
@ -771,11 +787,13 @@ inline base::Vector<const base::uc16> String::GetCharVector(
|
|||||||
|
|
||||||
uint8_t SeqOneByteString::Get(int index) const {
|
uint8_t SeqOneByteString::Get(int index) const {
|
||||||
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
|
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
|
||||||
return Get(index, SharedStringAccessGuardIfNeeded::NotNeeded());
|
return Get(index, GetPtrComprCageBase(*this),
|
||||||
|
SharedStringAccessGuardIfNeeded::NotNeeded());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t SeqOneByteString::Get(
|
uint8_t SeqOneByteString::Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
USE(access_guard);
|
USE(access_guard);
|
||||||
DCHECK(index >= 0 && index < length());
|
DCHECK(index >= 0 && index < length());
|
||||||
return ReadField<byte>(kHeaderSize + index * kCharSize);
|
return ReadField<byte>(kHeaderSize + index * kCharSize);
|
||||||
@ -825,7 +843,8 @@ base::uc16* SeqTwoByteString::GetChars(
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t SeqTwoByteString::Get(
|
uint16_t SeqTwoByteString::Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
USE(access_guard);
|
USE(access_guard);
|
||||||
DCHECK(index >= 0 && index < length());
|
DCHECK(index >= 0 && index < length());
|
||||||
return ReadField<uint16_t>(kHeaderSize + index * kShortSize);
|
return ReadField<uint16_t>(kHeaderSize + index * kShortSize);
|
||||||
@ -977,7 +996,8 @@ const uint8_t* ExternalOneByteString::GetChars() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ExternalOneByteString::Get(
|
uint8_t ExternalOneByteString::Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
USE(access_guard);
|
USE(access_guard);
|
||||||
DCHECK(index >= 0 && index < length());
|
DCHECK(index >= 0 && index < length());
|
||||||
return GetChars()[index];
|
return GetChars()[index];
|
||||||
@ -1044,7 +1064,8 @@ const uint16_t* ExternalTwoByteString::GetChars() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ExternalTwoByteString::Get(
|
uint16_t ExternalTwoByteString::Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
USE(access_guard);
|
USE(access_guard);
|
||||||
DCHECK(index >= 0 && index < length());
|
DCHECK(index >= 0 && index < length());
|
||||||
return GetChars()[index];
|
return GetChars()[index];
|
||||||
|
@ -647,53 +647,52 @@ std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
|
|||||||
template <typename sinkchar>
|
template <typename sinkchar>
|
||||||
void String::WriteToFlat(String source, sinkchar* sink, int from, int to) {
|
void String::WriteToFlat(String source, sinkchar* sink, int from, int to) {
|
||||||
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(source));
|
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(source));
|
||||||
return WriteToFlat(source, sink, from, to,
|
return WriteToFlat(source, sink, from, to, GetPtrComprCageBase(source),
|
||||||
SharedStringAccessGuardIfNeeded::NotNeeded());
|
SharedStringAccessGuardIfNeeded::NotNeeded());
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
template <typename sinkchar>
|
template <typename sinkchar>
|
||||||
void String::WriteToFlat(String source, sinkchar* sink, int from, int to,
|
void String::WriteToFlat(String source, sinkchar* sink, int from, int to,
|
||||||
|
PtrComprCageBase cage_base,
|
||||||
const SharedStringAccessGuardIfNeeded& access_guard) {
|
const SharedStringAccessGuardIfNeeded& access_guard) {
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
while (from < to) {
|
if (from == to) return;
|
||||||
|
while (true) {
|
||||||
|
DCHECK_LT(from, to);
|
||||||
DCHECK_LE(0, from);
|
DCHECK_LE(0, from);
|
||||||
DCHECK_LE(to, source.length());
|
DCHECK_LE(to, source.length());
|
||||||
switch (StringShape(source).full_representation_tag()) {
|
switch (StringShape(source, cage_base).full_representation_tag()) {
|
||||||
case kOneByteStringTag | kExternalStringTag: {
|
case kOneByteStringTag | kExternalStringTag:
|
||||||
CopyChars(sink, ExternalOneByteString::cast(source).GetChars() + from,
|
CopyChars(sink, ExternalOneByteString::cast(source).GetChars() + from,
|
||||||
to - from);
|
to - from);
|
||||||
return;
|
return;
|
||||||
}
|
case kTwoByteStringTag | kExternalStringTag:
|
||||||
case kTwoByteStringTag | kExternalStringTag: {
|
CopyChars(sink, ExternalTwoByteString::cast(source).GetChars() + from,
|
||||||
const base::uc16* data = ExternalTwoByteString::cast(source).GetChars();
|
to - from);
|
||||||
CopyChars(sink, data + from, to - from);
|
|
||||||
return;
|
return;
|
||||||
}
|
case kOneByteStringTag | kSeqStringTag:
|
||||||
case kOneByteStringTag | kSeqStringTag: {
|
|
||||||
CopyChars(
|
CopyChars(
|
||||||
sink,
|
sink,
|
||||||
SeqOneByteString::cast(source).GetChars(no_gc, access_guard) + from,
|
SeqOneByteString::cast(source).GetChars(no_gc, access_guard) + from,
|
||||||
to - from);
|
to - from);
|
||||||
return;
|
return;
|
||||||
}
|
case kTwoByteStringTag | kSeqStringTag:
|
||||||
case kTwoByteStringTag | kSeqStringTag: {
|
|
||||||
CopyChars(
|
CopyChars(
|
||||||
sink,
|
sink,
|
||||||
SeqTwoByteString::cast(source).GetChars(no_gc, access_guard) + from,
|
SeqTwoByteString::cast(source).GetChars(no_gc, access_guard) + from,
|
||||||
to - from);
|
to - from);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
case kOneByteStringTag | kConsStringTag:
|
case kOneByteStringTag | kConsStringTag:
|
||||||
case kTwoByteStringTag | kConsStringTag: {
|
case kTwoByteStringTag | kConsStringTag: {
|
||||||
ConsString cons_string = ConsString::cast(source);
|
ConsString cons_string = ConsString::cast(source);
|
||||||
String first = cons_string.first();
|
String first = cons_string.first(cage_base);
|
||||||
int boundary = first.length();
|
int boundary = first.length();
|
||||||
if (to - boundary >= boundary - from) {
|
if (to - boundary >= boundary - from) {
|
||||||
// Right hand side is longer. Recurse over left.
|
// Right hand side is longer. Recurse over left.
|
||||||
if (from < boundary) {
|
if (from < boundary) {
|
||||||
WriteToFlat(first, sink, from, boundary, access_guard);
|
WriteToFlat(first, sink, from, boundary, cage_base, access_guard);
|
||||||
if (from == 0 && cons_string.second() == first) {
|
if (from == 0 && cons_string.second(cage_base) == first) {
|
||||||
CopyChars(sink + boundary, sink, boundary);
|
CopyChars(sink + boundary, sink, boundary);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -703,46 +702,50 @@ void String::WriteToFlat(String source, sinkchar* sink, int from, int to,
|
|||||||
from -= boundary;
|
from -= boundary;
|
||||||
}
|
}
|
||||||
to -= boundary;
|
to -= boundary;
|
||||||
source = cons_string.second();
|
source = cons_string.second(cage_base);
|
||||||
} else {
|
} else {
|
||||||
// Left hand side is longer. Recurse over right.
|
// Left hand side is longer. Recurse over right.
|
||||||
if (to > boundary) {
|
if (to > boundary) {
|
||||||
String second = cons_string.second();
|
String second = cons_string.second(cage_base);
|
||||||
// When repeatedly appending to a string, we get a cons string that
|
// When repeatedly appending to a string, we get a cons string that
|
||||||
// is unbalanced to the left, a list, essentially. We inline the
|
// is unbalanced to the left, a list, essentially. We inline the
|
||||||
// common case of sequential one-byte right child.
|
// common case of sequential one-byte right child.
|
||||||
if (to - boundary == 1) {
|
if (to - boundary == 1) {
|
||||||
sink[boundary - from] = static_cast<sinkchar>(second.Get(0));
|
sink[boundary - from] =
|
||||||
} else if (second.IsSeqOneByteString()) {
|
static_cast<sinkchar>(second.Get(0, cage_base, access_guard));
|
||||||
|
} else if (second.IsSeqOneByteString(cage_base)) {
|
||||||
CopyChars(
|
CopyChars(
|
||||||
sink + boundary - from,
|
sink + boundary - from,
|
||||||
SeqOneByteString::cast(second).GetChars(no_gc, access_guard),
|
SeqOneByteString::cast(second).GetChars(no_gc, access_guard),
|
||||||
to - boundary);
|
to - boundary);
|
||||||
} else {
|
} else {
|
||||||
WriteToFlat(second, sink + boundary - from, 0, to - boundary,
|
WriteToFlat(second, sink + boundary - from, 0, to - boundary,
|
||||||
access_guard);
|
cage_base, access_guard);
|
||||||
}
|
}
|
||||||
to = boundary;
|
to = boundary;
|
||||||
}
|
}
|
||||||
source = first;
|
source = first;
|
||||||
}
|
}
|
||||||
break;
|
if (from == to) return;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
case kOneByteStringTag | kSlicedStringTag:
|
case kOneByteStringTag | kSlicedStringTag:
|
||||||
case kTwoByteStringTag | kSlicedStringTag: {
|
case kTwoByteStringTag | kSlicedStringTag: {
|
||||||
SlicedString slice = SlicedString::cast(source);
|
SlicedString slice = SlicedString::cast(source);
|
||||||
unsigned offset = slice.offset();
|
unsigned offset = slice.offset();
|
||||||
WriteToFlat(slice.parent(), sink, from + offset, to + offset,
|
source = slice.parent(cage_base);
|
||||||
access_guard);
|
from += offset;
|
||||||
return;
|
to += offset;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
case kOneByteStringTag | kThinStringTag:
|
case kOneByteStringTag | kThinStringTag:
|
||||||
case kTwoByteStringTag | kThinStringTag:
|
case kTwoByteStringTag | kThinStringTag:
|
||||||
source = ThinString::cast(source).actual();
|
source = ThinString::cast(source).actual(cage_base);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
DCHECK_EQ(from, to);
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SourceChar>
|
template <typename SourceChar>
|
||||||
@ -819,12 +822,15 @@ bool String::SlowEquals(
|
|||||||
if (len != other.length()) return false;
|
if (len != other.length()) return false;
|
||||||
if (len == 0) return true;
|
if (len == 0) return true;
|
||||||
|
|
||||||
|
PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
|
||||||
|
|
||||||
// Fast check: if at least one ThinString is involved, dereference it/them
|
// Fast check: if at least one ThinString is involved, dereference it/them
|
||||||
// and restart.
|
// and restart.
|
||||||
if (this->IsThinString() || other.IsThinString()) {
|
if (this->IsThinString(cage_base) || other.IsThinString(cage_base)) {
|
||||||
if (other.IsThinString()) other = ThinString::cast(other).actual();
|
if (other.IsThinString(cage_base))
|
||||||
if (this->IsThinString()) {
|
other = ThinString::cast(other).actual(cage_base);
|
||||||
return ThinString::cast(*this).actual().Equals(other);
|
if (this->IsThinString(cage_base)) {
|
||||||
|
return ThinString::cast(*this).actual(cage_base).Equals(other);
|
||||||
} else {
|
} else {
|
||||||
return this->Equals(other);
|
return this->Equals(other);
|
||||||
}
|
}
|
||||||
@ -852,7 +858,9 @@ bool String::SlowEquals(
|
|||||||
|
|
||||||
// We know the strings are both non-empty. Compare the first chars
|
// We know the strings are both non-empty. Compare the first chars
|
||||||
// before we try to flatten the strings.
|
// before we try to flatten the strings.
|
||||||
if (this->Get(0, access_guard) != other.Get(0, access_guard)) return false;
|
if (this->Get(0, cage_base, access_guard) !=
|
||||||
|
other.Get(0, cage_base, access_guard))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (IsSeqOneByteString() && other.IsSeqOneByteString()) {
|
if (IsSeqOneByteString() && other.IsSeqOneByteString()) {
|
||||||
const uint8_t* str1 =
|
const uint8_t* str1 =
|
||||||
@ -1348,6 +1356,7 @@ namespace {
|
|||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
uint32_t HashString(String string, size_t start, int length, uint64_t seed,
|
uint32_t HashString(String string, size_t start, int length, uint64_t seed,
|
||||||
|
PtrComprCageBase cage_base,
|
||||||
const SharedStringAccessGuardIfNeeded& access_guard) {
|
const SharedStringAccessGuardIfNeeded& access_guard) {
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
|
|
||||||
@ -1358,11 +1367,12 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed,
|
|||||||
std::unique_ptr<Char[]> buffer;
|
std::unique_ptr<Char[]> buffer;
|
||||||
const Char* chars;
|
const Char* chars;
|
||||||
|
|
||||||
if (string.IsConsString()) {
|
if (string.IsConsString(cage_base)) {
|
||||||
DCHECK_EQ(0, start);
|
DCHECK_EQ(0, start);
|
||||||
DCHECK(!string.IsFlat());
|
DCHECK(!string.IsFlat());
|
||||||
buffer.reset(new Char[length]);
|
buffer.reset(new Char[length]);
|
||||||
String::WriteToFlat(string, buffer.get(), 0, length, access_guard);
|
String::WriteToFlat(string, buffer.get(), 0, length, cage_base,
|
||||||
|
access_guard);
|
||||||
chars = buffer.get();
|
chars = buffer.get();
|
||||||
} else {
|
} else {
|
||||||
chars = string.GetChars<Char>(no_gc, access_guard) + start;
|
chars = string.GetChars<Char>(no_gc, access_guard) + start;
|
||||||
@ -1387,25 +1397,32 @@ uint32_t String::ComputeAndSetHash(
|
|||||||
uint64_t seed = HashSeed(GetReadOnlyRoots());
|
uint64_t seed = HashSeed(GetReadOnlyRoots());
|
||||||
size_t start = 0;
|
size_t start = 0;
|
||||||
String string = *this;
|
String string = *this;
|
||||||
if (string.IsSlicedString()) {
|
PtrComprCageBase cage_base = GetPtrComprCageBase(string);
|
||||||
|
StringShape shape(string, cage_base);
|
||||||
|
if (shape.IsSliced()) {
|
||||||
SlicedString sliced = SlicedString::cast(string);
|
SlicedString sliced = SlicedString::cast(string);
|
||||||
start = sliced.offset();
|
start = sliced.offset();
|
||||||
string = sliced.parent();
|
string = sliced.parent(cage_base);
|
||||||
|
shape = StringShape(string, cage_base);
|
||||||
}
|
}
|
||||||
if (string.IsConsString() && string.IsFlat()) {
|
if (shape.IsCons() && string.IsFlat(cage_base)) {
|
||||||
string = ConsString::cast(string).first();
|
string = ConsString::cast(string).first(cage_base);
|
||||||
|
shape = StringShape(string, cage_base);
|
||||||
}
|
}
|
||||||
if (string.IsThinString()) {
|
if (shape.IsThin()) {
|
||||||
string = ThinString::cast(string).actual();
|
string = ThinString::cast(string).actual(cage_base);
|
||||||
|
shape = StringShape(string, cage_base);
|
||||||
if (length() == string.length()) {
|
if (length() == string.length()) {
|
||||||
set_raw_hash_field(string.raw_hash_field());
|
set_raw_hash_field(string.raw_hash_field());
|
||||||
return hash();
|
return hash();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint32_t raw_hash_field =
|
uint32_t raw_hash_field =
|
||||||
string.IsOneByteRepresentation()
|
shape.encoding_tag() == kOneByteStringTag
|
||||||
? HashString<uint8_t>(string, start, length(), seed, access_guard)
|
? HashString<uint8_t>(string, start, length(), seed, cage_base,
|
||||||
: HashString<uint16_t>(string, start, length(), seed, access_guard);
|
access_guard)
|
||||||
|
: HashString<uint16_t>(string, start, length(), seed, cage_base,
|
||||||
|
access_guard);
|
||||||
set_raw_hash_field(raw_hash_field);
|
set_raw_hash_field(raw_hash_field);
|
||||||
|
|
||||||
// Check the hash code is there.
|
// Check the hash code is there.
|
||||||
@ -1509,29 +1526,30 @@ void SeqTwoByteString::clear_padding() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ConsString::Get(
|
uint16_t ConsString::Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
DCHECK(index >= 0 && index < this->length());
|
DCHECK(index >= 0 && index < this->length());
|
||||||
|
|
||||||
// Check for a flattened cons string
|
// Check for a flattened cons string
|
||||||
if (second().length() == 0) {
|
if (second(cage_base).length() == 0) {
|
||||||
String left = first();
|
String left = first(cage_base);
|
||||||
return left.Get(index);
|
return left.Get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
String string = String::cast(*this);
|
String string = String::cast(*this);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (StringShape(string).IsCons()) {
|
if (StringShape(string, cage_base).IsCons()) {
|
||||||
ConsString cons_string = ConsString::cast(string);
|
ConsString cons_string = ConsString::cast(string);
|
||||||
String left = cons_string.first();
|
String left = cons_string.first();
|
||||||
if (left.length() > index) {
|
if (left.length() > index) {
|
||||||
string = left;
|
string = left;
|
||||||
} else {
|
} else {
|
||||||
index -= left.length();
|
index -= left.length();
|
||||||
string = cons_string.second();
|
string = cons_string.second(cage_base);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return string.Get(index, access_guard);
|
return string.Get(index, cage_base, access_guard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1539,13 +1557,15 @@ uint16_t ConsString::Get(
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ThinString::Get(
|
uint16_t ThinString::Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
int index, PtrComprCageBase cage_base,
|
||||||
return actual().Get(index, access_guard);
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
|
return actual(cage_base).Get(index, cage_base, access_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t SlicedString::Get(
|
uint16_t SlicedString::Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
int index, PtrComprCageBase cage_base,
|
||||||
return parent().Get(offset() + index, access_guard);
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
|
return parent(cage_base).Get(offset() + index, cage_base, access_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExternalString::ExternalPayloadSize() const {
|
int ExternalString::ExternalPayloadSize() const {
|
||||||
@ -1744,10 +1764,10 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void String::WriteToFlat(
|
|||||||
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void String::WriteToFlat(
|
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void String::WriteToFlat(
|
||||||
String source, uint8_t* sink, int from, int to);
|
String source, uint8_t* sink, int from, int to);
|
||||||
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void String::WriteToFlat(
|
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void String::WriteToFlat(
|
||||||
String source, uint16_t* sink, int from, int to,
|
String source, uint16_t* sink, int from, int to, PtrComprCageBase cage_base,
|
||||||
const SharedStringAccessGuardIfNeeded&);
|
const SharedStringAccessGuardIfNeeded&);
|
||||||
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void String::WriteToFlat(
|
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void String::WriteToFlat(
|
||||||
String source, uint8_t* sink, int from, int to,
|
String source, uint8_t* sink, int from, int to, PtrComprCageBase cage_base,
|
||||||
const SharedStringAccessGuardIfNeeded&);
|
const SharedStringAccessGuardIfNeeded&);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "src/base/bits.h"
|
#include "src/base/bits.h"
|
||||||
#include "src/base/export-template.h"
|
#include "src/base/export-template.h"
|
||||||
#include "src/base/strings.h"
|
#include "src/base/strings.h"
|
||||||
|
#include "src/common/globals.h"
|
||||||
#include "src/objects/instance-type.h"
|
#include "src/objects/instance-type.h"
|
||||||
#include "src/objects/name.h"
|
#include "src/objects/name.h"
|
||||||
#include "src/objects/smi.h"
|
#include "src/objects/smi.h"
|
||||||
@ -43,6 +44,7 @@ enum RobustnessFlag { ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL };
|
|||||||
class StringShape {
|
class StringShape {
|
||||||
public:
|
public:
|
||||||
inline explicit StringShape(const String s);
|
inline explicit StringShape(const String s);
|
||||||
|
inline explicit StringShape(const String s, PtrComprCageBase cage_base);
|
||||||
inline explicit StringShape(Map s);
|
inline explicit StringShape(Map s);
|
||||||
inline explicit StringShape(InstanceType t);
|
inline explicit StringShape(InstanceType t);
|
||||||
inline bool IsSequential() const;
|
inline bool IsSequential() const;
|
||||||
@ -220,13 +222,15 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
// to this method are not efficient unless the string is flat.
|
// to this method are not efficient unless the string is flat.
|
||||||
// If it is called from a background thread, the LocalIsolate version should
|
// If it is called from a background thread, the LocalIsolate version should
|
||||||
// be used.
|
// be used.
|
||||||
V8_INLINE uint16_t Get(int index, Isolate* isolate = nullptr) const;
|
V8_INLINE uint16_t Get(int index) const;
|
||||||
|
V8_INLINE uint16_t Get(int index, Isolate* isolate) const;
|
||||||
V8_INLINE uint16_t Get(int index, LocalIsolate* local_isolate) const;
|
V8_INLINE uint16_t Get(int index, LocalIsolate* local_isolate) const;
|
||||||
// Method to pass down the access_guard. Useful for recursive calls such as
|
// Method to pass down the access_guard. Useful for recursive calls such as
|
||||||
// ThinStrings where we go String::Get into ThinString::Get into String::Get
|
// ThinStrings where we go String::Get into ThinString::Get into String::Get
|
||||||
// again for the internalized string.
|
// again for the internalized string.
|
||||||
V8_INLINE uint16_t
|
V8_INLINE uint16_t
|
||||||
Get(int index, const SharedStringAccessGuardIfNeeded& access_guard) const;
|
Get(int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
|
|
||||||
// ES6 section 7.1.3.1 ToNumber Applied to the String Type
|
// ES6 section 7.1.3.1 ToNumber Applied to the String Type
|
||||||
static Handle<Object> ToNumber(Isolate* isolate, Handle<String> subject);
|
static Handle<Object> ToNumber(Isolate* isolate, Handle<String> subject);
|
||||||
@ -429,6 +433,7 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
DECL_VERIFIER(String)
|
DECL_VERIFIER(String)
|
||||||
|
|
||||||
inline bool IsFlat() const;
|
inline bool IsFlat() const;
|
||||||
|
inline bool IsFlat(PtrComprCageBase cage_base) const;
|
||||||
|
|
||||||
// Max char codes.
|
// Max char codes.
|
||||||
static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar;
|
static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar;
|
||||||
@ -474,6 +479,7 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
static void WriteToFlat(String source, sinkchar* sink, int from, int to);
|
static void WriteToFlat(String source, sinkchar* sink, int from, int to);
|
||||||
template <typename sinkchar>
|
template <typename sinkchar>
|
||||||
static void WriteToFlat(String source, sinkchar* sink, int from, int to,
|
static void WriteToFlat(String source, sinkchar* sink, int from, int to,
|
||||||
|
PtrComprCageBase cage_base,
|
||||||
const SharedStringAccessGuardIfNeeded&);
|
const SharedStringAccessGuardIfNeeded&);
|
||||||
|
|
||||||
static inline bool IsAscii(const char* chars, int length) {
|
static inline bool IsAscii(const char* chars, int length) {
|
||||||
@ -551,7 +557,8 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
|
|
||||||
// Implementation of the Get() public methods. Do not use directly.
|
// Implementation of the Get() public methods. Do not use directly.
|
||||||
V8_INLINE uint16_t
|
V8_INLINE uint16_t
|
||||||
GetImpl(int index, const SharedStringAccessGuardIfNeeded& access_guard) const;
|
GetImpl(int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
|
|
||||||
// Implementation of the IsEqualTo() public methods. Do not use directly.
|
// Implementation of the IsEqualTo() public methods. Do not use directly.
|
||||||
template <EqualityType kEqType, typename Char>
|
template <EqualityType kEqType, typename Char>
|
||||||
@ -596,11 +603,13 @@ void String::WriteToFlat(String source, uint8_t* sink, int from, int to);
|
|||||||
extern template EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
|
extern template EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
|
||||||
void String::WriteToFlat(String source, uint16_t* sink, int from, int to);
|
void String::WriteToFlat(String source, uint16_t* sink, int from, int to);
|
||||||
extern template EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
|
extern template EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
|
||||||
void String::WriteToFlat(String source, uint8_t* sink, int from, int to ,
|
void String::WriteToFlat(String source, uint8_t* sink, int from, int to,
|
||||||
const SharedStringAccessGuardIfNeeded&);
|
PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded&);
|
||||||
extern template EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
|
extern template EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
|
||||||
void String::WriteToFlat(String source, uint16_t* sink, int from, int to,
|
void String::WriteToFlat(String source, uint16_t* sink, int from, int to,
|
||||||
const SharedStringAccessGuardIfNeeded&);
|
PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded&);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
class SubStringRange {
|
class SubStringRange {
|
||||||
@ -650,7 +659,7 @@ class SeqOneByteString
|
|||||||
// defined for convenience and it will check that the access guard is not
|
// defined for convenience and it will check that the access guard is not
|
||||||
// needed.
|
// needed.
|
||||||
inline uint8_t Get(int index) const;
|
inline uint8_t Get(int index) const;
|
||||||
inline uint8_t Get(int index,
|
inline uint8_t Get(int index, PtrComprCageBase cage_base,
|
||||||
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
inline void SeqOneByteStringSet(int index, uint16_t value);
|
inline void SeqOneByteStringSet(int index, uint16_t value);
|
||||||
|
|
||||||
@ -698,7 +707,8 @@ class SeqTwoByteString
|
|||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
inline uint16_t Get(
|
inline uint16_t Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const;
|
int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
inline void SeqTwoByteStringSet(int index, uint16_t value);
|
inline void SeqTwoByteStringSet(int index, uint16_t value);
|
||||||
|
|
||||||
// Get the address of the characters in this string.
|
// Get the address of the characters in this string.
|
||||||
@ -756,7 +766,8 @@ class ConsString : public TorqueGeneratedConsString<ConsString, String> {
|
|||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
V8_EXPORT_PRIVATE uint16_t
|
V8_EXPORT_PRIVATE uint16_t
|
||||||
Get(int index, const SharedStringAccessGuardIfNeeded& access_guard) const;
|
Get(int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
|
|
||||||
// Minimum length for a cons string.
|
// Minimum length for a cons string.
|
||||||
static const int kMinLength = 13;
|
static const int kMinLength = 13;
|
||||||
@ -780,7 +791,8 @@ class ThinString : public TorqueGeneratedThinString<ThinString, String> {
|
|||||||
DECL_GETTER(unchecked_actual, HeapObject)
|
DECL_GETTER(unchecked_actual, HeapObject)
|
||||||
|
|
||||||
V8_EXPORT_PRIVATE uint16_t
|
V8_EXPORT_PRIVATE uint16_t
|
||||||
Get(int index, const SharedStringAccessGuardIfNeeded& access_guard) const;
|
Get(int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
|
|
||||||
DECL_VERIFIER(ThinString)
|
DECL_VERIFIER(ThinString)
|
||||||
|
|
||||||
@ -805,7 +817,8 @@ class SlicedString : public TorqueGeneratedSlicedString<SlicedString, String> {
|
|||||||
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
V8_EXPORT_PRIVATE uint16_t
|
V8_EXPORT_PRIVATE uint16_t
|
||||||
Get(int index, const SharedStringAccessGuardIfNeeded& access_guard) const;
|
Get(int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
|
|
||||||
// Minimum length for a sliced string.
|
// Minimum length for a sliced string.
|
||||||
static const int kMinLength = 13;
|
static const int kMinLength = 13;
|
||||||
@ -891,7 +904,7 @@ class ExternalOneByteString
|
|||||||
inline const uint8_t* GetChars() const;
|
inline const uint8_t* GetChars() const;
|
||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
inline uint8_t Get(int index,
|
inline uint8_t Get(int index, PtrComprCageBase cage_base,
|
||||||
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
|
|
||||||
class BodyDescriptor;
|
class BodyDescriptor;
|
||||||
@ -935,7 +948,8 @@ class ExternalTwoByteString
|
|||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
inline uint16_t Get(
|
inline uint16_t Get(
|
||||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const;
|
int index, PtrComprCageBase cage_base,
|
||||||
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
|
|
||||||
// For regexp code.
|
// For regexp code.
|
||||||
inline const uint16_t* ExternalTwoByteStringGetData(unsigned start);
|
inline const uint16_t* ExternalTwoByteStringGetData(unsigned start);
|
||||||
|
Loading…
Reference in New Issue
Block a user