[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;
|
||||
|
||||
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));
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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(); }
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 {}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user