Commit 8ca93205 authored by Samuel Groß's avatar Samuel Groß Committed by V8 LUCI CQ

[sandbox] Turn ExternalPointerTag into a template parameter

The ExternalPointerTags are assumed to be compile-time constants in most
cases, so turning them into template parameters enforces that. As
decisions such as whether to use the per-isolate or the shared external
pointer table are encoded into the tag values, forcing those to be
compile-time constants guarantees that the compiler will be able to
inline the correct logic when accessing an external pointer.

With this, there are now two (high-level) ways of accessing external pointer fields from C++: the Read/WriteExternalPointerField methods
which require the ExternalPointerTag to be a template parameter, and the
ExternalPointerSlot class which takes the tag as an argument. The latter
is for example used for snapshot deserialization and by the garbage
collector (more generally, by the ObjectVisitor::VisitExternalPointer
method), where the tag is not a compile-time constant.

Finally, this CL also introduces a new ExternalPointerHandle type which
represents the (opaque) on-heap representation of a reference to an
entry in an ExternalPointerTable when sandboxing is enabled. Making this
its own type makes the code a bit more readable.

Bug: v8:10391
Change-Id: I867b8ce41d15d485f1dc66786f233c710c56afcb
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3720641Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81402}
parent d37910f5
......@@ -381,8 +381,8 @@ void* Context::GetAlignedPointerFromEmbedderData(int index) {
#endif
Isolate* isolate = I::GetIsolateForSandbox(ctx);
return reinterpret_cast<void*>(
I::ReadExternalPointerField(isolate, embedder_data, value_offset,
internal::kEmbedderDataSlotPayloadTag));
I::ReadExternalPointerField<internal::kEmbedderDataSlotPayloadTag>(
isolate, embedder_data, value_offset));
#else
return SlowGetAlignedPointerFromEmbedderData(index);
#endif
......
......@@ -176,11 +176,20 @@ constexpr bool SandboxedExternalPointersAreEnabled() {
// for example by storing them as offset rather than as raw pointers.
using SandboxedPointer_t = Address;
// ExternalPointers point to objects located outside the sandbox. When sandboxed
// external pointers are enabled, these are stored in an external pointer table
// and referenced from HeapObjects through indices.
// A ExternalPointerHandle represents a (opaque) reference to an external
// pointer that can be stored inside the sandbox. A ExternalPointerHandle has
// meaning only in combination with an (active) Isolate as it references an
// external pointer stored in the currently active Isolate's
// ExternalPointerTable. Internally, an ExternalPointerHandles is simply an
// index into an ExternalPointerTable that is shifted to the left to guarantee
// that it is smaller than the size of the table.
using ExternalPointerHandle = uint32_t;
// ExternalPointers point to objects located outside the sandbox. When
// sandboxed external pointers are enabled, these are stored on heap as
// ExternalPointerHandles, otherwise they are simply raw pointers.
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
using ExternalPointer_t = uint32_t;
using ExternalPointer_t = ExternalPointerHandle;
#else
using ExternalPointer_t = Address;
#endif
......@@ -676,9 +685,9 @@ class Internals {
#endif
}
template <ExternalPointerTag tag>
V8_INLINE static internal::Address ReadExternalPointerField(
v8::Isolate* isolate, internal::Address heap_object_ptr, int offset,
ExternalPointerTag tag) {
v8::Isolate* isolate, internal::Address heap_object_ptr, int offset) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
// See src/sandbox/external-pointer-table-inl.h. Logic duplicated here so it
// can be inlined in embedder code and doesn't require an additional call.
......
......@@ -742,8 +742,9 @@ void* Object::GetAlignedPointerFromInternalField(int index) {
offset += I::kEmbedderDataSlotRawPayloadOffset;
#endif
Isolate* isolate = I::GetIsolateForSandbox(obj);
A value = I::ReadExternalPointerField(
isolate, obj, offset, internal::kEmbedderDataSlotPayloadTag);
A value =
I::ReadExternalPointerField<internal::kEmbedderDataSlotPayloadTag>(
isolate, obj, offset);
return reinterpret_cast<void*>(value);
}
#endif
......
......@@ -786,9 +786,8 @@ String::ExternalStringResource* String::GetExternalStringResource() const {
ExternalStringResource* result;
if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) {
Isolate* isolate = I::GetIsolateForSandbox(obj);
A value =
I::ReadExternalPointerField(isolate, obj, I::kStringResourceOffset,
internal::kExternalStringResourceTag);
A value = I::ReadExternalPointerField<internal::kExternalStringResourceTag>(
isolate, obj, I::kStringResourceOffset);
result = reinterpret_cast<String::ExternalStringResource*>(value);
} else {
result = GetExternalStringResourceSlow();
......@@ -810,9 +809,8 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBase(
if (type == I::kExternalOneByteRepresentationTag ||
type == I::kExternalTwoByteRepresentationTag) {
Isolate* isolate = I::GetIsolateForSandbox(obj);
A value =
I::ReadExternalPointerField(isolate, obj, I::kStringResourceOffset,
internal::kExternalStringResourceTag);
A value = I::ReadExternalPointerField<internal::kExternalStringResourceTag>(
isolate, obj, I::kStringResourceOffset);
resource = reinterpret_cast<ExternalStringResourceBase*>(value);
} else {
resource = GetExternalStringResourceBaseSlow(encoding_out);
......
......@@ -5797,9 +5797,9 @@ String::ExternalStringResource* String::GetExternalStringResourceSlow() const {
if (i::StringShape(str).IsExternalTwoByte()) {
Isolate* isolate = i::Internals::GetIsolateForSandbox(str.ptr());
i::Address value = i::Internals::ReadExternalPointerField(
isolate, str.ptr(), i::Internals::kStringResourceOffset,
i::kExternalStringResourceTag);
i::Address value =
i::Internals::ReadExternalPointerField<i::kExternalStringResourceTag>(
isolate, str.ptr(), i::Internals::kStringResourceOffset);
return reinterpret_cast<String::ExternalStringResource*>(value);
}
return nullptr;
......@@ -5841,9 +5841,9 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBaseSlow(
if (i::StringShape(str).IsExternalOneByte() ||
i::StringShape(str).IsExternalTwoByte()) {
Isolate* isolate = i::Internals::GetIsolateForSandbox(string);
i::Address value = i::Internals::ReadExternalPointerField(
isolate, string, i::Internals::kStringResourceOffset,
i::kExternalStringResourceTag);
i::Address value =
i::Internals::ReadExternalPointerField<i::kExternalStringResourceTag>(
isolate, string, i::Internals::kStringResourceOffset);
resource = reinterpret_cast<ExternalStringResourceBase*>(value);
}
return resource;
......
......@@ -406,13 +406,13 @@ Reduction MemoryLowering::ReduceLoadElement(Node* node) {
return Changed(node);
}
Node* MemoryLowering::DecodeExternalPointer(
Node* node, ExternalPointerTag external_pointer_tag) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
Node* MemoryLowering::ReduceLoadExternalPointerField(Node* node,
ExternalPointerTag tag) {
DCHECK(V8_SANDBOXED_EXTERNAL_POINTERS_BOOL);
DCHECK(node->opcode() == IrOpcode::kLoad);
DCHECK_EQ(kExternalPointerSize, kUInt32Size);
DCHECK_NE(kExternalPointerNullTag, external_pointer_tag);
DCHECK_NE(kExternalPointerNullTag, tag);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
__ InitializeEffectControl(effect, control);
......@@ -438,7 +438,7 @@ Node* MemoryLowering::DecodeExternalPointer(
// would allow access to external objects from different Isolates. It also
// would break if the code is serialized/deserialized at some point.
Node* table_address =
IsExternalPointerTagShareable(external_pointer_tag)
IsExternalPointerTagShareable(tag)
? __
Load(MachineType::Pointer(),
__ ExternalConstant(
......@@ -450,15 +450,12 @@ Node* MemoryLowering::DecodeExternalPointer(
ExternalReference::external_pointer_table_address(isolate()));
Node* table = __ Load(MachineType::Pointer(), table_address,
Internals::kExternalPointerTableBufferOffset);
Node* decoded_ptr =
Node* pointer =
__ Load(MachineType::Pointer(), table, __ ChangeUint32ToUint64(offset));
Node* tag = __ IntPtrConstant(~external_pointer_tag);
decoded_ptr = __ WordAnd(decoded_ptr, tag);
return decoded_ptr;
#else
return node;
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
pointer = __ WordAnd(pointer, __ IntPtrConstant(~tag));
return pointer;
}
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
Reduction MemoryLowering::ReduceLoadMap(Node* node) {
#ifdef V8_MAP_PACKING
......@@ -499,7 +496,7 @@ Reduction MemoryLowering::ReduceLoadField(Node* node) {
if (access.type.Is(Type::ExternalPointer())) {
ExternalPointerTag tag = access.external_pointer_tag;
DCHECK_NE(kExternalPointerNullTag, tag);
node = DecodeExternalPointer(node, tag);
node = ReduceLoadExternalPointerField(node, tag);
return Replace(node);
}
#endif
......
......@@ -108,8 +108,8 @@ class MemoryLowering final : public Reducer {
Node* value,
AllocationState const* state,
WriteBarrierKind);
Node* DecodeExternalPointer(Node* encoded_pointer, ExternalPointerTag tag);
Reduction ReduceLoadMap(Node* encoded_pointer);
Node* ReduceLoadExternalPointerField(Node* node, ExternalPointerTag tag);
Reduction ReduceLoadMap(Node* node);
Node* ComputeIndex(ElementAccess const& access, Node* node);
void EnsureAllocateOperator();
Node* GetWasmInstanceNode();
......
......@@ -5759,22 +5759,19 @@ void Isolate::DetachFromSharedIsolate() {
}
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
ExternalPointer_t Isolate::EncodeWaiterQueueNodeAsExternalPointer(
Address node) {
ExternalPointerHandle
Isolate::InsertWaiterQueueNodeIntoSharedExternalPointerTable(Address node) {
DCHECK_NE(kNullAddress, node);
uint32_t index;
ExternalPointer_t ext;
ExternalPointerHandle handle;
if (waiter_queue_node_external_pointer_.IsJust()) {
ext = waiter_queue_node_external_pointer_.FromJust();
index = ext >> kExternalPointerIndexShift;
handle = waiter_queue_node_external_pointer_.FromJust();
} else {
index = shared_external_pointer_table().Allocate();
ext = index << kExternalPointerIndexShift;
waiter_queue_node_external_pointer_ = Just(ext);
handle = shared_external_pointer_table().Allocate();
waiter_queue_node_external_pointer_ = Just(handle);
}
DCHECK_NE(0, index);
shared_external_pointer_table().Set(index, node, kWaiterQueueNodeTag);
return ext;
DCHECK_NE(0, handle);
shared_external_pointer_table().Set(handle, node, kWaiterQueueNodeTag);
return handle;
}
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
......
......@@ -1977,11 +1977,12 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
&isolate_data_.shared_external_pointer_table_);
}
Maybe<ExternalPointer_t> GetWaiterQueueNodeExternalPointer() const {
Maybe<ExternalPointerHandle> GetWaiterQueueNodeExternalPointer() const {
return waiter_queue_node_external_pointer_;
}
ExternalPointer_t EncodeWaiterQueueNodeAsExternalPointer(Address node);
ExternalPointerHandle InsertWaiterQueueNodeIntoSharedExternalPointerTable(
Address node);
#endif
struct PromiseHookFields {
......@@ -2447,10 +2448,10 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
Isolate* shared_isolate_ = nullptr;
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
// A pointer to Isolate's main thread's WaiterQueueNode. It is used to wait
// for JS-exposed mutex or condition variable.
Maybe<ExternalPointer_t> waiter_queue_node_external_pointer_ =
Nothing<ExternalPointer_t>();
// The external pointer handle to the Isolate's main thread's WaiterQueueNode.
// It is used to wait for JS-exposed mutex or condition variable.
Maybe<ExternalPointerHandle> waiter_queue_node_external_pointer_ =
Nothing<ExternalPointerHandle>();
#endif
#if DEBUG
......
......@@ -145,11 +145,11 @@ template <typename ConcreteVisitor, typename MarkingState>
void MarkingVisitorBase<ConcreteVisitor, MarkingState>::VisitExternalPointer(
HeapObject host, ExternalPointerSlot slot, ExternalPointerTag tag) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
uint32_t index = slot.load_raw() >> kExternalPointerIndexShift;
ExternalPointerHandle handle = slot.load_handle();
if (IsExternalPointerTagShareable(tag)) {
shared_external_pointer_table_->Mark(index);
shared_external_pointer_table_->Mark(handle);
} else {
external_pointer_table_->Mark(index);
external_pointer_table_->Mark(handle);
}
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
}
......
......@@ -40,9 +40,9 @@ bool AccessorInfo::has_getter() { return getter() != kNullAddress; }
bool AccessorInfo::has_setter() { return setter() != kNullAddress; }
void AccessorInfo::AllocateExternalPointerEntries(Isolate* isolate) {
InitExternalPointerField(kSetterOffset, isolate, kAccessorInfoSetterTag);
InitExternalPointerField(kGetterOffset, isolate, kAccessorInfoGetterTag);
InitExternalPointerField(kJsGetterOffset, isolate, kAccessorInfoJsGetterTag);
InitExternalPointerField<kAccessorInfoSetterTag>(kSetterOffset, isolate);
InitExternalPointerField<kAccessorInfoGetterTag>(kGetterOffset, isolate);
InitExternalPointerField<kAccessorInfoJsGetterTag>(kJsGetterOffset, isolate);
}
BIT_FIELD_ACCESSORS(AccessorInfo, flags, all_can_read,
......@@ -118,10 +118,10 @@ bool CallHandlerInfo::NextCallHasNoSideEffect() {
}
void CallHandlerInfo::AllocateExternalPointerEntries(Isolate* isolate) {
InitExternalPointerField(kCallbackOffset, isolate,
kCallHandlerInfoCallbackTag);
InitExternalPointerField(kJsCallbackOffset, isolate,
kCallHandlerInfoJsCallbackTag);
InitExternalPointerField<kCallHandlerInfoCallbackTag>(kCallbackOffset,
isolate);
InitExternalPointerField<kCallHandlerInfoJsCallbackTag>(kJsCallbackOffset,
isolate);
}
EXTERNAL_POINTER_ACCESSORS(CallHandlerInfo, callback, Address, kCallbackOffset,
......
......@@ -1067,7 +1067,7 @@ void CodeDataContainer::set_code_cage_base(Address code_cage_base,
void CodeDataContainer::AllocateExternalPointerEntries(Isolate* isolate) {
CHECK(V8_EXTERNAL_CODE_SPACE_BOOL);
InitExternalPointerField(kCodeEntryPointOffset, isolate, kCodeEntryPointTag);
InitExternalPointerField<kCodeEntryPointTag>(kCodeEntryPointOffset, isolate);
}
Code CodeDataContainer::code() const {
......@@ -1093,14 +1093,14 @@ Code CodeDataContainer::code(PtrComprCageBase cage_base,
DEF_GETTER(CodeDataContainer, code_entry_point, Address) {
CHECK(V8_EXTERNAL_CODE_SPACE_BOOL);
Isolate* isolate = GetIsolateForSandbox(*this);
return ReadExternalPointerField(kCodeEntryPointOffset, isolate,
kCodeEntryPointTag);
return ReadExternalPointerField<kCodeEntryPointTag>(kCodeEntryPointOffset,
isolate);
}
void CodeDataContainer::set_code_entry_point(Isolate* isolate, Address value) {
CHECK(V8_EXTERNAL_CODE_SPACE_BOOL);
WriteExternalPointerField(kCodeEntryPointOffset, isolate, value,
kCodeEntryPointTag);
WriteExternalPointerField<kCodeEntryPointTag>(kCodeEntryPointOffset, isolate,
value);
}
void CodeDataContainer::SetCodeAndEntryPoint(Isolate* isolate_for_sandbox,
......
......@@ -268,20 +268,21 @@ Map Context::GetInitialJSArrayMap(ElementsKind kind) const {
DEF_GETTER(NativeContext, microtask_queue, MicrotaskQueue*) {
Isolate* isolate = GetIsolateForSandbox(*this);
return reinterpret_cast<MicrotaskQueue*>(ReadExternalPointerField(
kMicrotaskQueueOffset, isolate, kNativeContextMicrotaskQueueTag));
return reinterpret_cast<MicrotaskQueue*>(
ReadExternalPointerField<kNativeContextMicrotaskQueueTag>(
kMicrotaskQueueOffset, isolate));
}
void NativeContext::AllocateExternalPointerEntries(Isolate* isolate) {
InitExternalPointerField(kMicrotaskQueueOffset, isolate,
kNativeContextMicrotaskQueueTag);
InitExternalPointerField<kNativeContextMicrotaskQueueTag>(
kMicrotaskQueueOffset, isolate);
}
void NativeContext::set_microtask_queue(Isolate* isolate,
MicrotaskQueue* microtask_queue) {
WriteExternalPointerField(kMicrotaskQueueOffset, isolate,
reinterpret_cast<Address>(microtask_queue),
kNativeContextMicrotaskQueueTag);
WriteExternalPointerField<kNativeContextMicrotaskQueueTag>(
kMicrotaskQueueOffset, isolate,
reinterpret_cast<Address>(microtask_queue));
}
void NativeContext::synchronized_set_script_context_table(
......
......@@ -91,8 +91,8 @@ bool EmbedderDataSlot::ToAlignedPointer(Isolate* isolate,
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
// The raw part must always contain a valid external pointer table index.
*out_pointer = reinterpret_cast<void*>(
ReadExternalPointerField(address() + kExternalPointerOffset, isolate,
kEmbedderDataSlotPayloadTag));
ReadExternalPointerField<kEmbedderDataSlotPayloadTag>(
address() + kExternalPointerOffset, isolate));
return true;
#else
Address raw_value;
......@@ -116,8 +116,8 @@ bool EmbedderDataSlot::store_aligned_pointer(Isolate* isolate, void* ptr) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
DCHECK_EQ(0, value & kExternalPointerTagMask);
// This also mark the entry as alive until the next GC.
InitExternalPointerField(address() + kExternalPointerOffset, isolate, value,
kEmbedderDataSlotPayloadTag);
InitExternalPointerField<kEmbedderDataSlotPayloadTag>(
address() + kExternalPointerOffset, isolate, value);
ObjectSlot(address() + kTaggedPayloadOffset).Relaxed_Store(Smi::zero());
return true;
#else
......
......@@ -29,18 +29,18 @@ bool Foreign::IsNormalized(Object value) {
DEF_GETTER(Foreign, foreign_address, Address) {
Isolate* isolate = GetIsolateForSandbox(*this);
return ReadExternalPointerField(kForeignAddressOffset, isolate,
kForeignForeignAddressTag);
return ReadExternalPointerField<kForeignForeignAddressTag>(
kForeignAddressOffset, isolate);
}
void Foreign::AllocateExternalPointerEntries(Isolate* isolate) {
InitExternalPointerField(kForeignAddressOffset, isolate,
kForeignForeignAddressTag);
InitExternalPointerField<kForeignForeignAddressTag>(kForeignAddressOffset,
isolate);
}
void Foreign::set_foreign_address(Isolate* isolate, Address value) {
WriteExternalPointerField(kForeignAddressOffset, isolate, value,
kForeignForeignAddressTag);
WriteExternalPointerField<kForeignForeignAddressTag>(kForeignAddressOffset,
isolate, value);
}
} // namespace internal
......
......@@ -31,7 +31,7 @@ class V8_NODISCARD WaiterQueueNode final {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
if (head == nullptr) return 0;
auto state = static_cast<typename T::StateT>(
requester->EncodeWaiterQueueNodeAsExternalPointer(
requester->InsertWaiterQueueNodeIntoSharedExternalPointerTable(
reinterpret_cast<Address>(head)));
#else
auto state = base::bit_cast<typename T::StateT>(head);
......@@ -50,10 +50,14 @@ class V8_NODISCARD WaiterQueueNode final {
ExternalPointer_t ptr =
static_cast<ExternalPointer_t>(state & T::kWaiterQueueHeadMask);
if (ptr == 0) return nullptr;
ExternalPointerHandle handle =
static_cast<ExternalPointerHandle>(state & T::kWaiterQueueHeadMask);
if (handle == 0) return nullptr;
// The external pointer is cleared after decoding to prevent reuse by
// multiple mutexes in case of heap corruption.
return reinterpret_cast<WaiterQueueNode*>(
DecodeAndClearExternalPointer(requester, ptr, kWaiterQueueNodeTag));
requester->shared_external_pointer_table().Exchange(
handle, kNullAddress, kWaiterQueueNodeTag));
#else
return base::bit_cast<WaiterQueueNode*>(state & T::kWaiterQueueHeadMask);
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
......
......@@ -573,17 +573,16 @@ TQ_OBJECT_CONSTRUCTORS_IMPL(JSExternalObject)
DEF_GETTER(JSExternalObject, value, void*) {
Isolate* isolate = GetIsolateForSandbox(*this);
return reinterpret_cast<void*>(
ReadExternalPointerField(kValueOffset, isolate, kExternalObjectValueTag));
ReadExternalPointerField<kExternalObjectValueTag>(kValueOffset, isolate));
}
void JSExternalObject::AllocateExternalPointerEntries(Isolate* isolate) {
InitExternalPointerField(kValueOffset, isolate, kExternalObjectValueTag);
InitExternalPointerField<kExternalObjectValueTag>(kValueOffset, isolate);
}
void JSExternalObject::set_value(Isolate* isolate, void* value) {
WriteExternalPointerField(kValueOffset, isolate,
reinterpret_cast<Address>(value),
kExternalObjectValueTag);
WriteExternalPointerField<kExternalObjectValueTag>(
kValueOffset, isolate, reinterpret_cast<Address>(value));
}
DEF_GETTER(JSGlobalObject, native_context_unchecked, Object) {
......
......@@ -413,7 +413,7 @@
/* reinterpret casts to the same type. */ \
struct C2440 {}; \
Address result = \
Object::ReadExternalPointerField(offset, isolate_for_sandbox, tag); \
Object::ReadExternalPointerField<tag>(offset, isolate_for_sandbox); \
return reinterpret_cast<type>(reinterpret_cast<C2440*>(result)); \
} \
void holder::set_##name(i::Isolate* isolate, type value) { \
......@@ -422,7 +422,7 @@
struct C2440 {}; \
Address the_value = \
reinterpret_cast<Address>(reinterpret_cast<C2440*>(value)); \
Object::WriteExternalPointerField(offset, isolate, the_value, tag); \
Object::WriteExternalPointerField<tag>(offset, isolate, the_value); \
}
#define BIT_FIELD_ACCESSORS2(holder, get_field, set_field, name, BitField) \
......
......@@ -668,24 +668,27 @@ void Object::WriteSandboxedPointerField(size_t offset, Isolate* isolate,
PtrComprCageBase(isolate), value);
}
void Object::InitExternalPointerField(size_t offset, Isolate* isolate,
ExternalPointerTag tag) {
i::InitExternalPointerField(field_address(offset), isolate, tag);
template <ExternalPointerTag tag>
void Object::InitExternalPointerField(size_t offset, Isolate* isolate) {
i::InitExternalPointerField<tag>(field_address(offset), isolate);
}
template <ExternalPointerTag tag>
void Object::InitExternalPointerField(size_t offset, Isolate* isolate,
Address value, ExternalPointerTag tag) {
i::InitExternalPointerField(field_address(offset), isolate, value, tag);
Address value) {
i::InitExternalPointerField<tag>(field_address(offset), isolate, value);
}
Address Object::ReadExternalPointerField(size_t offset, Isolate* isolate,
ExternalPointerTag tag) const {
return i::ReadExternalPointerField(field_address(offset), isolate, tag);
template <ExternalPointerTag tag>
Address Object::ReadExternalPointerField(size_t offset,
Isolate* isolate) const {
return i::ReadExternalPointerField<tag>(field_address(offset), isolate);
}
template <ExternalPointerTag tag>
void Object::WriteExternalPointerField(size_t offset, Isolate* isolate,
Address value, ExternalPointerTag tag) {
i::WriteExternalPointerField(field_address(offset), isolate, value, tag);
Address value) {
i::WriteExternalPointerField<tag>(field_address(offset), isolate, value);
}
ObjectSlot HeapObject::RawField(int byte_offset) const {
......
......@@ -731,14 +731,17 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
//
// ExternalPointer_t field accessors.
//
template <ExternalPointerTag tag>
inline void InitExternalPointerField(size_t offset, Isolate* isolate);
template <ExternalPointerTag tag>
inline void InitExternalPointerField(size_t offset, Isolate* isolate,
ExternalPointerTag tag);
inline void InitExternalPointerField(size_t offset, Isolate* isolate,
Address value, ExternalPointerTag tag);
inline Address ReadExternalPointerField(size_t offset, Isolate* isolate,
ExternalPointerTag tag) const;
Address value);
template <ExternalPointerTag tag>
inline Address ReadExternalPointerField(size_t offset,
Isolate* isolate) const;
template <ExternalPointerTag tag>
inline void WriteExternalPointerField(size_t offset, Isolate* isolate,
Address value, ExternalPointerTag tag);
Address value);
// If the receiver is the JSGlobalObject, the store was contextual. In case
// the property did not exist yet on the global object itself, we have to
......
......@@ -154,25 +154,75 @@ void FullHeapObjectSlot::StoreHeapObject(HeapObject value) const {
*location() = value.ptr();
}
ExternalPointer_t ExternalPointerSlot::load_raw() const {
return ReadRawExternalPointerField(address());
void ExternalPointerSlot::init(Isolate* isolate, Address value,
ExternalPointerTag tag) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
ExternalPointerTable& table = GetExternalPointerTableForTag(isolate, tag);
ExternalPointerHandle handle = table.Allocate();
store_handle(handle);
#endif
store(isolate, value, tag);
}
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
ExternalPointerHandle ExternalPointerSlot::load_handle() const {
return base::Memory<ExternalPointerHandle>(address());
}
void ExternalPointerSlot::store_raw(ExternalPointer_t value) const {
WriteRawExternalPointerField(address(), value);
void ExternalPointerSlot::store_handle(ExternalPointerHandle handle) const {
base::Memory<ExternalPointerHandle>(address()) = handle;
}
#endif
Address ExternalPointerSlot::load(const Isolate* isolate,
ExternalPointerTag tag) {
ExternalPointer_t encoded_value = load_raw();
return DecodeExternalPointer(isolate, encoded_value, tag);
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
const ExternalPointerTable& table =
GetExternalPointerTableForTag(isolate, tag);
return table.Get(load_handle(), tag);
#else
// Pointer compression causes types larger than kTaggedSize to be unaligned.
constexpr bool may_be_unaligned = kExternalPointerSize > kTaggedSize;
if (may_be_unaligned) {
return base::ReadUnalignedValue<ExternalPointer_t>(address());
} else {
return base::Memory<ExternalPointer_t>(address());
}
#endif
}
void ExternalPointerSlot::store(Isolate* isolate, Address value,
ExternalPointerTag tag) {
WriteExternalPointerField(address(), isolate, value, tag);
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
ExternalPointerTable& table = GetExternalPointerTableForTag(isolate, tag);
table.Set(load_handle(), value, tag);
#else
// Pointer compression causes types larger than kTaggedSize to be unaligned.
constexpr bool may_be_unaligned = kExternalPointerSize > kTaggedSize;
if (may_be_unaligned) {
base::WriteUnalignedValue<ExternalPointer_t>(address(), value);
} else {
base::Memory<ExternalPointer_t>(address()) = value;
}
#endif
}
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
const ExternalPointerTable& ExternalPointerSlot::GetExternalPointerTableForTag(
const Isolate* isolate, ExternalPointerTag tag) {
return IsExternalPointerTagShareable(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
}
ExternalPointerTable& ExternalPointerSlot::GetExternalPointerTableForTag(
Isolate* isolate, ExternalPointerTag tag) {
return IsExternalPointerTagShareable(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
}
#endif
//
// Utils.
//
......
......@@ -7,6 +7,7 @@
#include "src/base/memory.h"
#include "src/common/globals.h"
#include "src/sandbox/external-pointer-table.h"
namespace v8 {
namespace internal {
......@@ -291,12 +292,26 @@ class ExternalPointerSlot
ExternalPointerSlot() : SlotBase(kNullAddress) {}
explicit ExternalPointerSlot(Address ptr) : SlotBase(ptr) {}
inline ExternalPointer_t load_raw() const;
inline void store_raw(ExternalPointer_t value) const;
inline void init(Isolate* isolate, Address value, ExternalPointerTag tag);
inline Address load(const Isolate* isolate, ExternalPointerTag tag);
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
// When the sandbox is enabled, these slots store a handle to an entry in an
// ExternalPointerTable. These methods allow access to the underlying handle
// while the load/store methods below resolve the handle to the real pointer.
inline ExternalPointerHandle load_handle() const;
inline void store_handle(ExternalPointerHandle handle) const;
#endif
inline Address load(const Isolate* isolate, ExternalPointerTag tag);
inline void store(Isolate* isolate, Address value, ExternalPointerTag tag);
private:
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
inline const ExternalPointerTable& GetExternalPointerTableForTag(
const Isolate* isolate, ExternalPointerTag tag);
inline ExternalPointerTable& GetExternalPointerTableForTag(
Isolate* isolate, ExternalPointerTag tag);
#endif
};
} // namespace internal
......
......@@ -1087,22 +1087,22 @@ bool ExternalString::is_uncached() const {
}
void ExternalString::AllocateExternalPointerEntries(Isolate* isolate) {
InitExternalPointerField(kResourceOffset, isolate,
kExternalStringResourceTag);
InitExternalPointerField<kExternalStringResourceTag>(kResourceOffset,
isolate);
if (is_uncached()) return;
InitExternalPointerField(kResourceDataOffset, isolate,
kExternalStringResourceDataTag);
InitExternalPointerField<kExternalStringResourceDataTag>(kResourceDataOffset,
isolate);
}
DEF_GETTER(ExternalString, resource_as_address, Address) {
Isolate* isolate = GetIsolateForSandbox(*this);
return ReadExternalPointerField(kResourceOffset, isolate,
kExternalStringResourceTag);
return ReadExternalPointerField<kExternalStringResourceTag>(kResourceOffset,
isolate);
}
void ExternalString::set_address_as_resource(Isolate* isolate, Address value) {
WriteExternalPointerField(kResourceOffset, isolate, value,
kExternalStringResourceTag);
WriteExternalPointerField<kExternalStringResourceTag>(kResourceOffset,
isolate, value);
if (IsExternalOneByteString()) {
ExternalOneByteString::cast(*this).update_data_cache(isolate);
} else {
......@@ -1124,16 +1124,16 @@ void ExternalString::SetResourceRefForSerialization(uint32_t ref) {
}
void ExternalString::DisposeResource(Isolate* isolate) {
Address value = ReadExternalPointerField(kResourceOffset, isolate,
kExternalStringResourceTag);
Address value = ReadExternalPointerField<kExternalStringResourceTag>(
kResourceOffset, isolate);
v8::String::ExternalStringResourceBase* resource =
reinterpret_cast<v8::String::ExternalStringResourceBase*>(value);
// Dispose of the C++ object if it has not already been disposed.
if (resource != nullptr) {
resource->Dispose();
WriteExternalPointerField(kResourceOffset, isolate, kNullAddress,
kExternalStringResourceTag);
WriteExternalPointerField<kExternalStringResourceTag>(
kResourceOffset, isolate, kNullAddress);
}
}
......@@ -1153,10 +1153,9 @@ void ExternalOneByteString::update_data_cache(Isolate* isolate) {
if (resource(isolate)->IsCacheable())
mutable_resource(isolate)->UpdateDataCache();
} else {
WriteExternalPointerField(
WriteExternalPointerField<kExternalStringResourceDataTag>(
kResourceDataOffset, isolate,
reinterpret_cast<Address>(resource(isolate)->data()),
kExternalStringResourceDataTag);
reinterpret_cast<Address>(resource(isolate)->data()));
}
}
......@@ -1171,9 +1170,8 @@ void ExternalOneByteString::SetResource(
void ExternalOneByteString::set_resource(
Isolate* isolate, const ExternalOneByteString::Resource* resource) {
WriteExternalPointerField(kResourceOffset, isolate,
reinterpret_cast<Address>(resource),
kExternalStringResourceTag);
WriteExternalPointerField<kExternalStringResourceTag>(
kResourceOffset, isolate, reinterpret_cast<Address>(resource));
if (resource != nullptr) update_data_cache(isolate);
}
......@@ -1225,10 +1223,9 @@ void ExternalTwoByteString::update_data_cache(Isolate* isolate) {
if (resource(isolate)->IsCacheable())
mutable_resource(isolate)->UpdateDataCache();
} else {
WriteExternalPointerField(
WriteExternalPointerField<kExternalStringResourceDataTag>(
kResourceDataOffset, isolate,
reinterpret_cast<Address>(resource(isolate)->data()),
kExternalStringResourceDataTag);
reinterpret_cast<Address>(resource(isolate)->data()));
}
}
......@@ -1243,9 +1240,8 @@ void ExternalTwoByteString::SetResource(
void ExternalTwoByteString::set_resource(
Isolate* isolate, const ExternalTwoByteString::Resource* resource) {
WriteExternalPointerField(kResourceOffset, isolate,
reinterpret_cast<Address>(resource),
kExternalStringResourceTag);
WriteExternalPointerField<kExternalStringResourceTag>(
kResourceOffset, isolate, reinterpret_cast<Address>(resource));
if (resource != nullptr) update_data_cache(isolate);
}
......
......@@ -13,118 +13,74 @@
namespace v8 {
namespace internal {
V8_INLINE Address DecodeExternalPointer(const Isolate* isolate,
ExternalPointer_t encoded_pointer,
ExternalPointerTag tag) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
static_assert(kExternalPointerSize == kInt32Size);
uint32_t index = encoded_pointer >> kExternalPointerIndexShift;
const ExternalPointerTable& table =
IsExternalPointerTagShareable(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
return table.Get(index, tag);
#else
static_assert(kExternalPointerSize == kSystemPointerSize);
return encoded_pointer;
#endif
template <ExternalPointerTag tag>
const ExternalPointerTable& GetExternalPointerTable(const Isolate* isolate) {
return IsExternalPointerTagShareable(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
}
V8_INLINE Address DecodeAndClearExternalPointer(
Isolate* isolate, ExternalPointer_t encoded_pointer,
ExternalPointerTag tag) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
static_assert(kExternalPointerSize == kInt32Size);
uint32_t index = encoded_pointer >> kExternalPointerIndexShift;
ExternalPointerTable& table = IsExternalPointerTagShareable(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
return table.Exchange(index, kNullAddress, tag);
#else
// There is nothing to clear when external pointers are not sandboxed since
// there is no double indirection.
static_assert(kExternalPointerSize == kSystemPointerSize);
return encoded_pointer;
#endif
template <ExternalPointerTag tag>
ExternalPointerTable& GetExternalPointerTable(Isolate* isolate) {
return IsExternalPointerTagShareable(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
}
#endif
V8_INLINE void InitExternalPointerField(Address field_address, Isolate* isolate,
ExternalPointerTag tag) {
InitExternalPointerField(field_address, isolate, kNullExternalPointer, tag);
template <ExternalPointerTag tag>
V8_INLINE void InitExternalPointerField(Address field_address,
Isolate* isolate) {
InitExternalPointerField<tag>(field_address, isolate, kNullExternalPointer);
}
template <ExternalPointerTag tag>
V8_INLINE void InitExternalPointerField(Address field_address, Isolate* isolate,
Address value, ExternalPointerTag tag) {
Address value) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
ExternalPointerTable& table = IsExternalPointerTagShareable(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
ExternalPointer_t index = table.Allocate();
table.Set(index, value, tag);
index <<= kExternalPointerIndexShift;
base::Memory<ExternalPointer_t>(field_address) = index;
ExternalPointerTable& table = GetExternalPointerTable<tag>(isolate);
ExternalPointerHandle handle = table.Allocate();
table.Set(handle, value, tag);
base::Memory<ExternalPointerHandle>(field_address) = handle;
#else
// Pointer compression causes types larger than kTaggedSize to be unaligned.
constexpr bool v8_pointer_compression_unaligned =
kExternalPointerSize > kTaggedSize;
ExternalPointer_t encoded_value = static_cast<ExternalPointer_t>(value);
if (v8_pointer_compression_unaligned) {
base::WriteUnalignedValue<ExternalPointer_t>(field_address, encoded_value);
} else {
base::Memory<ExternalPointer_t>(field_address) = encoded_value;
}
WriteExternalPointerField<tag>(field_address, isolate, value);
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
}
V8_INLINE ExternalPointer_t ReadRawExternalPointerField(Address field_address) {
template <ExternalPointerTag tag>
V8_INLINE Address ReadExternalPointerField(Address field_address,
const Isolate* isolate) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
ExternalPointerHandle handle =
base::Memory<ExternalPointerHandle>(field_address);
return GetExternalPointerTable<tag>(isolate).Get(handle, tag);
#else
// Pointer compression causes types larger than kTaggedSize to be unaligned.
constexpr bool v8_pointer_compression_unaligned =
kExternalPointerSize > kTaggedSize;
if (v8_pointer_compression_unaligned) {
constexpr bool may_be_unaligned = kExternalPointerSize > kTaggedSize;
if (may_be_unaligned) {
return base::ReadUnalignedValue<ExternalPointer_t>(field_address);
} else {
return base::Memory<ExternalPointer_t>(field_address);
}
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
}
V8_INLINE void WriteRawExternalPointerField(Address field_address,
ExternalPointer_t value) {
// Pointer compression causes types larger than kTaggedSize to be unaligned.
constexpr bool v8_pointer_compression_unaligned =
kExternalPointerSize > kTaggedSize;
if (v8_pointer_compression_unaligned) {
base::WriteUnalignedValue<ExternalPointer_t>(field_address, value);
} else {
base::Memory<ExternalPointer_t>(field_address) = value;
}
}
V8_INLINE Address ReadExternalPointerField(Address field_address,
const Isolate* isolate,
ExternalPointerTag tag) {
ExternalPointer_t encoded_value = ReadRawExternalPointerField(field_address);
return DecodeExternalPointer(isolate, encoded_value, tag);
}
template <ExternalPointerTag tag>
V8_INLINE void WriteExternalPointerField(Address field_address,
Isolate* isolate, Address value,
ExternalPointerTag tag) {
Isolate* isolate, Address value) {
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
ExternalPointer_t index = base::Memory<ExternalPointer_t>(field_address);
index >>= kExternalPointerIndexShift;
ExternalPointerTable& table = IsExternalPointerTagShareable(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
table.Set(index, value, tag);
ExternalPointerHandle handle =
base::Memory<ExternalPointerHandle>(field_address);
GetExternalPointerTable<tag>(isolate).Set(handle, value, tag);
#else
// Pointer compression causes types larger than kTaggedSize to be unaligned.
constexpr bool v8_pointer_compression_unaligned =
kExternalPointerSize > kTaggedSize;
ExternalPointer_t encoded_value = static_cast<ExternalPointer_t>(value);
if (v8_pointer_compression_unaligned) {
base::WriteUnalignedValue<ExternalPointer_t>(field_address, encoded_value);
constexpr bool may_be_unaligned = kExternalPointerSize > kTaggedSize;
if (may_be_unaligned) {
base::WriteUnalignedValue<ExternalPointer_t>(field_address, value);
} else {
base::Memory<ExternalPointer_t>(field_address) = encoded_value;
base::Memory<ExternalPointer_t>(field_address) = value;
}
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
}
......
......@@ -59,8 +59,9 @@ void ExternalPointerTable::TearDown() {
mutex_ = nullptr;
}
Address ExternalPointerTable::Get(uint32_t index,
Address ExternalPointerTable::Get(ExternalPointerHandle handle,
ExternalPointerTag tag) const {
uint32_t index = handle >> kExternalPointerIndexShift;
DCHECK_LT(index, capacity_);
Address entry = load_atomic(index);
......@@ -69,29 +70,33 @@ Address ExternalPointerTable::Get(uint32_t index,
return entry & ~tag;
}
void ExternalPointerTable::Set(uint32_t index, Address value,
void ExternalPointerTable::Set(ExternalPointerHandle handle, Address value,
ExternalPointerTag tag) {
DCHECK_LT(index, capacity_);
DCHECK_NE(kNullExternalPointer, index);
DCHECK_NE(kNullExternalPointer, handle);
DCHECK_EQ(0, value & kExternalPointerTagMask);
DCHECK(is_marked(tag));
uint32_t index = handle >> kExternalPointerIndexShift;
DCHECK_LT(index, capacity_);
store_atomic(index, value | tag);
}
Address ExternalPointerTable::Exchange(uint32_t index, Address value,
ExternalPointerTag tag) {
DCHECK_LT(index, capacity_);
DCHECK_NE(kNullExternalPointer, index);
Address ExternalPointerTable::Exchange(ExternalPointerHandle handle,
Address value, ExternalPointerTag tag) {
DCHECK_NE(kNullExternalPointer, handle);
DCHECK_EQ(0, value & kExternalPointerTagMask);
DCHECK(is_marked(tag));
uint32_t index = handle >> kExternalPointerIndexShift;
DCHECK_LT(index, capacity_);
Address entry = exchange_atomic(index, value | tag);
DCHECK(!is_free(entry));
return entry & ~tag;
}
uint32_t ExternalPointerTable::Allocate() {
ExternalPointerHandle ExternalPointerTable::Allocate() {
DCHECK(is_initialized());
base::Atomic32* freelist_head_ptr =
......@@ -132,13 +137,15 @@ uint32_t ExternalPointerTable::Allocate() {
success = old_val == freelist_head;
}
return index;
return index << kExternalPointerIndexShift;
}
void ExternalPointerTable::Mark(uint32_t index) {
DCHECK_LT(index, capacity_);
void ExternalPointerTable::Mark(ExternalPointerHandle handle) {
static_assert(sizeof(base::Atomic64) == sizeof(Address));
uint32_t index = handle >> kExternalPointerIndexShift;
DCHECK_LT(index, capacity_);
base::Atomic64 old_val = load_atomic(index);
DCHECK(!is_free(old_val));
base::Atomic64 new_val = set_mark_bit(old_val);
......
......@@ -18,7 +18,8 @@ namespace internal {
static_assert(sizeof(ExternalPointerTable) == ExternalPointerTable::kSize);
// static
uint32_t ExternalPointerTable::AllocateEntry(ExternalPointerTable* table) {
ExternalPointerHandle ExternalPointerTable::AllocateEntry(
ExternalPointerTable* table) {
return table->Allocate();
}
......
......@@ -73,22 +73,24 @@ class V8_EXPORT_PRIVATE ExternalPointerTable {
// Resets this external pointer table and deletes all associated memory.
inline void TearDown();
// Retrieves the entry at the given index.
// Retrieves the entry referenced by the given handle.
//
// This method is atomic and can be called from background threads.
inline Address Get(uint32_t index, ExternalPointerTag tag) const;
inline Address Get(ExternalPointerHandle handle,
ExternalPointerTag tag) const;
// Sets the entry at the given index to the given value.
// Sets the entry referenced by the given handle.
//
// This method is atomic and can be called from background threads.
inline void Set(uint32_t index, Address value, ExternalPointerTag tag);
inline void Set(ExternalPointerHandle handle, Address value,
ExternalPointerTag tag);
// Exchanges the entry at the given index with the given value, returning the
// previous value. The same tag is applied both to decode the previous value
// and encode the given value.
// Exchanges the entry referenced by the given handle with the given value,
// returning the previous value. The same tag is applied both to decode the
// previous value and encode the given value.
//
// This method is atomic and can call be called from background threads.
inline Address Exchange(uint32_t index, Address value,
inline Address Exchange(ExternalPointerHandle handle, Address value,
ExternalPointerTag tag);
// Allocates a new entry in the external pointer table. The caller must
......@@ -97,15 +99,15 @@ class V8_EXPORT_PRIVATE ExternalPointerTable {
// TODO(saelo) this can fail, in which case we should probably do GC + retry.
//
// This method is atomic and can be called from background threads.
inline uint32_t Allocate();
inline ExternalPointerHandle Allocate();
// Runtime function called from CSA. Internally just calls Allocate().
static uint32_t AllocateEntry(ExternalPointerTable* table);
static ExternalPointerHandle AllocateEntry(ExternalPointerTable* table);
// Marks the specified entry as alive.
//
// This method is atomic and can be called from background threads.
inline void Mark(uint32_t index);
inline void Mark(ExternalPointerHandle index);
// Frees unmarked entries.
//
......
......@@ -10,50 +10,32 @@
namespace v8 {
namespace internal {
// Convert external pointer from on-V8-heap representation to an actual external
// pointer value.
V8_INLINE Address DecodeExternalPointer(const Isolate* isolate,
ExternalPointer_t encoded_pointer,
ExternalPointerTag tag);
// Atomically convert an external pointer from on-V8-heap representation to an
// actual external pointer value and clear its entry in the external pointer
// table
V8_INLINE Address DecodeAndClearExternalPointer(
Isolate* isolate, ExternalPointer_t encoded_pointer,
ExternalPointerTag tag);
constexpr ExternalPointer_t kNullExternalPointer = 0;
// Creates zero-initialized entry in external pointer table and writes the entry
// id to the field. When sandbox is not enabled, it's a no-op.
V8_INLINE void InitExternalPointerField(Address field_address, Isolate* isolate,
ExternalPointerTag tag);
template <ExternalPointerTag tag>
V8_INLINE void InitExternalPointerField(Address field_address,
Isolate* isolate);
// Creates and initializes entry in external pointer table and writes the entry
// id to the field.
// Basically, it's InitExternalPointerField() followed by
// WriteExternalPointerField().
template <ExternalPointerTag tag>
V8_INLINE void InitExternalPointerField(Address field_address, Isolate* isolate,
Address value, ExternalPointerTag tag);
// Reads and returns a raw external pointer value.
V8_INLINE ExternalPointer_t ReadRawExternalPointerField(Address field_address);
// Writes a raw external pointer value at given address.
V8_INLINE void WriteRawExternalPointerField(Address field_address,
ExternalPointer_t value);
Address value);
// Reads external pointer for the field, and decodes it if the sandbox is
// enabled.
template <ExternalPointerTag tag>
V8_INLINE Address ReadExternalPointerField(Address field_address,
const Isolate* isolate,
ExternalPointerTag tag);
const Isolate* isolate);
// Encodes value if the sandbox is enabled and writes it into the field.
template <ExternalPointerTag tag>
V8_INLINE void WriteExternalPointerField(Address field_address,
Isolate* isolate, Address value,
ExternalPointerTag tag);
Isolate* isolate, Address value);
} // namespace internal
} // namespace v8
......
......@@ -62,6 +62,9 @@ class SlotAccessorForHeapObject {
}
MaybeObjectSlot slot() const { return object_->RawMaybeWeakField(offset_); }
ExternalPointerSlot external_pointer_slot() const {
return object_->RawExternalPointerField(offset_);
}
Handle<HeapObject> object() const { return object_; }
int offset() const { return offset_; }
......@@ -96,6 +99,7 @@ class SlotAccessorForRootSlots {
explicit SlotAccessorForRootSlots(FullMaybeObjectSlot slot) : slot_(slot) {}
FullMaybeObjectSlot slot() const { return slot_; }
ExternalPointerSlot external_pointer_slot() const { UNREACHABLE(); }
Handle<HeapObject> object() const { UNREACHABLE(); }
int offset() const { UNREACHABLE(); }
......@@ -128,6 +132,7 @@ class SlotAccessorForHandle {
: handle_(handle), isolate_(isolate) {}
MaybeObjectSlot slot() const { UNREACHABLE(); }
ExternalPointerSlot external_pointer_slot() const { UNREACHABLE(); }
Handle<HeapObject> object() const { UNREACHABLE(); }
int offset() const { UNREACHABLE(); }
......@@ -162,13 +167,14 @@ int Deserializer<IsolateT>::WriteAddress(TSlot dest, Address value) {
}
template <typename IsolateT>
template <typename TSlot>
int Deserializer<IsolateT>::WriteExternalPointer(TSlot dest, Address value,
int Deserializer<IsolateT>::WriteExternalPointer(ExternalPointerSlot dest,
Address value,
ExternalPointerTag tag) {
DCHECK(!next_reference_is_weak_);
DCHECK(IsAligned(kExternalPointerSize, TSlot::kSlotDataSize));
InitExternalPointerField(dest.address(), main_thread_isolate(), value, tag);
return (kExternalPointerSize / TSlot::kSlotDataSize);
DCHECK(IsAligned(kExternalPointerSize, ExternalPointerSlot::kSlotDataSize));
dest.init(main_thread_isolate(), value, tag);
return (kExternalPointerSize / ExternalPointerSlot::kSlotDataSize);
}
namespace {
......@@ -977,7 +983,8 @@ int Deserializer<IsolateT>::ReadSingleBytecodeData(byte data,
if (V8_SANDBOXED_EXTERNAL_POINTERS_BOOL &&
data == kSandboxedExternalReference) {
ExternalPointerTag tag = ReadExternalPointerTag();
return WriteExternalPointer(slot_accessor.slot(), address, tag);
return WriteExternalPointer(slot_accessor.external_pointer_slot(),
address, tag);
} else {
DCHECK(!V8_SANDBOXED_EXTERNAL_POINTERS_BOOL);
return WriteAddress(slot_accessor.slot(), address);
......@@ -1154,7 +1161,8 @@ int Deserializer<IsolateT>::ReadSingleBytecodeData(byte data,
if (V8_SANDBOXED_EXTERNAL_POINTERS_BOOL &&
data == kSandboxedApiReference) {
ExternalPointerTag tag = ReadExternalPointerTag();
return WriteExternalPointer(slot_accessor.slot(), address, tag);
return WriteExternalPointer(slot_accessor.external_pointer_slot(),
address, tag);
} else {
DCHECK(!V8_SANDBOXED_EXTERNAL_POINTERS_BOOL);
return WriteAddress(slot_accessor.slot(), address);
......
......@@ -154,8 +154,7 @@ class Deserializer : public SerializerDeserializer {
template <typename TSlot>
inline int WriteAddress(TSlot dest, Address value);
template <typename TSlot>
inline int WriteExternalPointer(TSlot dest, Address value,
inline int WriteExternalPointer(ExternalPointerSlot dest, Address value,
ExternalPointerTag tag);
// Fills in a heap object's data from start to end (exclusive). Start and end
......
......@@ -349,11 +349,14 @@ class ReadStringVisitor : public TqObjectVisitor {
if (IsExternalStringCached(object)) {
ExternalPointer_t resource_data =
GetOrFinish(object->GetResourceDataValue(accessor_));
#ifdef V8_COMPRESS_POINTERS
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
Isolate* isolate = GetIsolateForSandbox(
HeapObject::unchecked_cast(Object(heap_addresses_.any_heap_pointer)));
uintptr_t data_address = static_cast<uintptr_t>(DecodeExternalPointer(
isolate, resource_data, kExternalStringResourceDataTag));
ExternalPointerHandle handle =
static_cast<ExternalPointerHandle>(resource_data);
uintptr_t data_address =
static_cast<uintptr_t>(isolate->shared_external_pointer_table().Get(
handle, kExternalStringResourceDataTag));
#else
uintptr_t data_address = static_cast<uintptr_t>(resource_data);
#endif // V8_COMPRESS_POINTERS
......
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