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