[sandbox] Wire ExternalString resource through bottleneck

Bug: v8:10391
Change-Id: Ic92cdaca38c2181427cc12ec5e572d5964afe704
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2152647
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67601}
This commit is contained in:
Nico Hartmann 2020-04-17 14:33:45 +02:00 committed by Commit Bot
parent b3b824ba91
commit c64b52a892
8 changed files with 73 additions and 36 deletions

View File

@ -11387,7 +11387,10 @@ String::ExternalStringResource* String::GetExternalStringResource() const {
ExternalStringResource* result;
if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) {
void* value = I::ReadRawField<void*>(obj, I::kStringResourceOffset);
internal::Isolate* isolate =
internal::IsolateFromNeverReadOnlySpaceObject(obj);
A value =
I::ReadExternalPointerField(isolate, obj, I::kStringResourceOffset);
result = reinterpret_cast<String::ExternalStringResource*>(value);
} else {
result = GetExternalStringResourceSlow();
@ -11409,8 +11412,11 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBase(
ExternalStringResourceBase* resource;
if (type == I::kExternalOneByteRepresentationTag ||
type == I::kExternalTwoByteRepresentationTag) {
void* value = I::ReadRawField<void*>(obj, I::kStringResourceOffset);
resource = static_cast<ExternalStringResourceBase*>(value);
internal::Isolate* isolate =
internal::IsolateFromNeverReadOnlySpaceObject(obj);
A value =
I::ReadExternalPointerField(isolate, obj, I::kStringResourceOffset);
resource = reinterpret_cast<ExternalStringResourceBase*>(value);
} else {
resource = GetExternalStringResourceBaseSlow(encoding_out);
}

View File

@ -28,6 +28,7 @@
#include "src/codegen/compiler.h"
#include "src/codegen/cpu-features.h"
#include "src/common/assert-scope.h"
#include "src/common/external-pointer.h"
#include "src/common/globals.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h"
#include "src/date/date.h"
@ -5409,7 +5410,10 @@ String::ExternalStringResource* String::GetExternalStringResourceSlow() const {
}
if (i::StringShape(str).IsExternalTwoByte()) {
void* value = I::ReadRawField<void*>(str.ptr(), I::kStringResourceOffset);
internal::Isolate* isolate =
internal::IsolateFromNeverReadOnlySpaceObject(str.ptr());
internal::Address value = I::ReadExternalPointerField(
isolate, str.ptr(), I::kStringResourceOffset);
return reinterpret_cast<String::ExternalStringResource*>(value);
}
return nullptr;
@ -5431,8 +5435,11 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBaseSlow(
*encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
if (i::StringShape(str).IsExternalOneByte() ||
i::StringShape(str).IsExternalTwoByte()) {
void* value = I::ReadRawField<void*>(string, I::kStringResourceOffset);
resource = static_cast<ExternalStringResourceBase*>(value);
internal::Isolate* isolate =
internal::IsolateFromNeverReadOnlySpaceObject(string);
internal::Address value =
I::ReadExternalPointerField(isolate, string, I::kStringResourceOffset);
resource = reinterpret_cast<ExternalStringResourceBase*>(value);
}
return resource;
}

View File

@ -378,7 +378,7 @@ void Heap::FinalizeExternalString(String string) {
ExternalBackingStoreType::kExternalString,
ext_string.ExternalPayloadSize());
ext_string.DisposeResource();
ext_string.DisposeResource(isolate());
}
Address Heap::NewSpaceTop() { return new_space_->top(); }

View File

@ -5,6 +5,7 @@
#ifndef V8_OBJECTS_STRING_INL_H_
#define V8_OBJECTS_STRING_INL_H_
#include "src/common/external-pointer.h"
#include "src/objects/string.h"
#include "src/handles/handles-inl.h"
@ -600,12 +601,17 @@ bool ExternalString::is_uncached() const {
return (type & kUncachedExternalStringMask) == kUncachedExternalStringTag;
}
Address ExternalString::resource_as_address() {
return ReadField<Address>(kResourceOffset);
DEF_GETTER(ExternalString, resource_as_address, Address) {
ExternalPointer_t encoded_address =
ReadField<ExternalPointer_t>(kResourceOffset);
return DecodeExternalPointer(isolate, encoded_address);
}
void ExternalString::set_address_as_resource(Address address) {
WriteField<Address>(kResourceOffset, address);
void ExternalString::set_address_as_resource(Isolate* isolate,
Address address) {
const ExternalPointer_t encoded_address =
EncodeExternalPointer(isolate, address);
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
if (IsExternalOneByteString()) {
ExternalOneByteString::cast(*this).update_data_cache();
} else {
@ -614,29 +620,39 @@ void ExternalString::set_address_as_resource(Address address) {
}
uint32_t ExternalString::resource_as_uint32() {
return static_cast<uint32_t>(ReadField<Address>(kResourceOffset));
ExternalPointer_t encoded_address =
ReadField<ExternalPointer_t>(kResourceOffset);
return static_cast<uint32_t>(encoded_address);
}
void ExternalString::set_uint32_as_resource(uint32_t value) {
WriteField<Address>(kResourceOffset, value);
WriteField<ExternalPointer_t>(kResourceOffset, value);
if (is_uncached()) return;
WriteField<Address>(kResourceDataOffset, kNullAddress);
}
void ExternalString::DisposeResource() {
void ExternalString::DisposeResource(Isolate* isolate) {
const ExternalPointer_t encoded_address =
ReadField<ExternalPointer_t>(kResourceOffset);
v8::String::ExternalStringResourceBase* resource =
reinterpret_cast<v8::String::ExternalStringResourceBase*>(
ReadField<Address>(ExternalString::kResourceOffset));
DecodeExternalPointer(isolate, encoded_address));
// Dispose of the C++ object if it has not already been disposed.
if (resource != nullptr) {
resource->Dispose();
WriteField<Address>(ExternalString::kResourceOffset, kNullAddress);
const ExternalPointer_t encoded_address =
EncodeExternalPointer(isolate, kNullAddress);
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
}
}
const ExternalOneByteString::Resource* ExternalOneByteString::resource() {
return reinterpret_cast<Resource*>(ReadField<Address>(kResourceOffset));
DEF_GETTER(ExternalOneByteString, resource,
const ExternalOneByteString::Resource*) {
const ExternalPointer_t encoded_address =
ReadField<ExternalPointer_t>(kResourceOffset);
return reinterpret_cast<Resource*>(
DecodeExternalPointer(isolate, encoded_address));
}
void ExternalOneByteString::update_data_cache() {
@ -647,7 +663,7 @@ void ExternalOneByteString::update_data_cache() {
void ExternalOneByteString::SetResource(
Isolate* isolate, const ExternalOneByteString::Resource* resource) {
set_resource(resource);
set_resource(isolate, resource);
size_t new_payload = resource == nullptr ? 0 : resource->length();
if (new_payload > 0) {
isolate->heap()->UpdateExternalString(*this, 0, new_payload);
@ -655,8 +671,10 @@ void ExternalOneByteString::SetResource(
}
void ExternalOneByteString::set_resource(
const ExternalOneByteString::Resource* resource) {
WriteField<Address>(kResourceOffset, reinterpret_cast<Address>(resource));
Isolate* isolate, const ExternalOneByteString::Resource* resource) {
const ExternalPointer_t encoded_address =
EncodeExternalPointer(isolate, reinterpret_cast<Address>(resource));
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
if (resource != nullptr) update_data_cache();
}
@ -669,8 +687,12 @@ uint8_t ExternalOneByteString::Get(int index) {
return GetChars()[index];
}
const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
return reinterpret_cast<Resource*>(ReadField<Address>(kResourceOffset));
DEF_GETTER(ExternalTwoByteString, resource,
const ExternalTwoByteString::Resource*) {
const ExternalPointer_t encoded_address =
ReadField<ExternalPointer_t>(kResourceOffset);
return reinterpret_cast<Resource*>(
DecodeExternalPointer(isolate, encoded_address));
}
void ExternalTwoByteString::update_data_cache() {
@ -681,7 +703,7 @@ void ExternalTwoByteString::update_data_cache() {
void ExternalTwoByteString::SetResource(
Isolate* isolate, const ExternalTwoByteString::Resource* resource) {
set_resource(resource);
set_resource(isolate, resource);
size_t new_payload = resource == nullptr ? 0 : resource->length() * 2;
if (new_payload > 0) {
isolate->heap()->UpdateExternalString(*this, 0, new_payload);
@ -689,8 +711,10 @@ void ExternalTwoByteString::SetResource(
}
void ExternalTwoByteString::set_resource(
const ExternalTwoByteString::Resource* resource) {
WriteField<Address>(kResourceOffset, reinterpret_cast<Address>(resource));
Isolate* isolate, const ExternalTwoByteString::Resource* resource) {
const ExternalPointer_t encoded_address =
EncodeExternalPointer(isolate, reinterpret_cast<Address>(resource));
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
if (resource != nullptr) update_data_cache();
}

View File

@ -716,13 +716,13 @@ class ExternalString : public String {
int ExternalPayloadSize() const;
// Used in the serializer/deserializer.
inline Address resource_as_address();
inline void set_address_as_resource(Address address);
DECL_GETTER(resource_as_address, Address)
inline void set_address_as_resource(Isolate* isolate, Address address);
inline uint32_t resource_as_uint32();
inline void set_uint32_as_resource(uint32_t value);
// Disposes string's resource object if it has not already been disposed.
inline void DisposeResource();
inline void DisposeResource(Isolate* isolate);
STATIC_ASSERT(kResourceOffset == Internals::kStringResourceOffset);
static const int kSizeOfAllExternalStrings = kHeaderSize;
@ -739,13 +739,13 @@ class ExternalOneByteString : public ExternalString {
using Resource = v8::String::ExternalOneByteStringResource;
// The underlying resource.
inline const Resource* resource();
DECL_GETTER(resource, const Resource*)
// It is assumed that the previous resource is null. If it is not null, then
// it is the responsability of the caller the handle the previous resource.
inline void SetResource(Isolate* isolate, const Resource* buffer);
// Used only during serialization.
inline void set_resource(const Resource* buffer);
inline void set_resource(Isolate* isolate, const Resource* buffer);
// Update the pointer cache to the external character array.
// The cached pointer is always valid, as the external character array does =
@ -780,13 +780,13 @@ class ExternalTwoByteString : public ExternalString {
using Resource = v8::String::ExternalStringResource;
// The underlying string resource.
inline const Resource* resource();
DECL_GETTER(resource, const Resource*)
// It is assumed that the previous resource is null. If it is not null, then
// it is the responsability of the caller the handle the previous resource.
inline void SetResource(Isolate* isolate, const Resource* buffer);
// Used only during serialization.
inline void set_resource(const Resource* buffer);
inline void set_resource(Isolate* isolate, const Resource* buffer);
// Update the pointer cache to the external character array.
// The cached pointer is always valid, as the external character array does =

View File

@ -19,7 +19,7 @@ extern class ConsString extends String {
@abstract
@generateBodyDescriptor
extern class ExternalString extends String {
resource: RawPtr;
resource: ExternalPointer;
resource_data: RawPtr;
}

View File

@ -279,7 +279,7 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj,
uint32_t index = string.resource_as_uint32();
Address address =
static_cast<Address>(isolate_->api_external_references()[index]);
string.set_address_as_resource(address);
string.set_address_as_resource(isolate_, address);
isolate_->heap()->UpdateExternalString(string, 0,
string.ExternalPayloadSize());
isolate_->heap()->RegisterExternalString(String::cast(obj));

View File

@ -415,7 +415,7 @@ void Serializer::ObjectSerializer::SerializeExternalString() {
DCHECK(reference.is_from_api());
string.set_uint32_as_resource(reference.index());
SerializeObject();
string.set_address_as_resource(resource);
string.set_address_as_resource(serializer_->isolate(), resource);
} else {
SerializeExternalStringAsSequentialString();
}