v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
marking.h
Go to the documentation of this file.
1// Copyright 2016 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_HEAP_MARKING_H_
6#define V8_HEAP_MARKING_H_
7
8#include <cstdint>
9
11#include "src/common/globals.h"
14
15namespace v8::internal {
16
17class PageMetadata;
18
19class MarkBit final {
20 public:
21 using CellType = uintptr_t;
22 static_assert(sizeof(CellType) == sizeof(base::AtomicWord));
23
24 V8_ALLOW_UNUSED static inline MarkBit From(Address);
26
27 // These methods are meant to be used from the debugger and therefore
28 // intentionally not inlined such that they are always available.
31
32 // The function returns true if it succeeded to
33 // transition the bit from 0 to 1.
34 template <AccessMode mode = AccessMode::NON_ATOMIC>
35 inline bool Set();
36
37 template <AccessMode mode = AccessMode::NON_ATOMIC>
38 inline bool Get() const;
39
40 // The function returns true if it succeeded to
41 // transition the bit from 1 to 0. Only works in non-atomic contexts.
42 inline bool Clear();
43
44#ifdef DEBUG
45 bool operator==(const MarkBit& other) {
46 return cell_ == other.cell_ && mask_ == other.mask_;
47 }
48#endif
49
50 const CellType* CellAddress() const { return cell_; }
51 CellType Mask() const { return mask_; }
52
53 private:
54 inline MarkBit(CellType* cell, CellType mask) : cell_(cell), mask_(mask) {}
55
58
59 friend class MarkingBitmap;
60};
61
62template <>
63inline bool MarkBit::Set<AccessMode::NON_ATOMIC>() {
64 CellType old_value = *cell_;
65 if ((old_value & mask_) == mask_) return false;
66 *cell_ = old_value | mask_;
67 return true;
68}
69
70template <>
71inline bool MarkBit::Set<AccessMode::ATOMIC>() {
72 return base::AsAtomicWord::Relaxed_SetBits(cell_, mask_, mask_);
73}
74
75template <>
76inline bool MarkBit::Get<AccessMode::NON_ATOMIC>() const {
77 return (*cell_ & mask_) != 0;
78}
79
80template <>
81inline bool MarkBit::Get<AccessMode::ATOMIC>() const {
82 return (base::AsAtomicWord::Relaxed_Load(cell_) & mask_) != 0;
83}
84
85inline bool MarkBit::Clear() {
86 CellType old_value = *cell_;
87 *cell_ = old_value & ~mask_;
88 return (old_value & mask_) == mask_;
89}
90
91// Bitmap is a sequence of cells each containing fixed number of bits.
93 public:
95 using CellIndex = uint32_t;
96 using MarkBitIndex = uint32_t;
97
98 static constexpr uint32_t kBitsPerCell = sizeof(CellType) * kBitsPerByte;
99 static constexpr uint32_t kBitsPerCellLog2 =
100 base::bits::CountTrailingZeros(kBitsPerCell);
101 static constexpr uint32_t kBitIndexMask = kBitsPerCell - 1;
102 static constexpr uint32_t kBytesPerCell = kBitsPerCell / kBitsPerByte;
103 static constexpr uint32_t kBytesPerCellLog2 =
104 kBitsPerCellLog2 - kBitsPerByteLog2;
105
106 // The length is the number of bits in this bitmap.
107 static constexpr size_t kLength = ((1 << kPageSizeBits) >> kTaggedSizeLog2);
108
109 static constexpr size_t kCellsCount =
110 (kLength + kBitsPerCell - 1) >> kBitsPerCellLog2;
111
112 // The size of the bitmap in bytes is CellsCount() * kBytesPerCell.
113 static constexpr size_t kSize = kCellsCount * kBytesPerCell;
114
115 V8_INLINE static constexpr MarkBitIndex AddressToIndex(Address address);
116
117 V8_INLINE static constexpr MarkBitIndex LimitAddressToIndex(Address address);
118
119 V8_INLINE static constexpr CellIndex IndexToCell(MarkBitIndex index) {
120 return index >> kBitsPerCellLog2;
121 }
122
123 V8_INLINE static constexpr Address IndexToAddressOffset(MarkBitIndex index) {
124 return index << kTaggedSizeLog2;
125 }
126
127 V8_INLINE static constexpr Address CellToBase(CellIndex cell_index) {
128 return IndexToAddressOffset(cell_index << kBitsPerCellLog2);
129 }
130
131 V8_INLINE static constexpr uint32_t IndexInCell(MarkBitIndex index) {
132 return index & kBitIndexMask;
133 }
134
136 return static_cast<CellType>(1u) << IndexInCell(index);
137 }
138
139 // Retrieves the cell containing the provided markbit index.
140 V8_INLINE static constexpr uint32_t CellAlignIndex(uint32_t index) {
141 return index & ~kBitIndexMask;
142 }
143
144 V8_INLINE static MarkingBitmap* Cast(Address addr) {
145 return reinterpret_cast<MarkingBitmap*>(addr);
146 }
147
148 // Gets the MarkBit for an `address` which may be unaligned (include the tag
149 // bit).
150 V8_INLINE static MarkBit MarkBitFromAddress(Address address);
151 V8_INLINE static MarkBit MarkBitFromAddress(MarkingBitmap* bitmap,
152 Address address);
153
154 MarkingBitmap() = default;
155 MarkingBitmap(const MarkingBitmap&) = delete;
157
158 V8_INLINE CellType* cells() { return cells_; }
159 V8_INLINE const CellType* cells() const { return cells_; }
160
161 // Returns true if all bits in the range [start_index, end_index) are cleared.
162 bool AllBitsClearInRange(MarkBitIndex start_index,
163 MarkBitIndex end_index) const;
164
165 // Returns true if all bits in the range [start_index, end_index) are set.
166 bool AllBitsSetInRange(MarkBitIndex start_index,
167 MarkBitIndex end_index) const;
168
169 template <AccessMode mode>
170 inline void Clear();
171
172 // Sets all bits in the range [start_index, end_index). If the access is
173 // atomic, the cells at the boundary of the range are updated with atomic
174 // compare and swap operation. The inner cells are updated with relaxed write.
175 template <AccessMode mode>
176 inline void SetRange(MarkBitIndex start_index, MarkBitIndex end_index);
177
178 // Clears all bits in the range [start_index, end_index). If the access is
179 // atomic, the cells at the boundary of the range are updated with atomic
180 // compare and swap operation. The inner cells are updated with relaxed write.
181 template <AccessMode mode>
182 inline void ClearRange(MarkBitIndex start_index, MarkBitIndex end_index);
183
184 // Returns true if all bits are cleared.
185 bool IsClean() const;
186
187 // Not safe in a concurrent context.
188 void Print() const;
189
191 const auto mask = IndexInCellMask(index);
192 MarkBit::CellType* cell = cells() + IndexToCell(index);
193 return MarkBit(cell, mask);
194 }
195
196 // This method provides a basis for inner-pointer resolution. It expects a
197 // page and a maybe_inner_ptr that is contained in that page. It returns the
198 // highest address in the page that is not larger than maybe_inner_ptr, has
199 // its markbit set, and whose previous address (if it exists) does not have
200 // its markbit set. If no such address exists, it returns the page area start.
201 // If the page is iterable, the returned address is guaranteed to be the start
202 // of a valid object in the page.
203 static inline Address FindPreviousValidObject(const PageMetadata* page,
204 Address maybe_inner_ptr);
205
206 private:
207 V8_INLINE static MarkingBitmap* FromAddress(Address address);
208
209 // Sets bits in the given cell. The mask specifies bits to set: if a
210 // bit is set in the mask then the corresponding bit is set in the cell.
211 template <AccessMode mode>
212 inline void SetBitsInCell(uint32_t cell_index, MarkBit::CellType mask);
213
214 // Clears bits in the given cell. The mask specifies bits to clear: if a
215 // bit is set in the mask then the corresponding bit is cleared in the cell.
216 template <AccessMode mode>
217 inline void ClearBitsInCell(uint32_t cell_index, MarkBit::CellType mask);
218
219 // Set all bits in the cell range [start_cell_index, end_cell_index). If the
220 // access is atomic then *still* use a relaxed memory ordering.
221 template <AccessMode mode>
222 void SetCellRangeRelaxed(uint32_t start_cell_index, uint32_t end_cell_index);
223
224 template <AccessMode mode>
225 // Clear all bits in the cell range [start_cell_index, end_cell_index). If the
226 // access is atomic then *still* use a relaxed memory ordering.
227 inline void ClearCellRangeRelaxed(uint32_t start_cell_index,
228 uint32_t end_cell_index);
229
230 CellType cells_[kCellsCount] = {0};
231};
232
233struct MarkingHelper final : public AllStatic {
234 // TODO(340989496): Add on hold as target in ShouldMarkObject() and
235 // TryMarkAndPush().
236 enum class WorklistTarget : uint8_t {
237 kRegular,
238 };
239
240 enum class LivenessMode : uint8_t {
241 kMarkbit,
243 };
244
245 // Returns whether an object should be marked and if so also returns the
246 // worklist that must be used to do so.
247 //
248 // Can be used with full GC and young GC using sticky markbits.
249 static V8_INLINE std::optional<WorklistTarget> ShouldMarkObject(
250 Heap* heap, Tagged<HeapObject> object);
251
252 // Returns whether the markbit of an object should be considered or whether
253 // the object is always considered as live.
255 Tagged<HeapObject> object);
256
257 // Returns true if the object is marked or resides on an always live page.
258 template <typename MarkingStateT>
260 MarkingStateT* marking_state,
261 Tagged<HeapObject> object);
262
263 // Returns true if the object is unmarked and doesn't reside on an always live
264 // page.
265 template <typename MarkingStateT>
267 MarkingStateT* marking_state,
268 Tagged<HeapObject> object);
269
270 // Convenience helper around marking and pushing an object.
271 //
272 // Can be used with full GC and young GC using sticky markbits.
273 template <typename MarkingState>
275 Heap* heap, MarkingWorklists::Local* marking_worklist,
276 MarkingState* marking_state, WorklistTarget target_worklis,
277 Tagged<HeapObject> object);
278};
279
280} // namespace v8::internal
281
282#endif // V8_HEAP_MARKING_H_
constexpr int kPageSizeBits
static T Relaxed_Load(T *addr)
static bool Relaxed_SetBits(T *addr, T bits, T mask)
CellType *const cell_
Definition marking.h:56
MarkBit(CellType *cell, CellType mask)
Definition marking.h:54
const CellType * CellAddress() const
Definition marking.h:50
const CellType mask_
Definition marking.h:57
static V8_ALLOW_UNUSED MarkBit FromForTesting(Address)
Definition marking.cc:142
uintptr_t CellType
Definition marking.h:21
CellType Mask() const
Definition marking.h:51
static V8_ALLOW_UNUSED MarkBit From(Address)
static V8_INLINE constexpr Address IndexToAddressOffset(MarkBitIndex index)
Definition marking.h:123
static V8_INLINE constexpr uint32_t CellAlignIndex(uint32_t index)
Definition marking.h:140
MarkingBitmap(const MarkingBitmap &)=delete
void ClearBitsInCell(uint32_t cell_index, MarkBit::CellType mask)
V8_INLINE const CellType * cells() const
Definition marking.h:159
V8_INLINE MarkBit MarkBitFromIndexForTesting(uint32_t index)
Definition marking.h:190
MarkingBitmap & operator=(const MarkingBitmap &)=delete
void SetCellRangeRelaxed(uint32_t start_cell_index, uint32_t end_cell_index)
static V8_INLINE constexpr uint32_t IndexInCell(MarkBitIndex index)
Definition marking.h:131
void SetBitsInCell(uint32_t cell_index, MarkBit::CellType mask)
void ClearCellRangeRelaxed(uint32_t start_cell_index, uint32_t end_cell_index)
MarkBit::CellType CellType
Definition marking.h:94
V8_INLINE CellType * cells()
Definition marking.h:158
static V8_INLINE constexpr CellIndex IndexToCell(MarkBitIndex index)
Definition marking.h:119
static V8_INLINE constexpr Address CellToBase(CellIndex cell_index)
Definition marking.h:127
static V8_INLINE MarkingBitmap * Cast(Address addr)
Definition marking.h:144
static V8_INLINE constexpr CellType IndexInCellMask(MarkBitIndex index)
Definition marking.h:135
const PropertyCellRef cell_
uint32_t const mask
Atomic32 AtomicWord
Definition atomicops.h:76
constexpr int kBitsPerByte
Definition globals.h:682
constexpr int kTaggedSizeLog2
Definition globals.h:543
bool operator==(ExternalReference lhs, ExternalReference rhs)
constexpr int kBitsPerByteLog2
Definition globals.h:683
#define V8_ALLOW_UNUSED
#define V8_EXPORT_PRIVATE
Definition macros.h:460
static V8_INLINE bool TryMarkAndPush(Heap *heap, MarkingWorklists::Local *marking_worklist, MarkingState *marking_state, WorklistTarget target_worklis, Tagged< HeapObject > object)
static V8_INLINE bool IsMarkedOrAlwaysLive(Heap *heap, MarkingStateT *marking_state, Tagged< HeapObject > object)
static V8_INLINE bool IsUnmarkedAndNotAlwaysLive(Heap *heap, MarkingStateT *marking_state, Tagged< HeapObject > object)
static V8_INLINE std::optional< WorklistTarget > ShouldMarkObject(Heap *heap, Tagged< HeapObject > object)
static V8_INLINE LivenessMode GetLivenessMode(Heap *heap, Tagged< HeapObject > object)
#define V8_INLINE
Definition v8config.h:500