[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:
parent
8140856013
commit
4d1f17e4d6
@ -20,10 +20,10 @@ namespace internal {
|
|||||||
|
|
||||||
using Node = compiler::Node;
|
using Node = compiler::Node;
|
||||||
|
|
||||||
TNode<IntPtrT> StringBuiltinsAssembler::DirectStringData(
|
TNode<RawPtrT> StringBuiltinsAssembler::DirectStringData(
|
||||||
TNode<String> string, TNode<Word32T> string_instance_type) {
|
TNode<String> string, TNode<Word32T> string_instance_type) {
|
||||||
// Compute the effective offset of the first character.
|
// 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);
|
Label if_sequential(this), if_external(this), if_join(this);
|
||||||
Branch(Word32Equal(Word32And(string_instance_type,
|
Branch(Word32Equal(Word32And(string_instance_type,
|
||||||
Int32Constant(kStringRepresentationMask)),
|
Int32Constant(kStringRepresentationMask)),
|
||||||
@ -32,9 +32,9 @@ TNode<IntPtrT> StringBuiltinsAssembler::DirectStringData(
|
|||||||
|
|
||||||
BIND(&if_sequential);
|
BIND(&if_sequential);
|
||||||
{
|
{
|
||||||
var_data = IntPtrAdd(
|
var_data = RawPtrAdd(
|
||||||
IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
|
ReinterpretCast<RawPtrT>(BitcastTaggedToWord(string)),
|
||||||
BitcastTaggedToWord(string));
|
IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||||
Goto(&if_join);
|
Goto(&if_join);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ TNode<IntPtrT> StringBuiltinsAssembler::DirectStringData(
|
|||||||
Int32Constant(kUncachedExternalStringMask)),
|
Int32Constant(kUncachedExternalStringMask)),
|
||||||
Int32Constant(kUncachedExternalStringTag)));
|
Int32Constant(kUncachedExternalStringTag)));
|
||||||
var_data =
|
var_data =
|
||||||
LoadObjectField<IntPtrT>(string, ExternalString::kResourceDataOffset);
|
DecodeExternalPointer(LoadExternalStringResourceData(CAST(string)));
|
||||||
Goto(&if_join);
|
Goto(&if_join);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,8 +254,8 @@ void StringBuiltinsAssembler::StringEqual_Loop(
|
|||||||
CSA_ASSERT(this, WordEqual(LoadStringLengthAsWord(rhs), length));
|
CSA_ASSERT(this, WordEqual(LoadStringLengthAsWord(rhs), length));
|
||||||
|
|
||||||
// Compute the effective offset of the first character.
|
// Compute the effective offset of the first character.
|
||||||
TNode<IntPtrT> lhs_data = DirectStringData(lhs, lhs_instance_type);
|
TNode<RawPtrT> lhs_data = DirectStringData(lhs, lhs_instance_type);
|
||||||
TNode<IntPtrT> rhs_data = DirectStringData(rhs, rhs_instance_type);
|
TNode<RawPtrT> rhs_data = DirectStringData(rhs, rhs_instance_type);
|
||||||
|
|
||||||
// Loop over the {lhs} and {rhs} strings to see if they are equal.
|
// Loop over the {lhs} and {rhs} strings to see if they are equal.
|
||||||
TVARIABLE(IntPtrT, var_offset, IntPtrConstant(0));
|
TVARIABLE(IntPtrT, var_offset, IntPtrConstant(0));
|
||||||
|
@ -67,7 +67,7 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
|
|||||||
TNode<Word32T> rhs_instance_type, MachineType rhs_type,
|
TNode<Word32T> rhs_instance_type, MachineType rhs_type,
|
||||||
TNode<IntPtrT> length, Label* if_equal,
|
TNode<IntPtrT> length, Label* if_equal,
|
||||||
Label* if_not_equal);
|
Label* if_not_equal);
|
||||||
TNode<IntPtrT> DirectStringData(TNode<String> string,
|
TNode<RawPtrT> DirectStringData(TNode<String> string,
|
||||||
TNode<Word32T> string_instance_type);
|
TNode<Word32T> string_instance_type);
|
||||||
|
|
||||||
void DispatchOnStringEncodings(const TNode<Word32T> lhs_instance_type,
|
void DispatchOnStringEncodings(const TNode<Word32T> lhs_instance_type,
|
||||||
|
@ -6881,12 +6881,13 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential(
|
|||||||
{
|
{
|
||||||
STATIC_ASSERT(SeqOneByteString::kHeaderSize ==
|
STATIC_ASSERT(SeqOneByteString::kHeaderSize ==
|
||||||
SeqTwoByteString::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) {
|
if (ptr_kind == PTR_TO_DATA) {
|
||||||
result = IntPtrAdd(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
|
result = RawPtrAdd(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
|
||||||
kHeapObjectTag));
|
kHeapObjectTag));
|
||||||
}
|
}
|
||||||
var_result = ReinterpretCast<RawPtrT>(result);
|
var_result = result;
|
||||||
Goto(&out);
|
Goto(&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6896,13 +6897,13 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential(
|
|||||||
if_bailout);
|
if_bailout);
|
||||||
|
|
||||||
TNode<String> string = var_string_.value();
|
TNode<String> string = var_string_.value();
|
||||||
TNode<IntPtrT> result =
|
TNode<RawPtrT> result =
|
||||||
LoadObjectField<IntPtrT>(string, ExternalString::kResourceDataOffset);
|
DecodeExternalPointer(LoadExternalStringResourceData(CAST(string)));
|
||||||
if (ptr_kind == PTR_TO_STRING) {
|
if (ptr_kind == PTR_TO_STRING) {
|
||||||
result = IntPtrSub(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
|
result = RawPtrSub(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
|
||||||
kHeapObjectTag));
|
kHeapObjectTag));
|
||||||
}
|
}
|
||||||
var_result = ReinterpretCast<RawPtrT>(result);
|
var_result = result;
|
||||||
Goto(&out);
|
Goto(&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,7 +691,8 @@ FieldAccess AccessBuilder::ForExternalStringResourceData() {
|
|||||||
ExternalString::kResourceDataOffset,
|
ExternalString::kResourceDataOffset,
|
||||||
Handle<Name>(),
|
Handle<Name>(),
|
||||||
MaybeHandle<Map>(),
|
MaybeHandle<Map>(),
|
||||||
Type::ExternalPointer(),
|
V8_HEAP_SANDBOX_BOOL ? Type::SandboxedExternalPointer()
|
||||||
|
: Type::ExternalPointer(),
|
||||||
MachineType::Pointer(),
|
MachineType::Pointer(),
|
||||||
kNoWriteBarrier};
|
kNoWriteBarrier};
|
||||||
return access;
|
return access;
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
#ifndef V8_OBJECTS_STRING_INL_H_
|
#ifndef V8_OBJECTS_STRING_INL_H_
|
||||||
#define 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/common/external-pointer.h"
|
||||||
#include "src/objects/string.h"
|
#include "src/common/globals.h"
|
||||||
|
|
||||||
#include "src/handles/handles-inl.h"
|
#include "src/handles/handles-inl.h"
|
||||||
#include "src/heap/factory.h"
|
#include "src/heap/factory.h"
|
||||||
#include "src/numbers/conversions-inl.h"
|
#include "src/numbers/conversions-inl.h"
|
||||||
@ -15,6 +15,7 @@
|
|||||||
#include "src/objects/name-inl.h"
|
#include "src/objects/name-inl.h"
|
||||||
#include "src/objects/smi-inl.h"
|
#include "src/objects/smi-inl.h"
|
||||||
#include "src/objects/string-table-inl.h"
|
#include "src/objects/string-table-inl.h"
|
||||||
|
#include "src/objects/string.h"
|
||||||
#include "src/strings/string-hasher-inl.h"
|
#include "src/strings/string-hasher-inl.h"
|
||||||
|
|
||||||
// Has to be the last include (doesn't have include guards):
|
// 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);
|
EncodeExternalPointer(isolate, address);
|
||||||
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
|
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
|
||||||
if (IsExternalOneByteString()) {
|
if (IsExternalOneByteString()) {
|
||||||
ExternalOneByteString::cast(*this).update_data_cache();
|
ExternalOneByteString::cast(*this).update_data_cache(isolate);
|
||||||
} else {
|
} 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);
|
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);
|
WriteField<ExternalPointer_t>(kResourceOffset, value);
|
||||||
if (is_uncached()) return;
|
if (is_uncached()) return;
|
||||||
WriteField<Address>(kResourceDataOffset, kNullAddress);
|
WriteField<ExternalPointer_t>(kResourceDataOffset,
|
||||||
|
EncodeExternalPointer(isolate, kNullAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExternalString::DisposeResource(Isolate* isolate) {
|
void ExternalString::DisposeResource(Isolate* isolate) {
|
||||||
@ -655,10 +657,11 @@ DEF_GETTER(ExternalOneByteString, resource,
|
|||||||
DecodeExternalPointer(isolate, encoded_address));
|
DecodeExternalPointer(isolate, encoded_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExternalOneByteString::update_data_cache() {
|
void ExternalOneByteString::update_data_cache(Isolate* isolate) {
|
||||||
if (is_uncached()) return;
|
if (is_uncached()) return;
|
||||||
WriteField<Address>(kResourceDataOffset,
|
const ExternalPointer_t encoded_resource_data = EncodeExternalPointer(
|
||||||
reinterpret_cast<Address>(resource()->data()));
|
isolate, reinterpret_cast<Address>(resource()->data()));
|
||||||
|
WriteField<ExternalPointer_t>(kResourceDataOffset, encoded_resource_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExternalOneByteString::SetResource(
|
void ExternalOneByteString::SetResource(
|
||||||
@ -675,7 +678,7 @@ void ExternalOneByteString::set_resource(
|
|||||||
const ExternalPointer_t encoded_address =
|
const ExternalPointer_t encoded_address =
|
||||||
EncodeExternalPointer(isolate, reinterpret_cast<Address>(resource));
|
EncodeExternalPointer(isolate, reinterpret_cast<Address>(resource));
|
||||||
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
|
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
|
||||||
if (resource != nullptr) update_data_cache();
|
if (resource != nullptr) update_data_cache(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* ExternalOneByteString::GetChars() {
|
const uint8_t* ExternalOneByteString::GetChars() {
|
||||||
@ -695,10 +698,11 @@ DEF_GETTER(ExternalTwoByteString, resource,
|
|||||||
DecodeExternalPointer(isolate, encoded_address));
|
DecodeExternalPointer(isolate, encoded_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExternalTwoByteString::update_data_cache() {
|
void ExternalTwoByteString::update_data_cache(Isolate* isolate) {
|
||||||
if (is_uncached()) return;
|
if (is_uncached()) return;
|
||||||
WriteField<Address>(kResourceDataOffset,
|
const ExternalPointer_t encoded_resource_data = EncodeExternalPointer(
|
||||||
reinterpret_cast<Address>(resource()->data()));
|
isolate, reinterpret_cast<Address>(resource()->data()));
|
||||||
|
WriteField<ExternalPointer_t>(kResourceDataOffset, encoded_resource_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExternalTwoByteString::SetResource(
|
void ExternalTwoByteString::SetResource(
|
||||||
@ -715,7 +719,7 @@ void ExternalTwoByteString::set_resource(
|
|||||||
const ExternalPointer_t encoded_address =
|
const ExternalPointer_t encoded_address =
|
||||||
EncodeExternalPointer(isolate, reinterpret_cast<Address>(resource));
|
EncodeExternalPointer(isolate, reinterpret_cast<Address>(resource));
|
||||||
WriteField<ExternalPointer_t>(kResourceOffset, encoded_address);
|
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(); }
|
const uint16_t* ExternalTwoByteString::GetChars() { return resource()->data(); }
|
||||||
|
@ -719,7 +719,7 @@ class ExternalString : public String {
|
|||||||
DECL_GETTER(resource_as_address, Address)
|
DECL_GETTER(resource_as_address, Address)
|
||||||
inline void set_address_as_resource(Isolate* isolate, Address address);
|
inline void set_address_as_resource(Isolate* isolate, Address address);
|
||||||
inline uint32_t resource_as_uint32();
|
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.
|
// Disposes string's resource object if it has not already been disposed.
|
||||||
inline void DisposeResource(Isolate* isolate);
|
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 =
|
// The cached pointer is always valid, as the external character array does =
|
||||||
// not move during lifetime. Deserialization is the only exception, after
|
// not move during lifetime. Deserialization is the only exception, after
|
||||||
// which the pointer cache has to be refreshed.
|
// 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();
|
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 =
|
// The cached pointer is always valid, as the external character array does =
|
||||||
// not move during lifetime. Deserialization is the only exception, after
|
// not move during lifetime. Deserialization is the only exception, after
|
||||||
// which the pointer cache has to be refreshed.
|
// 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();
|
inline const uint16_t* GetChars();
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ extern class ConsString extends String {
|
|||||||
@generateBodyDescriptor
|
@generateBodyDescriptor
|
||||||
extern class ExternalString extends String {
|
extern class ExternalString extends String {
|
||||||
resource: ExternalPointer;
|
resource: ExternalPointer;
|
||||||
resource_data: RawPtr;
|
resource_data: ExternalPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class ExternalOneByteString extends ExternalString {}
|
extern class ExternalOneByteString extends ExternalString {}
|
||||||
|
@ -413,7 +413,7 @@ void Serializer::ObjectSerializer::SerializeExternalString() {
|
|||||||
if (serializer_->external_reference_encoder_.TryEncode(resource).To(
|
if (serializer_->external_reference_encoder_.TryEncode(resource).To(
|
||||||
&reference)) {
|
&reference)) {
|
||||||
DCHECK(reference.is_from_api());
|
DCHECK(reference.is_from_api());
|
||||||
string.set_uint32_as_resource(reference.index());
|
string.set_uint32_as_resource(serializer_->isolate(), reference.index());
|
||||||
SerializeObject();
|
SerializeObject();
|
||||||
string.set_address_as_resource(serializer_->isolate(), resource);
|
string.set_address_as_resource(serializer_->isolate(), resource);
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
#include "debug-helper-internal.h"
|
#include "debug-helper-internal.h"
|
||||||
#include "heap-constants.h"
|
#include "heap-constants.h"
|
||||||
#include "include/v8-internal.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/objects/string-inl.h"
|
||||||
#include "src/strings/unicode-inl.h"
|
#include "src/strings/unicode-inl.h"
|
||||||
#include "torque-generated/class-debug-readers-tq.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
|
// require knowledge of the embedder. For now, we only read cached external
|
||||||
// strings.
|
// strings.
|
||||||
if (IsExternalStringCached(object)) {
|
if (IsExternalStringCached(object)) {
|
||||||
uintptr_t data_address = reinterpret_cast<uintptr_t>(
|
ExternalPointer_t resource_data =
|
||||||
GetOrFinish(object->GetResourceDataValue(accessor_)));
|
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;
|
if (done_) return;
|
||||||
ReadStringCharacters<TChar>(object, data_address);
|
ReadStringCharacters<TChar>(object, data_address);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user