v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
segmented-table-inl.h
Go to the documentation of this file.
1// Copyright 2024 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_COMMON_SEGMENTED_TABLE_INL_H_
6#define V8_COMMON_SEGMENTED_TABLE_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
14
15namespace v8 {
16namespace internal {
17
18template <typename Entry, size_t size>
19typename SegmentedTable<Entry, size>::Segment
22 uint32_t number = offset / kSegmentSize;
23 return Segment(number);
24}
25
26template <typename Entry, size_t size>
29 uint32_t number = entry_index / kEntriesPerSegment;
30 return Segment(number);
31}
32
33template <typename Entry, size_t size>
34Entry& SegmentedTable<Entry, size>::at(uint32_t index) {
35 return base_[index];
36}
37
38template <typename Entry, size_t size>
39const Entry& SegmentedTable<Entry, size>::at(uint32_t index) const {
40 return base_[index];
41}
42
43template <typename Entry, size_t size>
46 return WriteIterator(base_, index);
47}
48
49template <typename Entry, size_t size>
51 DCHECK(!base_ || reinterpret_cast<Address>(base_) == vas_->base());
52 return vas_ != nullptr;
53}
54
55template <typename Entry, size_t size>
58 return reinterpret_cast<Address>(base_);
59}
60
61template <typename Entry, size_t size>
64 DCHECK_EQ(vas_, nullptr);
65
68#ifdef V8_TARGET_ARCH_64_BIT
69 static_assert(kUseContiguousMemory);
70 DCHECK(IsAligned(kReservationSize, root_space->allocation_granularity()));
71
72 if (root_space->CanAllocateSubspaces()) {
73 auto subspace = root_space->AllocateSubspace(VirtualAddressSpace::kNoHint,
74 kReservationSize, kSegmentSize,
76 vas_ = subspace.release();
77 } else {
78 // This may be required on old Windows versions that don't support
79 // VirtualAlloc2, which is required for subspaces. In that case, just use a
80 // fully-backed emulated subspace.
81 Address reservation_base = root_space->AllocatePages(
84 if (reservation_base) {
86 root_space, reservation_base, kReservationSize, kReservationSize);
87 }
88 }
89 if (!vas_) {
91 nullptr, "SegmentedTable::InitializeTable (subspace allocation)");
92 }
93#else // V8_TARGET_ARCH_64_BIT
94 static_assert(!kUseContiguousMemory);
95 vas_ = root_space;
96#endif
97
98 base_ = reinterpret_cast<Entry*>(vas_->base());
99
100 if constexpr (kUseContiguousMemory && kIsWriteProtected) {
103 }
104}
105
106template <typename Entry, size_t size>
109
110 base_ = nullptr;
111#ifdef V8_TARGET_ARCH_64_BIT
112 delete vas_;
113#endif
114 vas_ = nullptr;
115}
116
117template <typename Entry, size_t size>
120 uint32_t start_offset) {
121 DCHECK_LT(start_offset, kEntriesPerSegment);
122 uint32_t num_entries = kEntriesPerSegment - start_offset;
123
124 uint32_t first = segment.first_entry() + start_offset;
125 uint32_t last = segment.last_entry();
126 {
127 WriteIterator it = iter_at(first);
128 while (it.index() != last) {
129 it->MakeFreelistEntry(it.index() + 1);
130 ++it;
131 }
132 it->MakeFreelistEntry(0);
133 }
135 return FreelistHead(first, num_entries);
136}
137
138template <typename Entry, size_t size>
139std::pair<typename SegmentedTable<Entry, size>::Segment,
142 if (auto res = TryAllocateAndInitializeSegment()) {
143 return *res;
144 }
146 "SegmentedTable::AllocateAndInitializeSegment");
147}
148
149template <typename Entry, size_t size>
150std::optional<std::pair<typename SegmentedTable<Entry, size>::Segment,
153 Address start =
156 if (!start) {
157 return {};
158 }
159 uint32_t offset = static_cast<uint32_t>((start - vas_->base()));
160 Segment segment = Segment::At(offset);
161
162 FreelistHead freelist = InitializeFreeList(segment);
163
164 return {{segment, freelist}};
165}
166
167template <typename Entry, size_t size>
172
173template <typename Entry, size_t size>
175 uint32_t index)
176 : base_(base), index_(index), write_scope_("pointer table write") {}
178} // namespace internal
179} // namespace v8
180
181#endif // V8_COMMON_SEGMENTED_TABLE_INL_H_
virtual bool CanAllocateSubspaces()=0
Address base() const
virtual void FreePages(Address address, size_t size)=0
static constexpr Address kNoHint
virtual V8_WARN_UNUSED_RESULT Address AllocatePages(Address hint, size_t size, size_t alignment, PagePermissions permissions)=0
size_t allocation_granularity() const
virtual std::unique_ptr< VirtualAddressSpace > AllocateSubspace(Address hint, size_t size, size_t alignment, PagePermissions max_page_permissions)=0
static constexpr size_t kSegmentSize
static constexpr size_t kEntriesPerSegment
std::optional< std::pair< Segment, FreelistHead > > TryAllocateAndInitializeSegment()
VirtualAddressSpace * vas_
FreelistHead InitializeFreeList(Segment segment, uint32_t start_offset=0)
static constexpr bool kIsWriteProtected
void FreeTableSegment(Segment segment)
std::pair< Segment, FreelistHead > AllocateAndInitializeSegment()
WriteIterator iter_at(uint32_t index)
static constexpr bool kUseContiguousMemory
static V8_NODISCARD bool WriteProtectMemory(Address addr, size_t size, PageAllocator::Permission page_permissions)
static V8_EXPORT_PRIVATE void FatalProcessOutOfMemory(Isolate *isolate, const char *location, const OOMDetails &details=kNoOOMDetails)
Register const index_
int start
int32_t offset
v8::VirtualAddressSpace * GetPlatformVirtualAddressSpace()
Definition allocation.cc:71
const Address segment_start
#define CHECK(condition)
Definition logging.h:124
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
constexpr bool IsAligned(T value, U alignment)
Definition macros.h:403
static Segment At(uint32_t offset)
static Segment Containing(uint32_t entry_index)