v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
heap-visitor.h
Go to the documentation of this file.
1// Copyright 2012 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_HEAP_VISITOR_H_
6#define V8_HEAP_HEAP_VISITOR_H_
7
8#include "src/base/logging.h"
14#include "src/objects/map.h"
16#include "src/objects/objects.h"
18#include "src/objects/string.h"
20
21namespace v8 {
22namespace internal {
23
24// This class is used as argument to the HeapVisitor::Visit() method as a
25// cheaper alternative to std::optional<size_t>.
26class MaybeObjectSize final {
27 public:
28 explicit MaybeObjectSize(size_t size) : raw_size_(size) {
29 DCHECK_GT(size, 0);
30 }
31
33
34 size_t AssumeSize() const {
36 return raw_size_;
37 }
38
39 bool IsNone() const { return raw_size_ == 0; }
40
41 private:
42 size_t raw_size_;
43};
44
45// Visitation in here will refer to BodyDescriptors with the regular instance
46// size.
47#define TYPED_VISITOR_ID_LIST(V) \
48 V(AccessorInfo) \
49 V(AllocationSite) \
50 V(BigInt) \
51 V(BytecodeWrapper) \
52 V(CallSiteInfo) \
53 V(Cell) \
54 V(CodeWrapper) \
55 V(ConsString) \
56 V(ContextSidePropertyCell) \
57 V(CoverageInfo) \
58 V(DataHandler) \
59 V(DebugInfo) \
60 V(EmbedderDataArray) \
61 V(EphemeronHashTable) \
62 V(ExternalString) \
63 V(FeedbackCell) \
64 V(FeedbackMetadata) \
65 V(Foreign) \
66 V(FunctionTemplateInfo) \
67 V(HeapNumber) \
68 V(InterceptorInfo) \
69 V(Hole) \
70 V(Map) \
71 V(NativeContext) \
72 V(Oddball) \
73 V(PreparseData) \
74 V(PropertyArray) \
75 V(PropertyCell) \
76 V(PrototypeInfo) \
77 V(RegExpBoilerplateDescription) \
78 V(RegExpDataWrapper) \
79 V(SeqOneByteString) \
80 V(SeqTwoByteString) \
81 V(SharedFunctionInfo) \
82 V(SlicedString) \
83 V(SloppyArgumentsElements) \
84 V(SmallOrderedHashMap) \
85 V(SmallOrderedHashSet) \
86 V(SmallOrderedNameDictionary) \
87 V(SourceTextModule) \
88 V(SwissNameDictionary) \
89 V(Symbol) \
90 V(SyntheticModule) \
91 V(ThinString) \
92 V(TransitionArray) \
93 V(WeakCell) \
94 IF_WASM(V, WasmArray) \
95 IF_WASM(V, WasmFuncRef) \
96 IF_WASM(V, WasmMemoryMapDescriptor) \
97 IF_WASM(V, WasmNull) \
98 IF_WASM(V, WasmResumeData) \
99 IF_WASM(V, WasmStruct) \
100 IF_WASM(V, WasmSuspenderObject) \
101 IF_WASM(V, WasmTypeInfo) \
102 SIMPLE_HEAP_OBJECT_LIST1(V)
103
104// Visitation in here will refer to BodyDescriptors with the used size of the
105// map. Slack will thus be ignored. We are not allowed to visit slack as that's
106// visiting free space fillers.
107#define TYPED_VISITOR_WITH_SLACK_ID_LIST(V) \
108 V(JSArrayBuffer) \
109 V(JSDataViewOrRabGsabDataView) \
110 V(JSDate) \
111 V(JSExternalObject) \
112 V(JSFinalizationRegistry) \
113 V(JSFunction) \
114 V(JSObject) \
115 V(JSRegExp) \
116 V(JSSynchronizationPrimitive) \
117 V(JSTypedArray) \
118 V(JSWeakCollection) \
119 V(JSWeakRef) \
120 IF_WASM(V, WasmGlobalObject) \
121 IF_WASM(V, WasmInstanceObject) \
122 IF_WASM(V, WasmMemoryObject) \
123 IF_WASM(V, WasmSuspendingObject) \
124 IF_WASM(V, WasmTableObject) \
125 IF_WASM(V, WasmTagObject)
126
127// List of visitor ids that can only appear in read-only maps. Unfortunately,
128// these are generally contained in all other lists.
129//
130// Adding an instance type here allows skipping vistiation of Map slots for
131// visitors with `ShouldVisitReadOnlyMapPointer() == false`.
132#define VISITOR_IDS_WITH_READ_ONLY_MAPS_LIST(V) \
133 /* All trusted objects have maps in read-only space. */ \
134 CONCRETE_TRUSTED_OBJECT_TYPE_LIST1(V) \
135 V(AccessorInfo) \
136 V(AllocationSite) \
137 V(BigInt) \
138 V(BytecodeWrapper) \
139 V(ByteArray) \
140 V(Cell) \
141 V(CodeWrapper) \
142 V(DataHandler) \
143 V(DescriptorArray) \
144 V(EmbedderDataArray) \
145 V(ExternalString) \
146 V(FeedbackCell) \
147 V(FeedbackMetadata) \
148 V(FeedbackVector) \
149 V(Filler) \
150 V(FixedArray) \
151 V(FixedDoubleArray) \
152 V(FunctionTemplateInfo) \
153 V(FreeSpace) \
154 V(HeapNumber) \
155 V(InterceptorInfo) \
156 V(PreparseData) \
157 V(PropertyArray) \
158 V(PropertyCell) \
159 V(PrototypeInfo) \
160 V(RegExpBoilerplateDescription) \
161 V(RegExpDataWrapper) \
162 V(ScopeInfo) \
163 V(SeqOneByteString) \
164 V(SeqTwoByteString) \
165 V(SharedFunctionInfo) \
166 V(ShortcutCandidate) \
167 V(SlicedString) \
168 V(SloppyArgumentsElements) \
169 V(Symbol) \
170 V(ThinString) \
171 V(TransitionArray) \
172 V(WeakArrayList) \
173 V(WeakFixedArray)
174
175#define FORWARD_DECLARE(TypeName) class TypeName;
180#undef FORWARD_DECLARE
181
182// The base class for visitors that need to dispatch on object type. The default
183// behavior of all visit functions is to iterate body of the given object using
184// the BodyDescriptor of the object.
185//
186// The visit functions return the size of the object.
187//
188// This class is intended to be used in the following way:
189//
190// class SomeVisitor : public HeapVisitor<SomeVisitor> {
191// ...
192// }
193template <typename ConcreteVisitor>
195 public:
196 inline explicit HeapVisitor(LocalIsolate* isolate);
197 inline explicit HeapVisitor(Isolate* isolate);
198 inline explicit HeapVisitor(Heap* heap);
199
200 V8_INLINE size_t Visit(Tagged<HeapObject> object)
201 requires(!ConcreteVisitor::UsePrecomputedObjectSize());
202
204 requires(!ConcreteVisitor::UsePrecomputedObjectSize());
205
207 int object_size)
208 requires(ConcreteVisitor::UsePrecomputedObjectSize());
209
210 protected:
212 MaybeObjectSize maybe_object_size);
213
214 // If this predicate returns false the default implementations of Visit*
215 // functions bail out from visiting the map pointer.
216 V8_INLINE static constexpr bool ShouldVisitMapPointer() { return true; }
217 // If this predicate returns false the default implementations of Visit*
218 // functions bail out from visiting known read-only maps.
219 V8_INLINE static constexpr bool ShouldVisitReadOnlyMapPointer() {
220 return true;
221 }
222 // If this predicate returns false the default implementation of
223 // `VisitFiller()` and `VisitFreeSpace()` will be unreachable.
224 V8_INLINE static constexpr bool CanEncounterFillerOrFreeSpace() {
225 return true;
226 }
227 // If this predicate returns false the default implementation of
228 // `VisitFiller()` and `VisitFreeSpace()` will be unreachable.
229 V8_INLINE static constexpr bool ShouldUseUncheckedCast() { return false; }
230
231 // This should really only be defined and used in ConcurrentHeapVisitor but we
232 // need it here for a DCHECK in HeapVisitor::VisitWithBodyDescriptor.
233 V8_INLINE static constexpr bool EnableConcurrentVisitation() { return false; }
234
235 // Avoids size computation in visitors and uses the input argument instead.
236 V8_INLINE static constexpr bool UsePrecomputedObjectSize() { return false; }
237
238 // Only visits the Map pointer if `ShouldVisitMapPointer()` returns true.
239 template <VisitorId visitor_id>
241
242 // If this predicate returns true, the visitor will visit the full JSObject
243 // (including slack).
244 V8_INLINE static constexpr bool ShouldVisitFullJSObject() { return false; }
245
246 ConcreteVisitor* concrete_visitor() {
247 return static_cast<ConcreteVisitor*>(this);
248 }
249
250 const ConcreteVisitor* concrete_visitor() const {
251 return static_cast<const ConcreteVisitor*>(this);
252 }
253
254#define VISIT(TypeName) \
255 V8_INLINE size_t Visit##TypeName(Tagged<Map> map, Tagged<TypeName> object, \
256 MaybeObjectSize maybe_object_size);
261#undef VISIT
262 V8_INLINE size_t VisitShortcutCandidate(Tagged<Map> map,
263 Tagged<ConsString> object,
264 MaybeObjectSize maybe_object_size);
265 V8_INLINE size_t VisitJSObjectFast(Tagged<Map> map, Tagged<JSObject> object,
266 MaybeObjectSize maybe_object_size);
267 V8_INLINE size_t VisitJSApiObject(Tagged<Map> map, Tagged<JSObject> object,
268 MaybeObjectSize maybe_object_size);
269 V8_INLINE size_t VisitStruct(Tagged<Map> map, Tagged<HeapObject> object,
270 MaybeObjectSize maybe_object_size);
271 V8_INLINE size_t VisitFiller(Tagged<Map> map, Tagged<HeapObject> object,
272 MaybeObjectSize maybe_object_size);
273 V8_INLINE size_t VisitFreeSpace(Tagged<Map> map, Tagged<FreeSpace> object,
274 MaybeObjectSize maybe_object_size);
275
276 template <typename T, typename TBodyDescriptor = typename T::BodyDescriptor>
278 MaybeObjectSize maybe_object_size);
279
280 template <VisitorId visitor_id, typename T,
281 typename TBodyDescriptor = typename T::BodyDescriptor>
283 MaybeObjectSize maybe_object_size);
284
285 template <typename T>
287
288 // Inspects the slot and filters some well-known RO objects and Smis in a fast
289 // way. May still return Smis or RO objects.
290 template <typename TSlot>
291 std::optional<Tagged<Object>> GetObjectFilterReadOnlyAndSmiFast(
292 TSlot slot) const;
293
294 protected:
295 const Heap* heap_;
296};
297
298// These strings can be sources of safe string transitions. Transitions are safe
299// if they don't result in invalidated slots. It's safe to read the length field
300// on such strings as that's common for all.
301//
302// No special visitors are generated for such strings.
303// V(VisitorId, TypeName)
304#define SAFE_STRING_TRANSITION_SOURCES(V) \
305 V(SeqOneByteString, SeqOneByteString) \
306 V(SeqTwoByteString, SeqTwoByteString)
307
308// These strings can be sources of unsafe string transitions.
309// V(VisitorId, TypeName)
310#define UNSAFE_STRING_TRANSITION_SOURCES(V) \
311 V(ExternalString, ExternalString) \
312 V(ConsString, ConsString) \
313 V(SlicedString, SlicedString)
314
315// V(VisitorId, TypeName)
316#define UNSAFE_STRING_TRANSITION_TARGETS(V) \
317 UNSAFE_STRING_TRANSITION_SOURCES(V) \
318 V(ShortcutCandidate, ConsString) \
319 V(ThinString, ThinString)
320
321// A HeapVisitor that allows for concurrently tracing through objects. Tracing
322// through objects with unsafe shape changes is guarded by
323// `EnableConcurrentVisitation()` which defaults to off.
324template <typename ConcreteVisitor>
325class ConcurrentHeapVisitor : public HeapVisitor<ConcreteVisitor> {
326 public:
327 V8_INLINE explicit ConcurrentHeapVisitor(Isolate* isolate);
328
329 V8_INLINE static constexpr bool EnableConcurrentVisitation() { return false; }
330
331 protected:
332#define VISIT_AS_LOCKED_STRING(VisitorId, TypeName) \
333 V8_INLINE size_t Visit##TypeName(Tagged<Map> map, Tagged<TypeName> object, \
334 MaybeObjectSize maybe_object_size);
335
337#undef VISIT_AS_LOCKED_STRING
338
339 template <typename T>
341
342 private:
343 template <typename T>
345
346 friend class HeapVisitor<ConcreteVisitor>;
347};
348
349template <typename ConcreteVisitor>
350class NewSpaceVisitor : public ConcurrentHeapVisitor<ConcreteVisitor> {
351 public:
352 V8_INLINE explicit NewSpaceVisitor(Isolate* isolate);
353
354 // Special cases: Unreachable visitors for objects that are never found in the
355 // young generation.
367
368 protected:
369 V8_INLINE static constexpr bool ShouldVisitMapPointer() { return false; }
370
371 // Special cases: Unreachable visitors for objects that are never found in the
372 // young generation.
386 UNREACHABLE();
387 }
388
389 friend class HeapVisitor<ConcreteVisitor>;
390};
391
392class WeakObjectRetainer;
393
394// A weak list is single linked list where each element has a weak pointer to
395// the next element. Given the head of the list, this function removes dead
396// elements from the list and if requested records slots for next-element
397// pointers. The template parameter T is a WeakListVisitor that defines how to
398// access the next-element pointers.
399template <class T>
401 WeakObjectRetainer* retainer);
402} // namespace internal
403} // namespace v8
404
405#endif // V8_HEAP_HEAP_VISITOR_H_
#define T
#define FORWARD_DECLARE(Name, Argc)
Definition builtins.cc:30
V8_INLINE ConcurrentHeapVisitor(Isolate *isolate)
static V8_INLINE Tagged< T > Cast(Tagged< HeapObject > object, const Heap *heap)
V8_INLINE size_t VisitStringLocked(Tagged< T > object)
static V8_INLINE constexpr bool EnableConcurrentVisitation()
V8_INLINE size_t VisitFiller(Tagged< Map > map, Tagged< HeapObject > object, MaybeObjectSize maybe_object_size)
const ConcreteVisitor * concrete_visitor() const
static V8_INLINE Tagged< T > Cast(Tagged< HeapObject > object, const Heap *heap)
static V8_INLINE constexpr bool ShouldVisitReadOnlyMapPointer()
static V8_INLINE constexpr bool ShouldUseUncheckedCast()
V8_INLINE size_t VisitShortcutCandidate(Tagged< Map > map, Tagged< ConsString > object, MaybeObjectSize maybe_object_size)
V8_INLINE size_t VisitJSObjectSubclass(Tagged< Map > map, Tagged< T > object, MaybeObjectSize maybe_object_size)
V8_INLINE void VisitMapPointerIfNeeded(Tagged< HeapObject > host)
static V8_INLINE constexpr bool ShouldVisitFullJSObject()
HeapVisitor(LocalIsolate *isolate)
static V8_INLINE constexpr bool CanEncounterFillerOrFreeSpace()
static V8_INLINE constexpr bool UsePrecomputedObjectSize()
ConcreteVisitor * concrete_visitor()
V8_INLINE size_t VisitFreeSpace(Tagged< Map > map, Tagged< FreeSpace > object, MaybeObjectSize maybe_object_size)
static V8_INLINE constexpr bool EnableConcurrentVisitation()
V8_INLINE size_t VisitStruct(Tagged< Map > map, Tagged< HeapObject > object, MaybeObjectSize maybe_object_size)
V8_INLINE size_t VisitJSObjectFast(Tagged< Map > map, Tagged< JSObject > object, MaybeObjectSize maybe_object_size)
std::optional< Tagged< Object > > GetObjectFilterReadOnlyAndSmiFast(TSlot slot) const
static V8_INLINE constexpr bool ShouldVisitMapPointer()
V8_INLINE size_t Visit(Tagged< HeapObject > object)
V8_INLINE size_t VisitJSApiObject(Tagged< Map > map, Tagged< JSObject > object, MaybeObjectSize maybe_object_size)
V8_INLINE size_t VisitWithBodyDescriptor(Tagged< Map > map, Tagged< T > object, MaybeObjectSize maybe_object_size)
void VisitInstructionStreamPointer(Tagged< Code >, InstructionStreamSlot) final
size_t VisitBytecodeArray(Tagged< Map >, Tagged< BytecodeArray >, MaybeObjectSize)
void VisitEmbeddedPointer(Tagged< InstructionStream > host, RelocInfo *) final
static V8_INLINE constexpr bool ShouldVisitMapPointer()
size_t VisitWeakCell(Tagged< Map >, Tagged< WeakCell >, MaybeObjectSize)
void VisitMapPointer(Tagged< HeapObject >) override
void VisitCodeTarget(Tagged< InstructionStream > host, RelocInfo *) final
size_t VisitNativeContext(Tagged< Map >, Tagged< NativeContext >, MaybeObjectSize)
size_t VisitSharedFunctionInfo(Tagged< Map > map, Tagged< SharedFunctionInfo >, MaybeObjectSize)
V8_INLINE NewSpaceVisitor(Isolate *isolate)
#define VISIT(TypeName)
#define VISIT_AS_LOCKED_STRING(VisitorId, TypeName)
#define TYPED_VISITOR_WITH_SLACK_ID_LIST(V)
#define TYPED_VISITOR_ID_LIST(V)
#define UNSAFE_STRING_TRANSITION_SOURCES(V)
#define TORQUE_VISITOR_ID_LIST(V)
Definition map.h:117
#define TRUSTED_VISITOR_ID_LIST(V)
Definition map.h:121
Tagged< Object > VisitWeakList(Heap *heap, Tagged< Object > list, WeakObjectRetainer *retainer)
Tagged(T object) -> Tagged< T >
kInterpreterTrampolineOffset Tagged< HeapObject >
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define V8_INLINE
Definition v8config.h:500