5#ifndef V8_SANDBOX_EXTERNAL_POINTER_TABLE_INL_H_
6#define V8_SANDBOX_EXTERNAL_POINTER_TABLE_INL_H_
14#ifdef V8_COMPRESS_POINTERS
19void ExternalPointerTableEntry::MakeExternalPointerEntry(
Address value,
27 Payload new_payload(value, tag);
29 new_payload.SetMarkBit();
31 payload_.store(new_payload, std::memory_order_relaxed);
32 MaybeUpdateRawPointerForLSan(value);
35Address ExternalPointerTableEntry::GetExternalPointer(
37 auto payload = payload_.load(std::memory_order_relaxed);
38 DCHECK(payload.ContainsPointer());
39 return payload.Untag(tag_range);
42void ExternalPointerTableEntry::SetExternalPointer(
Address value,
46 DCHECK(payload_.load(std::memory_order_relaxed).ContainsPointer());
48 Payload new_payload(value, tag);
51 new_payload.SetMarkBit();
52 payload_.store(new_payload, std::memory_order_relaxed);
53 MaybeUpdateRawPointerForLSan(value);
56bool ExternalPointerTableEntry::HasExternalPointer(
58 auto payload = payload_.load(std::memory_order_relaxed);
59 if (!payload.ContainsPointer())
return false;
60 return payload.IsTaggedWithTagIn(tag_range);
63Address ExternalPointerTableEntry::ExchangeExternalPointer(
68 Payload new_payload(value, tag);
71 new_payload.SetMarkBit();
73 payload_.exchange(new_payload, std::memory_order_relaxed);
74 DCHECK(old_payload.ContainsPointer());
75 MaybeUpdateRawPointerForLSan(value);
76 return old_payload.Untag(tag);
80 auto payload = payload_.load(std::memory_order_relaxed);
81 DCHECK(payload.ContainsPointer());
82 return payload.ExtractTag();
85Address ExternalPointerTableEntry::ExtractManagedResourceOrNull()
const {
86 auto payload = payload_.load(std::memory_order_relaxed);
89 return payload.Untag(tag);
94void ExternalPointerTableEntry::MakeZappedEntry() {
96 payload_.store(new_payload, std::memory_order_relaxed);
99void ExternalPointerTableEntry::MakeFreelistEntry(uint32_t next_entry_index) {
101 static_assert(kMaxExternalPointers <= std::numeric_limits<uint32_t>::max());
103 payload_.store(new_payload, std::memory_order_relaxed);
106uint32_t ExternalPointerTableEntry::GetNextFreelistEntryIndex()
const {
107 auto payload = payload_.load(std::memory_order_relaxed);
108 return payload.ExtractFreelistLink();
111void ExternalPointerTableEntry::Mark() {
112 auto old_payload = payload_.load(std::memory_order_relaxed);
113 DCHECK(old_payload.ContainsPointer());
115 auto new_payload = old_payload;
116 new_payload.SetMarkBit();
122 bool success = payload_.compare_exchange_strong(old_payload, new_payload,
123 std::memory_order_relaxed);
124 DCHECK(success || old_payload.HasMarkBitSet());
128void ExternalPointerTableEntry::MakeEvacuationEntry(
Address handle_location) {
130 payload_.store(new_payload, std::memory_order_relaxed);
133bool ExternalPointerTableEntry::HasEvacuationEntry()
const {
134 auto payload = payload_.load(std::memory_order_relaxed);
135 return payload.ContainsEvacuationEntry();
138void ExternalPointerTableEntry::Evacuate(ExternalPointerTableEntry& dest,
139 EvacuateMarkMode mode) {
140 auto payload = payload_.load(std::memory_order_relaxed);
142 DCHECK(payload.ContainsPointer());
145 case EvacuateMarkMode::kTransferMark:
147 case EvacuateMarkMode::kLeaveUnmarked:
148 DCHECK(!payload.HasMarkBitSet());
150 case EvacuateMarkMode::kClearMark:
151 DCHECK(payload.HasMarkBitSet());
152 payload.ClearMarkBit();
156 dest.payload_.store(payload, std::memory_order_relaxed);
157#if defined(LEAK_SANITIZER)
158 dest.raw_pointer_for_lsan_ = raw_pointer_for_lsan_;
167 uint32_t index = HandleToIndex(
handle);
168 DCHECK(index == 0 || at(index).HasExternalPointer(tag_range));
169 return at(index).GetExternalPointer(tag_range);
175 uint32_t index = HandleToIndex(
handle);
181 FreeManagedResourceIfPresent(index);
182 TakeOwnershipOfManagedResourceIfNecessary(value,
handle, tag);
183 at(index).SetExternalPointer(value, tag);
190 uint32_t index = HandleToIndex(
handle);
191 return at(index).ExchangeExternalPointer(value, tag);
196 uint32_t index = HandleToIndex(
handle);
197 return at(index).GetExternalPointerTag();
205 uint32_t index = HandleToIndex(
handle);
206 at(index).MakeZappedEntry();
211 DCHECK(space->BelongsTo(
this));
212 uint32_t index = AllocateEntry(space);
213 at(index).MakeExternalPointerEntry(initial_value, tag,
214 space->allocate_black());
216 TakeOwnershipOfManagedResourceIfNecessary(initial_value,
handle, tag);
222 DCHECK(space->BelongsTo(
this));
238 uint32_t index = HandleToIndex(
handle);
239 DCHECK(space->Contains(index));
243 MaybeCreateEvacuationEntry(space, index, handle_location);
250void ExternalPointerTable::Evacuate(Space* from_space, Space* to_space,
253 EvacuateMarkMode mode) {
254 DCHECK(from_space->BelongsTo(
this));
255 DCHECK(to_space->BelongsTo(
this));
271 uint32_t from_index = HandleToIndex(
handle);
272 DCHECK(from_space->Contains(from_index));
273 uint32_t to_index = AllocateEntry(to_space);
275 at(from_index).Evacuate(at(to_index), mode);
278 if (
Address addr = at(to_index).ExtractManagedResourceOrNull()) {
279 ManagedResource* resource =
reinterpret_cast<ManagedResource*
>(addr);
281 resource->ept_entry_ = new_handle;
290 uint32_t index =
handle >> kExternalPointerIndexShift;
291 return handle == index << kExternalPointerIndexShift;
297 uint32_t index =
handle >> kExternalPointerIndexShift;
298#if defined(LEAK_SANITIZER)
318#if defined(LEAK_SANITIZER)
325bool ExternalPointerTable::Contains(Space* space,
327 DCHECK(space->BelongsTo(
this));
328 return space->Contains(HandleToIndex(
handle));
331void ExternalPointerTable::Space::NotifyExternalPointerFieldInvalidated(
342 AddInvalidatedField(field_address);
345void ExternalPointerTable::ManagedResource::ZapExternalPointerTableEntry() {
347 owning_table_->Zap(ept_entry_);
352void ExternalPointerTable::TakeOwnershipOfManagedResourceIfNecessary(
355 ManagedResource* resource =
reinterpret_cast<ManagedResource*
>(
value);
357 resource->owning_table_ =
this;
358 resource->ept_entry_ =
handle;
362void ExternalPointerTable::FreeManagedResourceIfPresent(uint32_t entry_index) {
367 if (
Address addr = at(entry_index).ExtractManagedResourceOrNull()) {
368 ManagedResource* resource =
reinterpret_cast<ManagedResource*
>(addr);
379 resource->ept_entry_ == IndexToHandle(entry_index));
static T Acquire_Load(T *addr)
static void Relaxed_Store(T *addr, typename std::remove_reference< T >::type new_value)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
TagRange< ExternalPointerTag > ExternalPointerTagRange
constexpr uint64_t kExternalPointerTagAndMarkbitMask
constexpr size_t kMaxExternalPointers
constexpr ExternalPointerHandle kNullExternalPointerHandle
@ kExternalPointerEvacuationEntryTag
@ kExternalPointerFreeEntryTag
@ kExternalPointerZappedEntryTag
V8_EXPORT_PRIVATE FlagValues v8_flags
static V8_INLINE constexpr bool IsManagedExternalPointerType(ExternalPointerTagRange tag_range)
uint32_t ExternalPointerHandle
static constexpr Address kNullAddress
#define DCHECK_LE(v1, v2)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define V8_UNLIKELY(condition)