[sandbox] Access ExternalString ResourceData via bottlenecks

Bug: v8:10391
Change-Id: I4e86394c53d02eab797c2daad2ccfde6acb83bf0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2151350
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67619}
This commit is contained in:
Leszek Swirski 2020-05-06 17:45:50 +02:00 committed by Commit Bot
parent 8140856013
commit 4d1f17e4d6
9 changed files with 53 additions and 39 deletions

View File

@ -20,10 +20,10 @@ namespace internal {
using Node = compiler::Node;
TNode<IntPtrT> StringBuiltinsAssembler::DirectStringData(
TNode<RawPtrT> StringBuiltinsAssembler::DirectStringData(
TNode<String> string, TNode<Word32T> string_instance_type) {
// Compute the effective offset of the first character.
TVARIABLE(IntPtrT, var_data);
TVARIABLE(RawPtrT, var_data);
Label if_sequential(this), if_external(this), if_join(this);
Branch(Word32Equal(Word32And(string_instance_type,
Int32Constant(kStringRepresentationMask)),
@ -32,9 +32,9 @@ TNode<IntPtrT> StringBuiltinsAssembler::DirectStringData(
BIND(&if_sequential);
{
var_data = IntPtrAdd(
IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
BitcastTaggedToWord(string));
var_data = RawPtrAdd(
ReinterpretCast<RawPtrT>(BitcastTaggedToWord(string)),
IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
Goto(&if_join);
}
@ -47,7 +47,7 @@ TNode<IntPtrT> StringBuiltinsAssembler::DirectStringData(
Int32Constant(kUncachedExternalStringMask)),
Int32Constant(kUncachedExternalStringTag)));
var_data =
LoadObjectField<IntPtrT>(string, ExternalString::kResourceDataOffset);
DecodeExternalPointer(LoadExternalStringResourceData(CAST(string)));
Goto(&if_join);
}
@ -254,8 +254,8 @@ void StringBuiltinsAssembler::StringEqual_Loop(
CSA_ASSERT(this, WordEqual(LoadStringLengthAsWord(rhs), length));
// Compute the effective offset of the first character.
TNode<IntPtrT> lhs_data = DirectStringData(lhs, lhs_instance_type);
TNode<IntPtrT> rhs_data = DirectStringData(rhs, rhs_instance_type);
TNode<RawPtrT> lhs_data = DirectStringData(lhs, lhs_instance_type);
TNode<RawPtrT> rhs_data = DirectStringData(rhs, rhs_instance_type);
// Loop over the {lhs} and {rhs} strings to see if they are equal.
TVARIABLE(IntPtrT, var_offset, IntPtrConstant(0));

View File

@ -67,7 +67,7 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
TNode<Word32T> rhs_instance_type, MachineType rhs_type,
TNode<IntPtrT> length, Label* if_equal,
Label* if_not_equal);
TNode<IntPtrT> DirectStringData(TNode<String> string,
TNode<RawPtrT> DirectStringData(TNode<String> string,
TNode<Word32T> string_instance_type);
void DispatchOnStringEncodings(const TNode<Word32T> lhs_instance_type,

View File

@ -6881,12 +6881,13 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential(
{
STATIC_ASSERT(SeqOneByteString::kHeaderSize ==
SeqTwoByteString::kHeaderSize);
TNode<IntPtrT> result = BitcastTaggedToWord(var_string_.value());
TNode<RawPtrT> result =
ReinterpretCast<RawPtrT>(BitcastTaggedToWord(var_string_.value()));
if (ptr_kind == PTR_TO_DATA) {
result = IntPtrAdd(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
result = RawPtrAdd(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
kHeapObjectTag));
}
var_result = ReinterpretCast<RawPtrT>(result);
var_result = result;
Goto(&out);
}
@ -6896,13 +6897,13 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential(
if_bailout);
TNode<String> string = var_string_.value();
TNode<IntPtrT> result =
LoadObjectField<IntPtrT>(string, ExternalString::kResourceDataOffset);
TNode<RawPtrT> result =
DecodeExternalPointer(LoadExternalStringResourceData(CAST(string)));
if (ptr_kind == PTR_TO_STRING) {
result = IntPtrSub(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
result = RawPtrSub(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
kHeapObjectTag));
}
var_result = ReinterpretCast<RawPtrT>(result);
var_result = result;
Goto(&out);
}

View File

@ -691,7 +691,8 @@ FieldAccess AccessBuilder::ForExternalStringResourceData() {
ExternalString::kResourceDataOffset,
Handle<Name>(),
MaybeHandle<Map>(),
Type::ExternalPointer(),
V8_HEAP_SANDBOX_BOOL ? Type::SandboxedExternalPointer()
: Type::ExternalPointer(),
MachineType::Pointer(),
kNoWriteBarrier};
return access;

View File

@ -5,9 +5,9 @@
#ifndef V8_OBJECTS_STRING_INL_H_
#define V8_OBJECTS_STRING_INL_H_
#include "src/common/external-pointer-inl.h"
#include "src/common/external-pointer.h"
#include "src/objects/string.h"
#include "src/common/globals.h"
#include "src/handles/handles-inl.h"
#include "src/heap/factory.h"
#include "src/numbers/conversions-inl.h"
@ -15,6 +15,7 @@
#include "src/objects/name-inl.h"
#include "src/objects/smi-inl.h"
#include "src/objects/string-table-inl.h"
#include "src/objects/string.h"
#include "src/strings/string-hasher-inl.h"
// Has to be the last include (doesn't have include guards):
@ -613,9 +614,9 @@ void ExternalString::set_address_as_resource(Isolate* isolate,
EncodeExternalPointer(isolate, address);
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
if (IsExternalOneByteString()) {
ExternalOneByteString::cast(*this).update_data_cache();
ExternalOneByteString::cast(*this).update_data_cache(isolate);
} else {
ExternalTwoByteString::cast(*this).update_data_cache();
ExternalTwoByteString::cast(*this).update_data_cache(isolate);
}
}
@ -625,10 +626,11 @@ uint32_t ExternalString::resource_as_uint32() {
return static_cast<uint32_t>(encoded_address);
}
void ExternalString::set_uint32_as_resource(uint32_t value) {
void ExternalString::set_uint32_as_resource(Isolate* isolate, uint32_t value) {
WriteField<ExternalPointer_t>(kResourceOffset, value);
if (is_uncached()) return;
WriteField<Address>(kResourceDataOffset, kNullAddress);
WriteField<ExternalPointer_t>(kResourceDataOffset,
EncodeExternalPointer(isolate, kNullAddress));
}
void ExternalString::DisposeResource(Isolate* isolate) {
@ -655,10 +657,11 @@ DEF_GETTER(ExternalOneByteString, resource,
DecodeExternalPointer(isolate, encoded_address));
}
void ExternalOneByteString::update_data_cache() {
void ExternalOneByteString::update_data_cache(Isolate* isolate) {
if (is_uncached()) return;
WriteField<Address>(kResourceDataOffset,
reinterpret_cast<Address>(resource()->data()));
const ExternalPointer_t encoded_resource_data = EncodeExternalPointer(
isolate, reinterpret_cast<Address>(resource()->data()));
WriteField<ExternalPointer_t>(kResourceDataOffset, encoded_resource_data);
}
void ExternalOneByteString::SetResource(
@ -675,7 +678,7 @@ void ExternalOneByteString::set_resource(
const ExternalPointer_t encoded_address =
EncodeExternalPointer(isolate, reinterpret_cast<Address>(resource));
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
if (resource != nullptr) update_data_cache();
if (resource != nullptr) update_data_cache(isolate);
}
const uint8_t* ExternalOneByteString::GetChars() {
@ -695,10 +698,11 @@ DEF_GETTER(ExternalTwoByteString, resource,
DecodeExternalPointer(isolate, encoded_address));
}
void ExternalTwoByteString::update_data_cache() {
void ExternalTwoByteString::update_data_cache(Isolate* isolate) {
if (is_uncached()) return;
WriteField<Address>(kResourceDataOffset,
reinterpret_cast<Address>(resource()->data()));
const ExternalPointer_t encoded_resource_data = EncodeExternalPointer(
isolate, reinterpret_cast<Address>(resource()->data()));
WriteField<ExternalPointer_t>(kResourceDataOffset, encoded_resource_data);
}
void ExternalTwoByteString::SetResource(
@ -715,7 +719,7 @@ void ExternalTwoByteString::set_resource(
const ExternalPointer_t encoded_address =
EncodeExternalPointer(isolate, reinterpret_cast<Address>(resource));
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
if (resource != nullptr) update_data_cache();
if (resource != nullptr) update_data_cache(isolate);
}
const uint16_t* ExternalTwoByteString::GetChars() { return resource()->data(); }

View File

@ -719,7 +719,7 @@ class ExternalString : public String {
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);
inline void set_uint32_as_resource(Isolate* isolate, uint32_t value);
// Disposes string's resource object if it has not already been disposed.
inline void DisposeResource(Isolate* isolate);
@ -751,7 +751,7 @@ class ExternalOneByteString : public ExternalString {
// The cached pointer is always valid, as the external character array does =
// not move during lifetime. Deserialization is the only exception, after
// which the pointer cache has to be refreshed.
inline void update_data_cache();
inline void update_data_cache(Isolate* isolate);
inline const uint8_t* GetChars();
@ -792,7 +792,7 @@ class ExternalTwoByteString : public ExternalString {
// The cached pointer is always valid, as the external character array does =
// not move during lifetime. Deserialization is the only exception, after
// which the pointer cache has to be refreshed.
inline void update_data_cache();
inline void update_data_cache(Isolate* isolate);
inline const uint16_t* GetChars();

View File

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

View File

@ -413,7 +413,7 @@ void Serializer::ObjectSerializer::SerializeExternalString() {
if (serializer_->external_reference_encoder_.TryEncode(resource).To(
&reference)) {
DCHECK(reference.is_from_api());
string.set_uint32_as_resource(reference.index());
string.set_uint32_as_resource(serializer_->isolate(), reference.index());
SerializeObject();
string.set_address_as_resource(serializer_->isolate(), resource);
} else {

View File

@ -7,7 +7,8 @@
#include "debug-helper-internal.h"
#include "heap-constants.h"
#include "include/v8-internal.h"
#include "src/common/ptr-compr-inl.h"
#include "src/common/external-pointer.h"
#include "src/execution/isolate-utils.h"
#include "src/objects/string-inl.h"
#include "src/strings/unicode-inl.h"
#include "torque-generated/class-debug-readers-tq.h"
@ -323,8 +324,15 @@ class ReadStringVisitor : public TqObjectVisitor {
// require knowledge of the embedder. For now, we only read cached external
// strings.
if (IsExternalStringCached(object)) {
uintptr_t data_address = reinterpret_cast<uintptr_t>(
GetOrFinish(object->GetResourceDataValue(accessor_)));
ExternalPointer_t resource_data =
GetOrFinish(object->GetResourceDataValue(accessor_));
#ifdef V8_COMPRESS_POINTERS
uintptr_t data_address = static_cast<uintptr_t>(DecodeExternalPointer(
Isolate::FromRoot(GetIsolateRoot(heap_addresses_.any_heap_pointer)),
resource_data));
#else
uintptr_t data_address = reinterpret_cast<uintptr_t>(resource_data);
#endif // V8_COMPRESS_POINTERS
if (done_) return;
ReadStringCharacters<TChar>(object, data_address);
} else {