#ifndef V8_SANDBOX_CPPHEAP_POINTER_TABLE_H_
#define V8_SANDBOX_CPPHEAP_POINTER_TABLE_H_
#include "include/v8-sandbox.h"
#include "include/v8config.h"
#include "src/base/atomicops.h"
#include "src/base/bounds.h"
#include "src/base/memory.h"
#include "src/common/globals.h"
#include "src/sandbox/compactible-external-entity-table.h"
#include "src/sandbox/tagged-payload.h"
#include "src/utils/allocation.h"
#ifdef V8_COMPRESS_POINTERS
namespace v8::internal {
class Isolate;
class Counters;
* The entries of an CppHeapPointerTable.
*
* Each entry consists of a single pointer-sized word containing the pointer,
* the marking bit, and a type tag. An entry can either be:
* - A "regular" entry, containing the pointer together with a type tag and
* the marking bit, or
* - A freelist entry, tagged with the kFreeEntryTag and containing the index
* of the next free entry, or
* - An evacuation entry, tagged with the kEvacuationEntryTag and containing
* the address of the CppHeapPointerSlot referencing the entry that will be
* evacuated into this entry.
*/
struct CppHeapPointerTableEntry {
inline void MakePointerEntry(Address value, CppHeapPointerTag tag,
bool mark_as_alive);
inline Address GetPointer(CppHeapPointerTagRange tag_range) const;
inline void SetPointer(Address value, CppHeapPointerTag tag);
inline bool HasPointer(CppHeapPointerTagRange tag_range) const;
inline void MakeZappedEntry();
inline void MakeFreelistEntry(uint32_t next_entry_index);
inline uint32_t GetNextFreelistEntryIndex() const;
inline void MakeEvacuationEntry(Address handle_location);
inline bool HasEvacuationEntry() const;
inline void Evacuate(CppHeapPointerTableEntry& dest);
inline void Mark();
static constexpr bool IsWriteProtected = false;
private:
friend class CppHeapPointerTable;
friend class CppHeapPointerTableEntryPrinter;
struct Payload {
Payload(Address pointer, CppHeapPointerTag tag)
: encoded_word_(Tag(pointer, tag)) {}
Address Untag(CppHeapPointerTagRange tag_range) const {
Address content = encoded_word_;
if (V8_LIKELY(tag_range.CheckTagOf(content))) {
content >>= kCppHeapPointerPayloadShift;
} else {
content = 0;
}
return content;
}
Address Untag(CppHeapPointerTag tag) const {
return Untag(CppHeapPointerTagRange(tag, tag));
}
static Address Tag(Address pointer, CppHeapPointerTag tag) {
return (pointer << kCppHeapPointerPayloadShift) |
(static_cast<uint16_t>(tag) << kCppHeapPointerTagShift);
}
bool IsTaggedWithTagIn(CppHeapPointerTagRange tag_range) const {
return tag_range.CheckTagOf(encoded_word_);
}
bool IsTaggedWith(CppHeapPointerTag tag) const {
return IsTaggedWithTagIn(CppHeapPointerTagRange(tag, tag));
}
void SetMarkBit() { encoded_word_ |= kCppHeapPointerMarkBit; }
void ClearMarkBit() { encoded_word_ &= ~kCppHeapPointerMarkBit; }
bool HasMarkBitSet() const {
return encoded_word_ & kCppHeapPointerMarkBit;
}
uint32_t ExtractFreelistLink() const {
return static_cast<uint32_t>(encoded_word_ >>
kCppHeapPointerPayloadShift);
}
CppHeapPointerTag ExtractTag() const {
return static_cast<CppHeapPointerTag>(encoded_word_ >>
kCppHeapPointerTagShift);
}
bool ContainsFreelistLink() const {
return IsTaggedWith(CppHeapPointerTag::kFreeEntryTag);
}
bool ContainsEvacuationEntry() const {
return IsTaggedWith(CppHeapPointerTag::kEvacuationEntryTag);
}
Address ExtractEvacuationEntryHandleLocation() const {
return Untag(CppHeapPointerTag::kEvacuationEntryTag);
}
bool ContainsPointer() const {
return !ContainsFreelistLink() && !ContainsEvacuationEntry();
}
bool operator==(Payload other) const {
return encoded_word_ == other.encoded_word_;
}
bool operator!=(Payload other) const {
return encoded_word_ != other.encoded_word_;
}
private:
Address encoded_word_;
};
inline Payload GetRawPayload() const {
return payload_.load(std::memory_order_relaxed);
}
inline void SetRawPayload(Payload new_payload) {
return payload_.store(new_payload, std::memory_order_relaxed);
}
std::atomic<Payload> payload_;
};
static_assert(sizeof(CppHeapPointerTableEntry) == 8);
* A table storing pointers to objects in the CppHeap
*
* This table is essentially a specialized version of the ExternalPointerTable
* used for CppHeap objects. It uses a different type tagging scheme which
* supports significantly more types and also supports type hierarchies. See
* the CppHeapPointerTag enum for more details.
*
* Apart from that, this table mostly behaves like the external pointer table
* and so uses a simple garbage collection algorithm to detect and free unused
* entries and also supports table compaction.
*
*/
class V8_EXPORT_PRIVATE CppHeapPointerTable
: public CompactibleExternalEntityTable<
CppHeapPointerTableEntry, kCppHeapPointerTableReservationSize> {
using Base =
CompactibleExternalEntityTable<CppHeapPointerTableEntry,
kCppHeapPointerTableReservationSize>;
static_assert(kMaxCppHeapPointers == kMaxCapacity);
public:
CppHeapPointerTable() = default;
CppHeapPointerTable(const CppHeapPointerTable&) = delete;
CppHeapPointerTable& operator=(const CppHeapPointerTable&) = delete;
using Space = Base::Space;
inline Address Get(CppHeapPointerHandle handle,
CppHeapPointerTagRange tag_range) const;
inline void Set(CppHeapPointerHandle handle, Address value,
CppHeapPointerTag tag);
inline CppHeapPointerHandle AllocateAndInitializeEntry(Space* space,
Address initial_value,
CppHeapPointerTag tag);
inline void Mark(Space* space, CppHeapPointerHandle handle,
Address handle_location);
uint32_t SweepAndCompact(Space* space, Counters* counters);
inline bool Contains(Space* space, CppHeapPointerHandle handle) const;
private:
static inline bool IsValidHandle(CppHeapPointerHandle handle);
static inline uint32_t HandleToIndex(CppHeapPointerHandle handle);
static inline CppHeapPointerHandle IndexToHandle(uint32_t index);
void ResolveEvacuationEntryDuringSweeping(
uint32_t index, CppHeapPointerHandle* handle_location,
uint32_t start_of_evacuation_area);
};
#ifdef OBJECT_PRINT
class CppHeapPointerTableEntryPrinter {
public:
static void PrintHeader(const char* space_name);
static void PrintIfInUse(
CppHeapPointerHandle handle, const CppHeapPointerTableEntry& entry,
std::function<bool(CppHeapPointerTag)> entry_callback);
static void PrintFooter();
};
template <>
class TableEntryPrinter<CppHeapPointerTableEntry>
: public CppHeapPointerTableEntryPrinter {};
#endif
}
#endif
#endif