Commit 012af69b authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[string] Add PtrCage for ExternalString::GetChars

Change-Id: I14400c0efea88b4bbb40aa2fbe9527dc9c67d3fb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3160340
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76837}
parent d345b25a
...@@ -7,9 +7,11 @@ ...@@ -7,9 +7,11 @@
#include "src/api/api.h" #include "src/api/api.h"
#include "src/base/ieee754.h" #include "src/base/ieee754.h"
#include "src/codegen/cpu-features.h" #include "src/codegen/cpu-features.h"
#include "src/common/globals.h"
#include "src/date/date.h" #include "src/date/date.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
#include "src/deoptimizer/deoptimizer.h" #include "src/deoptimizer/deoptimizer.h"
#include "src/execution/isolate-utils.h"
#include "src/execution/isolate.h" #include "src/execution/isolate.h"
#include "src/execution/microtask-queue.h" #include "src/execution/microtask-queue.h"
#include "src/execution/simulator-base.h" #include "src/execution/simulator-base.h"
...@@ -895,22 +897,24 @@ void StringWriteToFlatTwoByte(Address source, uint16_t* sink, int32_t start, ...@@ -895,22 +897,24 @@ void StringWriteToFlatTwoByte(Address source, uint16_t* sink, int32_t start,
} }
const uint8_t* ExternalOneByteStringGetChars(Address string) { const uint8_t* ExternalOneByteStringGetChars(Address string) {
PtrComprCageBase cage_base = GetPtrComprCageBaseFromOnHeapAddress(string);
// The following CHECK is a workaround to prevent a CFI bug where // The following CHECK is a workaround to prevent a CFI bug where
// ExternalOneByteStringGetChars() and ExternalTwoByteStringGetChars() are // ExternalOneByteStringGetChars() and ExternalTwoByteStringGetChars() are
// merged by the linker, resulting in one of the input type's vtable address // merged by the linker, resulting in one of the input type's vtable address
// failing the address range check. // failing the address range check.
// TODO(chromium:1160961): Consider removing the CHECK when CFI is fixed. // TODO(chromium:1160961): Consider removing the CHECK when CFI is fixed.
CHECK(Object(string).IsExternalOneByteString()); CHECK(Object(string).IsExternalOneByteString(cage_base));
return ExternalOneByteString::cast(Object(string)).GetChars(); return ExternalOneByteString::cast(Object(string)).GetChars(cage_base);
} }
const uint16_t* ExternalTwoByteStringGetChars(Address string) { const uint16_t* ExternalTwoByteStringGetChars(Address string) {
PtrComprCageBase cage_base = GetPtrComprCageBaseFromOnHeapAddress(string);
// The following CHECK is a workaround to prevent a CFI bug where // The following CHECK is a workaround to prevent a CFI bug where
// ExternalOneByteStringGetChars() and ExternalTwoByteStringGetChars() are // ExternalOneByteStringGetChars() and ExternalTwoByteStringGetChars() are
// merged by the linker, resulting in one of the input type's vtable address // merged by the linker, resulting in one of the input type's vtable address
// failing the address range check. // failing the address range check.
// TODO(chromium:1160961): Consider removing the CHECK when CFI is fixed. // TODO(chromium:1160961): Consider removing the CHECK when CFI is fixed.
CHECK(Object(string).IsExternalTwoByteString()); CHECK(Object(string).IsExternalTwoByteString(cage_base));
return ExternalTwoByteString::cast(Object(string)).GetChars(); return ExternalTwoByteString::cast(Object(string)).GetChars(cage_base);
} }
} // namespace } // namespace
......
...@@ -627,13 +627,13 @@ MaybeHandle<String> FactoryBase<Impl>::NewConsString( ...@@ -627,13 +627,13 @@ MaybeHandle<String> FactoryBase<Impl>::NewConsString(
// Copy left part. // Copy left part.
{ {
const uint8_t* src = const uint8_t* src =
left->template GetChars<uint8_t>(no_gc, access_guard); left->template GetChars<uint8_t>(isolate(), no_gc, access_guard);
CopyChars(dest, src, left_length); CopyChars(dest, src, left_length);
} }
// Copy right part. // Copy right part.
{ {
const uint8_t* src = const uint8_t* src =
right->template GetChars<uint8_t>(no_gc, access_guard); right->template GetChars<uint8_t>(isolate(), no_gc, access_guard);
CopyChars(dest + left_length, src, right_length); CopyChars(dest + left_length, src, right_length);
} }
return result; return result;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "src/json/json-parser.h" #include "src/json/json-parser.h"
#include "src/base/strings.h" #include "src/base/strings.h"
#include "src/common/globals.h"
#include "src/common/message-template.h" #include "src/common/message-template.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
#include "src/numbers/conversions.h" #include "src/numbers/conversions.h"
...@@ -210,19 +211,21 @@ JsonParser<Char>::JsonParser(Isolate* isolate, Handle<String> source) ...@@ -210,19 +211,21 @@ JsonParser<Char>::JsonParser(Isolate* isolate, Handle<String> source)
original_source_(source) { original_source_(source) {
size_t start = 0; size_t start = 0;
size_t length = source->length(); size_t length = source->length();
if (source->IsSlicedString()) { PtrComprCageBase cage_base(isolate);
if (source->IsSlicedString(cage_base)) {
SlicedString string = SlicedString::cast(*source); SlicedString string = SlicedString::cast(*source);
start = string.offset(); start = string.offset();
String parent = string.parent(); String parent = string.parent(cage_base);
if (parent.IsThinString()) parent = ThinString::cast(parent).actual(); if (parent.IsThinString(cage_base))
parent = ThinString::cast(parent).actual(cage_base);
source_ = handle(parent, isolate); source_ = handle(parent, isolate);
} else { } else {
source_ = String::Flatten(isolate, source); source_ = String::Flatten(isolate, source);
} }
if (StringShape(*source_).IsExternal()) { if (StringShape(*source_, cage_base).IsExternal()) {
chars_ = chars_ = static_cast<const Char*>(
static_cast<const Char*>(SeqExternalString::cast(*source_).GetChars()); SeqExternalString::cast(*source_).GetChars(cage_base));
chars_may_relocate_ = false; chars_may_relocate_ = false;
} else { } else {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
......
...@@ -512,12 +512,14 @@ bool String::IsEqualToImpl( ...@@ -512,12 +512,14 @@ bool String::IsEqualToImpl(
data, len); data, len);
case kExternalStringTag | kOneByteStringTag: case kExternalStringTag | kOneByteStringTag:
return CompareCharsEqual( return CompareCharsEqual(
ExternalOneByteString::cast(string).GetChars() + slice_offset, data, ExternalOneByteString::cast(string).GetChars(cage_base) +
len); slice_offset,
data, len);
case kExternalStringTag | kTwoByteStringTag: case kExternalStringTag | kTwoByteStringTag:
return CompareCharsEqual( return CompareCharsEqual(
ExternalTwoByteString::cast(string).GetChars() + slice_offset, data, ExternalTwoByteString::cast(string).GetChars(cage_base) +
len); slice_offset,
data, len);
case kSlicedStringTag | kOneByteStringTag: case kSlicedStringTag | kOneByteStringTag:
case kSlicedStringTag | kTwoByteStringTag: { case kSlicedStringTag | kTwoByteStringTag: {
...@@ -582,19 +584,20 @@ bool String::IsOneByteEqualTo(base::Vector<const char> str) { ...@@ -582,19 +584,20 @@ bool String::IsOneByteEqualTo(base::Vector<const char> str) {
} }
template <typename Char> template <typename Char>
const Char* String::GetChars(const DisallowGarbageCollection& no_gc) const { const Char* String::GetChars(PtrComprCageBase cage_base,
const DisallowGarbageCollection& no_gc) const {
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this)); DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
return StringShape(*this).IsExternal() return StringShape(*this, cage_base).IsExternal()
? CharTraits<Char>::ExternalString::cast(*this).GetChars() ? CharTraits<Char>::ExternalString::cast(*this).GetChars(cage_base)
: CharTraits<Char>::String::cast(*this).GetChars(no_gc); : CharTraits<Char>::String::cast(*this).GetChars(no_gc);
} }
template <typename Char> template <typename Char>
const Char* String::GetChars( const Char* String::GetChars(
const DisallowGarbageCollection& no_gc, PtrComprCageBase cage_base, const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) const { const SharedStringAccessGuardIfNeeded& access_guard) const {
return StringShape(*this).IsExternal() return StringShape(*this, cage_base).IsExternal()
? CharTraits<Char>::ExternalString::cast(*this).GetChars() ? CharTraits<Char>::ExternalString::cast(*this).GetChars(cage_base)
: CharTraits<Char>::String::cast(*this).GetChars(no_gc, : CharTraits<Char>::String::cast(*this).GetChars(no_gc,
access_guard); access_guard);
} }
...@@ -717,9 +720,10 @@ ConsString String::VisitFlat( ...@@ -717,9 +720,10 @@ ConsString String::VisitFlat(
int slice_offset = offset; int slice_offset = offset;
const int length = string.length(); const int length = string.length();
DCHECK(offset <= length); DCHECK(offset <= length);
PtrComprCageBase cage_base = GetPtrComprCageBase(string);
while (true) { while (true) {
int32_t type = string.map().instance_type(); int32_t tag = StringShape(string, cage_base).full_representation_tag();
switch (type & (kStringRepresentationMask | kStringEncodingMask)) { switch (tag) {
case kSeqStringTag | kOneByteStringTag: case kSeqStringTag | kOneByteStringTag:
visitor->VisitOneByteString( visitor->VisitOneByteString(
SeqOneByteString::cast(string).GetChars(no_gc, access_guard) + SeqOneByteString::cast(string).GetChars(no_gc, access_guard) +
...@@ -736,13 +740,15 @@ ConsString String::VisitFlat( ...@@ -736,13 +740,15 @@ ConsString String::VisitFlat(
case kExternalStringTag | kOneByteStringTag: case kExternalStringTag | kOneByteStringTag:
visitor->VisitOneByteString( visitor->VisitOneByteString(
ExternalOneByteString::cast(string).GetChars() + slice_offset, ExternalOneByteString::cast(string).GetChars(cage_base) +
slice_offset,
length - offset); length - offset);
return ConsString(); return ConsString();
case kExternalStringTag | kTwoByteStringTag: case kExternalStringTag | kTwoByteStringTag:
visitor->VisitTwoByteString( visitor->VisitTwoByteString(
ExternalTwoByteString::cast(string).GetChars() + slice_offset, ExternalTwoByteString::cast(string).GetChars(cage_base) +
slice_offset,
length - offset); length - offset);
return ConsString(); return ConsString();
...@@ -750,7 +756,7 @@ ConsString String::VisitFlat( ...@@ -750,7 +756,7 @@ ConsString String::VisitFlat(
case kSlicedStringTag | kTwoByteStringTag: { case kSlicedStringTag | kTwoByteStringTag: {
SlicedString slicedString = SlicedString::cast(string); SlicedString slicedString = SlicedString::cast(string);
slice_offset += slicedString.offset(); slice_offset += slicedString.offset();
string = slicedString.parent(); string = slicedString.parent(cage_base);
continue; continue;
} }
...@@ -760,7 +766,7 @@ ConsString String::VisitFlat( ...@@ -760,7 +766,7 @@ ConsString String::VisitFlat(
case kThinStringTag | kOneByteStringTag: case kThinStringTag | kOneByteStringTag:
case kThinStringTag | kTwoByteStringTag: case kThinStringTag | kTwoByteStringTag:
string = ThinString::cast(string).actual(); string = ThinString::cast(string).actual(cage_base);
continue; continue;
default: default:
...@@ -948,11 +954,13 @@ DEF_GETTER(ExternalOneByteString, mutable_resource, ...@@ -948,11 +954,13 @@ DEF_GETTER(ExternalOneByteString, mutable_resource,
void ExternalOneByteString::update_data_cache(Isolate* isolate) { void ExternalOneByteString::update_data_cache(Isolate* isolate) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
if (is_uncached()) { if (is_uncached()) {
if (resource()->IsCacheable()) mutable_resource()->UpdateDataCache(); if (resource(isolate)->IsCacheable())
mutable_resource(isolate)->UpdateDataCache();
} else { } else {
WriteExternalPointerField(kResourceDataOffset, isolate, WriteExternalPointerField(
reinterpret_cast<Address>(resource()->data()), kResourceDataOffset, isolate,
kExternalStringResourceDataTag); reinterpret_cast<Address>(resource(isolate)->data()),
kExternalStringResourceDataTag);
} }
} }
...@@ -973,13 +981,15 @@ void ExternalOneByteString::set_resource( ...@@ -973,13 +981,15 @@ void ExternalOneByteString::set_resource(
if (resource != nullptr) update_data_cache(isolate); if (resource != nullptr) update_data_cache(isolate);
} }
const uint8_t* ExternalOneByteString::GetChars() const { const uint8_t* ExternalOneByteString::GetChars(
PtrComprCageBase cage_base) const {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
auto res = resource(cage_base);
if (is_uncached()) { if (is_uncached()) {
if (resource()->IsCacheable()) { if (res->IsCacheable()) {
// TODO(solanes): Teach TurboFan/CSA to not bailout to the runtime to // TODO(solanes): Teach TurboFan/CSA to not bailout to the runtime to
// avoid this call. // avoid this call.
return reinterpret_cast<const uint8_t*>(resource()->cached_data()); return reinterpret_cast<const uint8_t*>(res->cached_data());
} }
#if DEBUG #if DEBUG
// Check that this method is called only from the main thread if we have an // Check that this method is called only from the main thread if we have an
...@@ -992,7 +1002,7 @@ const uint8_t* ExternalOneByteString::GetChars() const { ...@@ -992,7 +1002,7 @@ const uint8_t* ExternalOneByteString::GetChars() const {
#endif #endif
} }
return reinterpret_cast<const uint8_t*>(resource()->data()); return reinterpret_cast<const uint8_t*>(res->data());
} }
uint8_t ExternalOneByteString::Get( uint8_t ExternalOneByteString::Get(
...@@ -1000,7 +1010,7 @@ uint8_t ExternalOneByteString::Get( ...@@ -1000,7 +1010,7 @@ uint8_t ExternalOneByteString::Get(
const SharedStringAccessGuardIfNeeded& access_guard) const { 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(cage_base)[index];
} }
DEF_GETTER(ExternalTwoByteString, resource, DEF_GETTER(ExternalTwoByteString, resource,
...@@ -1016,11 +1026,13 @@ DEF_GETTER(ExternalTwoByteString, mutable_resource, ...@@ -1016,11 +1026,13 @@ DEF_GETTER(ExternalTwoByteString, mutable_resource,
void ExternalTwoByteString::update_data_cache(Isolate* isolate) { void ExternalTwoByteString::update_data_cache(Isolate* isolate) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
if (is_uncached()) { if (is_uncached()) {
if (resource()->IsCacheable()) mutable_resource()->UpdateDataCache(); if (resource(isolate)->IsCacheable())
mutable_resource(isolate)->UpdateDataCache();
} else { } else {
WriteExternalPointerField(kResourceDataOffset, isolate, WriteExternalPointerField(
reinterpret_cast<Address>(resource()->data()), kResourceDataOffset, isolate,
kExternalStringResourceDataTag); reinterpret_cast<Address>(resource(isolate)->data()),
kExternalStringResourceDataTag);
} }
} }
...@@ -1041,13 +1053,15 @@ void ExternalTwoByteString::set_resource( ...@@ -1041,13 +1053,15 @@ void ExternalTwoByteString::set_resource(
if (resource != nullptr) update_data_cache(isolate); if (resource != nullptr) update_data_cache(isolate);
} }
const uint16_t* ExternalTwoByteString::GetChars() const { const uint16_t* ExternalTwoByteString::GetChars(
PtrComprCageBase cage_base) const {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
auto res = resource(cage_base);
if (is_uncached()) { if (is_uncached()) {
if (resource()->IsCacheable()) { if (res->IsCacheable()) {
// TODO(solanes): Teach TurboFan/CSA to not bailout to the runtime to // TODO(solanes): Teach TurboFan/CSA to not bailout to the runtime to
// avoid this call. // avoid this call.
return resource()->cached_data(); return res->cached_data();
} }
#if DEBUG #if DEBUG
// Check that this method is called only from the main thread if we have an // Check that this method is called only from the main thread if we have an
...@@ -1060,7 +1074,7 @@ const uint16_t* ExternalTwoByteString::GetChars() const { ...@@ -1060,7 +1074,7 @@ const uint16_t* ExternalTwoByteString::GetChars() const {
#endif #endif
} }
return resource()->data(); return res->data();
} }
uint16_t ExternalTwoByteString::Get( uint16_t ExternalTwoByteString::Get(
...@@ -1068,12 +1082,12 @@ uint16_t ExternalTwoByteString::Get( ...@@ -1068,12 +1082,12 @@ uint16_t ExternalTwoByteString::Get(
const SharedStringAccessGuardIfNeeded& access_guard) const { 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(cage_base)[index];
} }
const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData( const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
unsigned start) { unsigned start) {
return GetChars() + start; return GetChars(GetPtrComprCageBase(*this)) + start;
} }
int ConsStringIterator::OffsetForDepth(int depth) { return depth & kDepthMask; } int ConsStringIterator::OffsetForDepth(int depth) { return depth & kDepthMask; }
......
...@@ -574,13 +574,14 @@ Address StringTable::Data::TryStringToIndexOrLookupExisting(Isolate* isolate, ...@@ -574,13 +574,14 @@ Address StringTable::Data::TryStringToIndexOrLookupExisting(Isolate* isolate,
std::unique_ptr<Char[]> buffer; std::unique_ptr<Char[]> buffer;
const Char* chars; const Char* chars;
if (source.IsConsString()) { SharedStringAccessGuardIfNeeded access_guard(isolate);
DCHECK(!source.IsFlat()); if (source.IsConsString(isolate)) {
DCHECK(!source.IsFlat(isolate));
buffer.reset(new Char[length]); buffer.reset(new Char[length]);
String::WriteToFlat(source, buffer.get(), 0, length); String::WriteToFlat(source, buffer.get(), 0, length, isolate, access_guard);
chars = buffer.get(); chars = buffer.get();
} else { } else {
chars = source.GetChars<Char>(no_gc) + start; chars = source.GetChars<Char>(isolate, no_gc, access_guard) + start;
} }
// TODO(verwaest): Internalize to one-byte when possible. // TODO(verwaest): Internalize to one-byte when possible.
SequentialStringKey<Char> key(base::Vector<const Char>(chars, length), seed); SequentialStringKey<Char> key(base::Vector<const Char>(chars, length), seed);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "src/heap/memory-chunk.h" #include "src/heap/memory-chunk.h"
#include "src/heap/read-only-heap.h" #include "src/heap/read-only-heap.h"
#include "src/numbers/conversions.h" #include "src/numbers/conversions.h"
#include "src/objects/instance-type.h"
#include "src/objects/map.h" #include "src/objects/map.h"
#include "src/objects/oddball.h" #include "src/objects/oddball.h"
#include "src/objects/string-comparator.h" #include "src/objects/string-comparator.h"
...@@ -546,29 +547,30 @@ String::FlatContent String::GetFlatContent( ...@@ -546,29 +547,30 @@ String::FlatContent String::GetFlatContent(
} }
#endif #endif
USE(no_gc); USE(no_gc);
PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
int length = this->length(); int length = this->length();
StringShape shape(*this); StringShape shape(*this, cage_base);
String string = *this; String string = *this;
int offset = 0; int offset = 0;
if (shape.representation_tag() == kConsStringTag) { if (shape.representation_tag() == kConsStringTag) {
ConsString cons = ConsString::cast(string); ConsString cons = ConsString::cast(string);
if (cons.second().length() != 0) { if (cons.second(cage_base).length() != 0) {
return FlatContent(no_gc); return FlatContent(no_gc);
} }
string = cons.first(); string = cons.first(cage_base);
shape = StringShape(string); shape = StringShape(string, cage_base);
} else if (shape.representation_tag() == kSlicedStringTag) { } else if (shape.representation_tag() == kSlicedStringTag) {
SlicedString slice = SlicedString::cast(string); SlicedString slice = SlicedString::cast(string);
offset = slice.offset(); offset = slice.offset();
string = slice.parent(); string = slice.parent(cage_base);
shape = StringShape(string); shape = StringShape(string, cage_base);
DCHECK(shape.representation_tag() != kConsStringTag && DCHECK(shape.representation_tag() != kConsStringTag &&
shape.representation_tag() != kSlicedStringTag); shape.representation_tag() != kSlicedStringTag);
} }
if (shape.representation_tag() == kThinStringTag) { if (shape.representation_tag() == kThinStringTag) {
ThinString thin = ThinString::cast(string); ThinString thin = ThinString::cast(string);
string = thin.actual(); string = thin.actual(cage_base);
shape = StringShape(string); shape = StringShape(string, cage_base);
DCHECK(!shape.IsCons()); DCHECK(!shape.IsCons());
DCHECK(!shape.IsSliced()); DCHECK(!shape.IsSliced());
} }
...@@ -577,7 +579,7 @@ String::FlatContent String::GetFlatContent( ...@@ -577,7 +579,7 @@ String::FlatContent String::GetFlatContent(
if (shape.representation_tag() == kSeqStringTag) { if (shape.representation_tag() == kSeqStringTag) {
start = SeqOneByteString::cast(string).GetChars(no_gc); start = SeqOneByteString::cast(string).GetChars(no_gc);
} else { } else {
start = ExternalOneByteString::cast(string).GetChars(); start = ExternalOneByteString::cast(string).GetChars(cage_base);
} }
return FlatContent(start + offset, length, no_gc); return FlatContent(start + offset, length, no_gc);
} else { } else {
...@@ -586,7 +588,7 @@ String::FlatContent String::GetFlatContent( ...@@ -586,7 +588,7 @@ String::FlatContent String::GetFlatContent(
if (shape.representation_tag() == kSeqStringTag) { if (shape.representation_tag() == kSeqStringTag) {
start = SeqTwoByteString::cast(string).GetChars(no_gc); start = SeqTwoByteString::cast(string).GetChars(no_gc);
} else { } else {
start = ExternalTwoByteString::cast(string).GetChars(); start = ExternalTwoByteString::cast(string).GetChars(cage_base);
} }
return FlatContent(start + offset, length, no_gc); return FlatContent(start + offset, length, no_gc);
} }
...@@ -664,12 +666,16 @@ void String::WriteToFlat(String source, sinkchar* sink, int start, int length, ...@@ -664,12 +666,16 @@ void String::WriteToFlat(String source, sinkchar* sink, int start, int length,
DCHECK_LE(length, source.length()); DCHECK_LE(length, source.length());
switch (StringShape(source, cage_base).full_representation_tag()) { switch (StringShape(source, cage_base).full_representation_tag()) {
case kOneByteStringTag | kExternalStringTag: case kOneByteStringTag | kExternalStringTag:
CopyChars(sink, ExternalOneByteString::cast(source).GetChars() + start, CopyChars(
length); sink,
ExternalOneByteString::cast(source).GetChars(cage_base) + start,
length);
return; return;
case kTwoByteStringTag | kExternalStringTag: case kTwoByteStringTag | kExternalStringTag:
CopyChars(sink, ExternalTwoByteString::cast(source).GetChars() + start, CopyChars(
length); sink,
ExternalTwoByteString::cast(source).GetChars(cage_base) + start,
length);
return; return;
case kOneByteStringTag | kSeqStringTag: case kOneByteStringTag | kSeqStringTag:
CopyChars(sink, CopyChars(sink,
...@@ -1377,7 +1383,7 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed, ...@@ -1377,7 +1383,7 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed,
access_guard); access_guard);
chars = buffer.get(); chars = buffer.get();
} else { } else {
chars = string.GetChars<Char>(no_gc, access_guard) + start; chars = string.GetChars<Char>(cage_base, no_gc, access_guard) + start;
} }
return StringHasher::HashSequentialString<Char>(chars, length, seed); return StringHasher::HashSequentialString<Char>(chars, length, seed);
...@@ -1734,30 +1740,39 @@ const byte* String::AddressOfCharacterAt( ...@@ -1734,30 +1740,39 @@ const byte* String::AddressOfCharacterAt(
int start_index, const DisallowGarbageCollection& no_gc) { int start_index, const DisallowGarbageCollection& no_gc) {
DCHECK(IsFlat()); DCHECK(IsFlat());
String subject = *this; String subject = *this;
if (subject.IsConsString()) { PtrComprCageBase cage_base = GetPtrComprCageBase(subject);
subject = ConsString::cast(subject).first(); StringShape shape(subject, cage_base);
} else if (subject.IsSlicedString()) { if (subject.IsConsString(cage_base)) {
subject = ConsString::cast(subject).first(cage_base);
shape = StringShape(subject, cage_base);
} else if (subject.IsSlicedString(cage_base)) {
start_index += SlicedString::cast(subject).offset(); start_index += SlicedString::cast(subject).offset();
subject = SlicedString::cast(subject).parent(); subject = SlicedString::cast(subject).parent(cage_base);
shape = StringShape(subject, cage_base);
} }
if (subject.IsThinString()) { if (subject.IsThinString(cage_base)) {
subject = ThinString::cast(subject).actual(); subject = ThinString::cast(subject).actual(cage_base);
shape = StringShape(subject, cage_base);
} }
CHECK_LE(0, start_index); CHECK_LE(0, start_index);
CHECK_LE(start_index, subject.length()); CHECK_LE(start_index, subject.length());
if (subject.IsSeqOneByteString()) { switch (shape.full_representation_tag()) {
return reinterpret_cast<const byte*>( case kOneByteStringTag | kSeqStringTag:
SeqOneByteString::cast(subject).GetChars(no_gc) + start_index); return reinterpret_cast<const byte*>(
} else if (subject.IsSeqTwoByteString()) { SeqOneByteString::cast(subject).GetChars(no_gc) + start_index);
return reinterpret_cast<const byte*>( case kTwoByteStringTag | kSeqStringTag:
SeqTwoByteString::cast(subject).GetChars(no_gc) + start_index); return reinterpret_cast<const byte*>(
} else if (subject.IsExternalOneByteString()) { SeqTwoByteString::cast(subject).GetChars(no_gc) + start_index);
return reinterpret_cast<const byte*>( case kOneByteStringTag | kExternalStringTag:
ExternalOneByteString::cast(subject).GetChars() + start_index); return reinterpret_cast<const byte*>(
} else { ExternalOneByteString::cast(subject).GetChars(cage_base) +
DCHECK(subject.IsExternalTwoByteString()); start_index);
return reinterpret_cast<const byte*>( case kTwoByteStringTag | kExternalStringTag:
ExternalTwoByteString::cast(subject).GetChars() + start_index); return reinterpret_cast<const byte*>(
ExternalTwoByteString::cast(subject).GetChars(cage_base) +
start_index);
default:
UNREACHABLE();
} }
} }
......
...@@ -185,12 +185,13 @@ class String : public TorqueGeneratedString<String, Name> { ...@@ -185,12 +185,13 @@ class String : public TorqueGeneratedString<String, Name> {
// SharedStringAccessGuard is not needed (i.e. on the main thread or on // SharedStringAccessGuard is not needed (i.e. on the main thread or on
// read-only strings). // read-only strings).
template <typename Char> template <typename Char>
inline const Char* GetChars(const DisallowGarbageCollection& no_gc) const; inline const Char* GetChars(PtrComprCageBase cage_base,
const DisallowGarbageCollection& no_gc) const;
// Get chars from sequential or external strings. // Get chars from sequential or external strings.
template <typename Char> template <typename Char>
inline const Char* GetChars( inline const Char* GetChars(
const DisallowGarbageCollection& no_gc, PtrComprCageBase cage_base, const DisallowGarbageCollection& no_gc,
const SharedStringAccessGuardIfNeeded& access_guard) const; const SharedStringAccessGuardIfNeeded& access_guard) const;
// Returns the address of the character at an offset into this string. // Returns the address of the character at an offset into this string.
...@@ -901,7 +902,7 @@ class ExternalOneByteString ...@@ -901,7 +902,7 @@ class ExternalOneByteString
// which the pointer cache has to be refreshed. // which the pointer cache has to be refreshed.
inline void update_data_cache(Isolate* isolate); inline void update_data_cache(Isolate* isolate);
inline const uint8_t* GetChars() const; inline const uint8_t* GetChars(PtrComprCageBase cage_base) const;
// Dispatched behavior. // Dispatched behavior.
inline uint8_t Get(int index, PtrComprCageBase cage_base, inline uint8_t Get(int index, PtrComprCageBase cage_base,
...@@ -944,7 +945,7 @@ class ExternalTwoByteString ...@@ -944,7 +945,7 @@ class ExternalTwoByteString
// which the pointer cache has to be refreshed. // which the pointer cache has to be refreshed.
inline void update_data_cache(Isolate* isolate); inline void update_data_cache(Isolate* isolate);
inline const uint16_t* GetChars() const; inline const uint16_t* GetChars(PtrComprCageBase cage_base) const;
// Dispatched behavior. // Dispatched behavior.
inline uint16_t Get( inline uint16_t Get(
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "include/v8-primitive.h" #include "include/v8-primitive.h"
#include "src/base/strings.h" #include "src/base/strings.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/execution/isolate-utils.h"
#include "src/handles/handles.h" #include "src/handles/handles.h"
#include "src/logging/runtime-call-stats-scope.h" #include "src/logging/runtime-call-stats-scope.h"
#include "src/objects/objects-inl.h" #include "src/objects/objects-inl.h"
...@@ -102,7 +103,7 @@ class ExternalStringStream { ...@@ -102,7 +103,7 @@ class ExternalStringStream {
ExternalStringStream(ExternalString string, size_t start_offset, ExternalStringStream(ExternalString string, size_t start_offset,
size_t length) size_t length)
: lock_(string), : lock_(string),
data_(string.GetChars() + start_offset), data_(string.GetChars(GetPtrComprCageBase(string)) + start_offset),
length_(length) {} length_(length) {}
ExternalStringStream(const ExternalStringStream& other) V8_NOEXCEPT ExternalStringStream(const ExternalStringStream& other) V8_NOEXCEPT
......
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