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_OBJECTS_VISITING_INL_H_
6 #define V8_HEAP_OBJECTS_VISITING_INL_H_
7
8 #include "src/heap/embedder-tracing.h"
9 #include "src/heap/mark-compact.h"
10 #include "src/heap/objects-visiting.h"
11 #include "src/objects/arguments.h"
12 #include "src/objects/data-handler-inl.h"
13 #include "src/objects/free-space-inl.h"
14 #include "src/objects/js-weak-refs-inl.h"
15 #include "src/objects/module-inl.h"
16 #include "src/objects/objects-body-descriptors-inl.h"
17 #include "src/objects/objects-inl.h"
18 #include "src/objects/oddball.h"
19 #include "src/objects/ordered-hash-table.h"
20 #include "src/objects/synthetic-module-inl.h"
21 #include "src/objects/torque-defined-classes.h"
22 #include "src/objects/visitors.h"
23
24 #if V8_ENABLE_WEBASSEMBLY
25 #include "src/wasm/wasm-objects.h"
26 #endif // V8_ENABLE_WEBASSEMBLY
27
28 namespace v8 {
29 namespace internal {
30
31 template <typename ResultType, typename ConcreteVisitor>
HeapVisitor(PtrComprCageBase cage_base,PtrComprCageBase code_cage_base)32 HeapVisitor<ResultType, ConcreteVisitor>::HeapVisitor(
33 PtrComprCageBase cage_base, PtrComprCageBase code_cage_base)
34 : ObjectVisitorWithCageBases(cage_base, code_cage_base) {}
35
36 template <typename ResultType, typename ConcreteVisitor>
HeapVisitor(Isolate * isolate)37 HeapVisitor<ResultType, ConcreteVisitor>::HeapVisitor(Isolate* isolate)
38 : ObjectVisitorWithCageBases(isolate) {}
39
40 template <typename ResultType, typename ConcreteVisitor>
HeapVisitor(Heap * heap)41 HeapVisitor<ResultType, ConcreteVisitor>::HeapVisitor(Heap* heap)
42 : ObjectVisitorWithCageBases(heap) {}
43
44 template <typename ResultType, typename ConcreteVisitor>
45 template <typename T>
Cast(HeapObject object)46 T HeapVisitor<ResultType, ConcreteVisitor>::Cast(HeapObject object) {
47 return T::cast(object);
48 }
49
50 template <typename ResultType, typename ConcreteVisitor>
Visit(HeapObject object)51 ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(HeapObject object) {
52 return Visit(object.map(cage_base()), object);
53 }
54
55 template <typename ResultType, typename ConcreteVisitor>
Visit(Map map,HeapObject object)56 ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map map,
57 HeapObject object) {
58 ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
59 switch (map.visitor_id()) {
60 #define CASE(TypeName) \
61 case kVisit##TypeName: \
62 return visitor->Visit##TypeName( \
63 map, ConcreteVisitor::template Cast<TypeName>(object));
64 TYPED_VISITOR_ID_LIST(CASE)
65 TORQUE_VISITOR_ID_LIST(CASE)
66 #undef CASE
67 case kVisitShortcutCandidate:
68 return visitor->VisitShortcutCandidate(
69 map, ConcreteVisitor::template Cast<ConsString>(object));
70 case kVisitDataObject:
71 return visitor->VisitDataObject(map, object);
72 case kVisitJSObjectFast:
73 return visitor->VisitJSObjectFast(
74 map, ConcreteVisitor::template Cast<JSObject>(object));
75 case kVisitJSApiObject:
76 return visitor->VisitJSApiObject(
77 map, ConcreteVisitor::template Cast<JSObject>(object));
78 case kVisitStruct:
79 return visitor->VisitStruct(map, object);
80 case kVisitFreeSpace:
81 return visitor->VisitFreeSpace(map, FreeSpace::cast(object));
82 case kDataOnlyVisitorIdCount:
83 case kVisitorIdCount:
84 UNREACHABLE();
85 }
86 UNREACHABLE();
87 // Make the compiler happy.
88 return ResultType();
89 }
90
91 template <typename ResultType, typename ConcreteVisitor>
VisitMapPointer(HeapObject host)92 void HeapVisitor<ResultType, ConcreteVisitor>::VisitMapPointer(
93 HeapObject host) {
94 DCHECK(!host.map_word(kRelaxedLoad).IsForwardingAddress());
95 if (!static_cast<ConcreteVisitor*>(this)->ShouldVisitMapPointer()) return;
96 static_cast<ConcreteVisitor*>(this)->VisitMapPointer(host);
97 }
98
99 #define VISIT(TypeName) \
100 template <typename ResultType, typename ConcreteVisitor> \
101 ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit##TypeName( \
102 Map map, TypeName object) { \
103 ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this); \
104 if (!visitor->ShouldVisit(object)) return ResultType(); \
105 if (!visitor->AllowDefaultJSObjectVisit()) { \
106 DCHECK_WITH_MSG(!map.IsJSObjectMap(), \
107 "Implement custom visitor for new JSObject subclass in " \
108 "concurrent marker"); \
109 } \
110 int size = TypeName::BodyDescriptor::SizeOf(map, object); \
111 if (visitor->ShouldVisitMapPointer()) { \
112 visitor->VisitMapPointer(object); \
113 } \
114 TypeName::BodyDescriptor::IterateBody(map, object, size, visitor); \
115 return static_cast<ResultType>(size); \
116 }
117 TYPED_VISITOR_ID_LIST(VISIT)
TORQUE_VISITOR_ID_LIST(VISIT)118 TORQUE_VISITOR_ID_LIST(VISIT)
119 #undef VISIT
120
121 template <typename ResultType, typename ConcreteVisitor>
122 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitShortcutCandidate(
123 Map map, ConsString object) {
124 return static_cast<ConcreteVisitor*>(this)->VisitConsString(map, object);
125 }
126
127 template <typename ResultType, typename ConcreteVisitor>
VisitDataObject(Map map,HeapObject object)128 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitDataObject(
129 Map map, HeapObject object) {
130 ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
131 if (!visitor->ShouldVisit(object)) return ResultType();
132 int size = map.instance_size();
133 if (visitor->ShouldVisitMapPointer()) {
134 visitor->VisitMapPointer(object);
135 }
136 #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
137 // The following types have external pointers, which must be visited.
138 // TODO(v8:10391) Consider adding custom visitor IDs for these.
139 if (object.IsExternalOneByteString()) {
140 ExternalOneByteString::BodyDescriptor::IterateBody(map, object, size,
141 visitor);
142 } else if (object.IsExternalTwoByteString()) {
143 ExternalTwoByteString::BodyDescriptor::IterateBody(map, object, size,
144 visitor);
145 } else if (object.IsForeign()) {
146 Foreign::BodyDescriptor::IterateBody(map, object, size, visitor);
147 }
148 #endif // V8_SANDBOXED_EXTERNAL_POINTERS
149 return static_cast<ResultType>(size);
150 }
151
152 template <typename ResultType, typename ConcreteVisitor>
VisitJSObjectFast(Map map,JSObject object)153 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSObjectFast(
154 Map map, JSObject object) {
155 ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
156 if (!visitor->ShouldVisit(object)) return ResultType();
157 int size = JSObject::FastBodyDescriptor::SizeOf(map, object);
158 if (visitor->ShouldVisitMapPointer()) {
159 visitor->VisitMapPointer(object);
160 }
161 JSObject::FastBodyDescriptor::IterateBody(map, object, size, visitor);
162 return static_cast<ResultType>(size);
163 }
164
165 template <typename ResultType, typename ConcreteVisitor>
VisitJSApiObject(Map map,JSObject object)166 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSApiObject(
167 Map map, JSObject object) {
168 ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
169 if (!visitor->ShouldVisit(object)) return ResultType();
170 int size = JSObject::BodyDescriptor::SizeOf(map, object);
171 if (visitor->ShouldVisitMapPointer()) {
172 visitor->VisitMapPointer(object);
173 }
174 JSObject::BodyDescriptor::IterateBody(map, object, size, visitor);
175 return static_cast<ResultType>(size);
176 }
177
178 template <typename ResultType, typename ConcreteVisitor>
VisitStruct(Map map,HeapObject object)179 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitStruct(
180 Map map, HeapObject object) {
181 ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
182 if (!visitor->ShouldVisit(object)) return ResultType();
183 int size = map.instance_size();
184 if (visitor->ShouldVisitMapPointer()) {
185 visitor->VisitMapPointer(object);
186 }
187 StructBodyDescriptor::IterateBody(map, object, size, visitor);
188 return static_cast<ResultType>(size);
189 }
190
191 template <typename ResultType, typename ConcreteVisitor>
VisitFreeSpace(Map map,FreeSpace object)192 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace(
193 Map map, FreeSpace object) {
194 ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
195 if (!visitor->ShouldVisit(object)) return ResultType();
196 if (visitor->ShouldVisitMapPointer()) {
197 visitor->VisitMapPointer(object);
198 }
199 return static_cast<ResultType>(object.size(kRelaxedLoad));
200 }
201
202 template <typename ConcreteVisitor>
NewSpaceVisitor(Isolate * isolate)203 NewSpaceVisitor<ConcreteVisitor>::NewSpaceVisitor(Isolate* isolate)
204 : HeapVisitor<int, ConcreteVisitor>(isolate) {}
205
206 template <typename ConcreteVisitor>
VisitNativeContext(Map map,NativeContext object)207 int NewSpaceVisitor<ConcreteVisitor>::VisitNativeContext(Map map,
208 NativeContext object) {
209 ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
210 int size = NativeContext::BodyDescriptor::SizeOf(map, object);
211 NativeContext::BodyDescriptor::IterateBody(map, object, size, visitor);
212 return size;
213 }
214
215 template <typename ConcreteVisitor>
VisitJSApiObject(Map map,JSObject object)216 int NewSpaceVisitor<ConcreteVisitor>::VisitJSApiObject(Map map,
217 JSObject object) {
218 ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
219 return visitor->VisitJSObject(map, object);
220 }
221
222 template <typename ConcreteVisitor>
VisitSharedFunctionInfo(Map map,SharedFunctionInfo object)223 int NewSpaceVisitor<ConcreteVisitor>::VisitSharedFunctionInfo(
224 Map map, SharedFunctionInfo object) {
225 UNREACHABLE();
226 return 0;
227 }
228
229 template <typename ConcreteVisitor>
VisitWeakCell(Map map,WeakCell weak_cell)230 int NewSpaceVisitor<ConcreteVisitor>::VisitWeakCell(Map map,
231 WeakCell weak_cell) {
232 UNREACHABLE();
233 return 0;
234 }
235
236 } // namespace internal
237 } // namespace v8
238
239 #endif // V8_HEAP_OBJECTS_VISITING_INL_H_
240