Commit 806ef9ac authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[sandbox] Access external pointer in JSTypedArray via bottlenecks

Bug: v8:10391
Change-Id: If1db52dc74f9027f06104ce719514b751b4d9504
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2149417
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67515}
parent 35655a8e
......@@ -397,8 +397,8 @@ void TypedArrayBuiltinsAssembler::SetJSTypedArrayOnHeapDataPtr(
}
StoreObjectField(holder, JSTypedArray::kBasePointerOffset, base);
StoreObjectFieldNoWriteBarrier<UintPtrT>(
holder, JSTypedArray::kExternalPointerOffset, offset);
StoreJSTypedArrayExternalPointer(
holder, EncodeExternalPointer(ReinterpretCast<RawPtrT>(offset)));
}
void TypedArrayBuiltinsAssembler::SetJSTypedArrayOffHeapDataPtr(
......@@ -407,8 +407,7 @@ void TypedArrayBuiltinsAssembler::SetJSTypedArrayOffHeapDataPtr(
SmiConstant(0));
base = RawPtrAdd(base, Signed(offset));
StoreObjectFieldNoWriteBarrier<RawPtrT>(
holder, JSTypedArray::kExternalPointerOffset, base);
StoreJSTypedArrayExternalPointer(holder, EncodeExternalPointer(base));
}
void TypedArrayBuiltinsAssembler::StoreJSTypedArrayElementFromNumeric(
......
......@@ -2228,9 +2228,10 @@ TNode<IntPtrT> CodeStubAssembler::LoadPropertyArrayLength(
TNode<RawPtrT> CodeStubAssembler::LoadJSTypedArrayDataPtr(
TNode<JSTypedArray> typed_array) {
// Data pointer = external_pointer + static_cast<Tagged_t>(base_pointer).
TNode<RawPtrT> external_pointer = LoadObjectField<RawPtrT>(
typed_array, JSTypedArray::kExternalPointerOffset);
// Data pointer = DecodeExternalPointer(external_pointer) +
// static_cast<Tagged_t>(base_pointer).
TNode<RawPtrT> external_pointer =
DecodeExternalPointer(LoadJSTypedArrayExternalPointer(typed_array));
TNode<IntPtrT> base_pointer;
if (COMPRESS_POINTERS_BOOL) {
......
......@@ -1079,6 +1079,18 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
return value;
}
// Convert external pointer value to on-V8-heap representation.
// This should eventually become a call to a non-allocating runtime function.
TNode<ExternalPointerT> EncodeExternalPointer(TNode<RawPtrT> pointer) {
STATIC_ASSERT(kExternalPointerSize == kSystemPointerSize);
TNode<RawPtrT> encoded_pointer = pointer;
if (V8_HEAP_SANDBOX_BOOL) {
encoded_pointer = UncheckedCast<RawPtrT>(
WordXor(encoded_pointer, UintPtrConstant(kExternalPointerSalt)));
}
return ReinterpretCast<ExternalPointerT>(encoded_pointer);
}
// Load value from current parent frame by given offset in bytes.
TNode<Object> LoadFromParentFrame(int offset);
......
......@@ -420,7 +420,8 @@ FieldAccess AccessBuilder::ForJSTypedArrayExternalPointer() {
JSTypedArray::kExternalPointerOffset,
MaybeHandle<Name>(),
MaybeHandle<Map>(),
Type::ExternalPointer(),
V8_HEAP_SANDBOX_BOOL ? Type::SandboxedExternalPointer()
: Type::ExternalPointer(),
MachineType::Pointer(),
kNoWriteBarrier,
LoadSensitivity::kCritical};
......
......@@ -2675,7 +2675,8 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
Handle<JSTypedArray>::cast(NewJSArrayBufferView(
map, empty_byte_array(), buffer, byte_offset, byte_length));
typed_array->set_length(length);
typed_array->SetOffHeapDataPtr(buffer->backing_store(), byte_offset);
typed_array->SetOffHeapDataPtr(isolate(), buffer->backing_store(),
byte_offset);
return typed_array;
}
......
......@@ -7,6 +7,7 @@
#include "src/objects/js-array-buffer.h"
#include "src/common/external-pointer-inl.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/js-objects-inl.h"
#include "src/objects/objects-inl.h"
......@@ -185,12 +186,15 @@ void JSTypedArray::set_length(size_t value) {
WriteField<size_t>(kLengthOffset, value);
}
Address JSTypedArray::external_pointer() const {
return ReadField<Address>(kExternalPointerOffset);
DEF_GETTER(JSTypedArray, external_pointer, Address) {
ExternalPointer_t encoded_value =
ReadField<ExternalPointer_t>(kExternalPointerOffset);
return DecodeExternalPointer(isolate, encoded_value);
}
void JSTypedArray::set_external_pointer(Address value) {
WriteField<Address>(kExternalPointerOffset, value);
void JSTypedArray::set_external_pointer(Isolate* isolate, Address value) {
ExternalPointer_t encoded_value = EncodeExternalPointer(isolate, value);
WriteField<ExternalPointer_t>(kExternalPointerOffset, encoded_value);
}
Address JSTypedArray::ExternalPointerCompensationForOnHeapArray(
......@@ -202,11 +206,29 @@ Address JSTypedArray::ExternalPointerCompensationForOnHeapArray(
#endif
}
void JSTypedArray::RemoveExternalPointerCompensationForSerialization() {
uint32_t JSTypedArray::GetExternalBackingStoreRefForDeserialization() const {
DCHECK(!is_on_heap());
ExternalPointer_t encoded_value =
ReadField<ExternalPointer_t>(kExternalPointerOffset);
return static_cast<uint32_t>(encoded_value);
}
void JSTypedArray::SetExternalBackingStoreRefForSerialization(uint32_t ref) {
DCHECK(!is_on_heap());
ExternalPointer_t encoded_value = ref;
WriteField<ExternalPointer_t>(kExternalPointerOffset, encoded_value);
}
void JSTypedArray::RemoveExternalPointerCompensationForSerialization(
Isolate* isolate) {
DCHECK(is_on_heap());
const Isolate* isolate = GetIsolateForPtrCompr(*this);
set_external_pointer(external_pointer() -
ExternalPointerCompensationForOnHeapArray(isolate));
// TODO(v8:10391): once we have an external table, avoid the need for
// compensation by replacing external_pointer and base_pointer fields
// with one data_pointer field which can point to either external data
// backing store or into on-heap backing store.
set_external_pointer(
isolate,
external_pointer() - ExternalPointerCompensationForOnHeapArray(isolate));
}
ACCESSORS(JSTypedArray, base_pointer, Object, kBasePointerOffset)
......@@ -220,18 +242,19 @@ void* JSTypedArray::DataPtr() {
static_cast<Tagged_t>(base_pointer().ptr()));
}
void JSTypedArray::SetOffHeapDataPtr(void* base, Address offset) {
void JSTypedArray::SetOffHeapDataPtr(Isolate* isolate, void* base,
Address offset) {
set_base_pointer(Smi::zero(), SKIP_WRITE_BARRIER);
Address address = reinterpret_cast<Address>(base) + offset;
set_external_pointer(address);
set_external_pointer(isolate, address);
DCHECK_EQ(address, reinterpret_cast<Address>(DataPtr()));
}
void JSTypedArray::SetOnHeapDataPtr(HeapObject base, Address offset) {
void JSTypedArray::SetOnHeapDataPtr(Isolate* isolate, HeapObject base,
Address offset) {
set_base_pointer(base);
const Isolate* isolate = GetIsolateForPtrCompr(*this);
set_external_pointer(offset +
ExternalPointerCompensationForOnHeapArray(isolate));
set_external_pointer(
isolate, offset + ExternalPointerCompensationForOnHeapArray(isolate));
DCHECK_EQ(base.ptr() + offset, reinterpret_cast<Address>(DataPtr()));
}
......
......@@ -193,7 +193,7 @@ Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
// Clear the elements of the typed array.
self->set_elements(ReadOnlyRoots(isolate).empty_byte_array());
self->SetOffHeapDataPtr(array_buffer->backing_store(), 0);
self->SetOffHeapDataPtr(isolate, array_buffer->backing_store(), 0);
DCHECK(!self->is_on_heap());
return array_buffer;
......
......@@ -270,8 +270,9 @@ class JSTypedArray : public JSArrayBufferView {
// Use with care: returns raw pointer into heap.
inline void* DataPtr();
inline void SetOffHeapDataPtr(void* base, Address offset);
inline void SetOnHeapDataPtr(HeapObject base, Address offset);
inline void SetOffHeapDataPtr(Isolate* isolate, void* base, Address offset);
inline void SetOnHeapDataPtr(Isolate* isolate, HeapObject base,
Address offset);
// Whether the buffer's backing store is on-heap or off-heap.
inline bool is_on_heap() const;
......@@ -288,8 +289,21 @@ class JSTypedArray : public JSArrayBufferView {
static inline Address ExternalPointerCompensationForOnHeapArray(
const Isolate* isolate);
//
// Serializer/deserializer support.
//
// External backing stores are serialized/deserialized separately.
// During serialization the backing store reference is stored in the typed
// array object and upon deserialization it is converted back to actual
// external (off-heap) pointer value.
// The backing store reference is stored in the external_pointer field.
inline uint32_t GetExternalBackingStoreRefForDeserialization() const;
inline void SetExternalBackingStoreRefForSerialization(uint32_t ref);
// Subtracts external pointer compensation from the external pointer value.
inline void RemoveExternalPointerCompensationForSerialization();
inline void RemoveExternalPointerCompensationForSerialization(
Isolate* isolate);
static inline MaybeHandle<JSTypedArray> Validate(Isolate* isolate,
Handle<Object> receiver,
......@@ -300,12 +314,12 @@ class JSTypedArray : public JSArrayBufferView {
DECL_VERIFIER(JSTypedArray)
// Layout description.
#define JS_TYPED_ARRAY_FIELDS(V) \
/* Raw data fields. */ \
V(kLengthOffset, kUIntptrSize) \
V(kExternalPointerOffset, kSystemPointerSize) \
V(kBasePointerOffset, kTaggedSize) \
/* Header size. */ \
#define JS_TYPED_ARRAY_FIELDS(V) \
/* Raw data fields. */ \
V(kLengthOffset, kUIntptrSize) \
V(kExternalPointerOffset, kExternalPointerSize) \
V(kBasePointerOffset, kTaggedSize) \
/* Header size. */ \
V(kHeaderSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSArrayBufferView::kHeaderSize,
......@@ -334,7 +348,8 @@ class JSTypedArray : public JSArrayBufferView {
DECL_ACCESSORS(base_pointer, Object)
// [external_pointer]: TODO(v8:4153)
DECL_PRIMITIVE_ACCESSORS(external_pointer, Address)
DECL_GETTER(external_pointer, Address)
inline void set_external_pointer(Isolate* isolate, Address value);
OBJECT_CONSTRUCTORS(JSTypedArray, JSArrayBufferView);
};
......
......@@ -39,7 +39,7 @@ extern class JSArrayBufferView extends JSObject {
extern class JSTypedArray extends JSArrayBufferView {
length: uintptr;
external_pointer: RawPtr;
external_pointer: ExternalPointer;
base_pointer: ByteArray|Smi;
}
......
......@@ -300,16 +300,19 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj,
JSTypedArray typed_array = JSTypedArray::cast(obj);
// Fixup typed array pointers.
if (typed_array.is_on_heap()) {
typed_array.SetOnHeapDataPtr(HeapObject::cast(typed_array.base_pointer()),
typed_array.SetOnHeapDataPtr(isolate(),
HeapObject::cast(typed_array.base_pointer()),
typed_array.external_pointer());
} else {
// Serializer writes backing store ref as a DataPtr() value.
size_t store_index = reinterpret_cast<size_t>(typed_array.DataPtr());
uint32_t store_index =
typed_array.GetExternalBackingStoreRefForDeserialization();
auto backing_store = backing_stores_[store_index];
auto start = backing_store
? reinterpret_cast<byte*>(backing_store->buffer_start())
: nullptr;
typed_array.SetOffHeapDataPtr(start, typed_array.byte_offset());
typed_array.SetOffHeapDataPtr(isolate(), start,
typed_array.byte_offset());
}
} else if (obj.IsJSArrayBuffer()) {
JSArrayBuffer buffer = JSArrayBuffer::cast(obj);
......
......@@ -353,7 +353,8 @@ uint32_t Serializer::ObjectSerializer::SerializeBackingStore(
void Serializer::ObjectSerializer::SerializeJSTypedArray() {
JSTypedArray typed_array = JSTypedArray::cast(object_);
if (typed_array.is_on_heap()) {
typed_array.RemoveExternalPointerCompensationForSerialization();
typed_array.RemoveExternalPointerCompensationForSerialization(
serializer_->isolate());
} else {
if (!typed_array.WasDetached()) {
// Explicitly serialize the backing store now.
......@@ -369,13 +370,9 @@ void Serializer::ObjectSerializer::SerializeJSTypedArray() {
reinterpret_cast<Address>(typed_array.DataPtr()) - byte_offset);
uint32_t ref = SerializeBackingStore(backing_store, byte_length);
// To properly share the buffer, we set the backing store ref as an
// off-heap offset from nullptr. On deserialization we re-set data
// pointer to proper value.
typed_array.SetOffHeapDataPtr(nullptr, ref);
DCHECK_EQ(ref, reinterpret_cast<Address>(typed_array.DataPtr()));
typed_array.SetExternalBackingStoreRefForSerialization(ref);
} else {
typed_array.SetOffHeapDataPtr(nullptr, 0);
typed_array.SetExternalBackingStoreRefForSerialization(0);
}
}
SerializeObject();
......
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