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/objects-visiting.h"
9 
10 #include "src/heap/array-buffer-tracker.h"
11 #include "src/heap/embedder-tracing.h"
12 #include "src/heap/mark-compact.h"
13 #include "src/macro-assembler.h"
14 #include "src/objects-body-descriptors-inl.h"
15 #include "src/objects-inl.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 template <typename ResultType, typename ConcreteVisitor>
21 template <typename T>
Cast(HeapObject * object)22 T* HeapVisitor<ResultType, ConcreteVisitor>::Cast(HeapObject* object) {
23   return T::cast(object);
24 }
25 
26 template <typename ResultType, typename ConcreteVisitor>
Visit(HeapObject * object)27 ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(HeapObject* object) {
28   return Visit(object->map(), object);
29 }
30 
31 template <typename ResultType, typename ConcreteVisitor>
Visit(Map * map,HeapObject * object)32 ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map* map,
33                                                            HeapObject* object) {
34   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
35   switch (map->visitor_id()) {
36 #define CASE(type)                   \
37   case kVisit##type:                 \
38     return visitor->Visit##type(map, \
39                                 ConcreteVisitor::template Cast<type>(object));
40     TYPED_VISITOR_ID_LIST(CASE)
41 #undef CASE
42     case kVisitShortcutCandidate:
43       return visitor->VisitShortcutCandidate(
44           map, ConcreteVisitor::template Cast<ConsString>(object));
45     case kVisitNativeContext:
46       return visitor->VisitNativeContext(
47           map, ConcreteVisitor::template Cast<Context>(object));
48     case kVisitDataObject:
49       return visitor->VisitDataObject(map, object);
50     case kVisitJSObjectFast:
51       return visitor->VisitJSObjectFast(
52           map, ConcreteVisitor::template Cast<JSObject>(object));
53     case kVisitJSApiObject:
54       return visitor->VisitJSApiObject(
55           map, ConcreteVisitor::template Cast<JSObject>(object));
56     case kVisitStruct:
57       return visitor->VisitStruct(map, object);
58     case kVisitFreeSpace:
59       return visitor->VisitFreeSpace(map, FreeSpace::cast(object));
60     case kVisitWeakArray:
61       return visitor->VisitWeakArray(map, object);
62     case kVisitorIdCount:
63       UNREACHABLE();
64   }
65   UNREACHABLE();
66   // Make the compiler happy.
67   return ResultType();
68 }
69 
70 template <typename ResultType, typename ConcreteVisitor>
VisitMapPointer(HeapObject * host,HeapObject ** map)71 void HeapVisitor<ResultType, ConcreteVisitor>::VisitMapPointer(
72     HeapObject* host, HeapObject** map) {
73   static_cast<ConcreteVisitor*>(this)->VisitPointer(
74       host, reinterpret_cast<Object**>(map));
75 }
76 
77 #define VISIT(type)                                                            \
78   template <typename ResultType, typename ConcreteVisitor>                     \
79   ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit##type(            \
80       Map* map, type* object) {                                                \
81     ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);            \
82     if (!visitor->ShouldVisit(object)) return ResultType();                    \
83     if (!visitor->AllowDefaultJSObjectVisit()) {                               \
84       DCHECK_WITH_MSG(!map->IsJSObjectMap(),                                   \
85                       "Implement custom visitor for new JSObject subclass in " \
86                       "concurrent marker");                                    \
87     }                                                                          \
88     int size = type::BodyDescriptor::SizeOf(map, object);                      \
89     if (visitor->ShouldVisitMapPointer())                                      \
90       visitor->VisitMapPointer(object, object->map_slot());                    \
91     type::BodyDescriptor::IterateBody(map, object, size, visitor);             \
92     return static_cast<ResultType>(size);                                      \
93   }
TYPED_VISITOR_ID_LIST(VISIT)94 TYPED_VISITOR_ID_LIST(VISIT)
95 #undef VISIT
96 
97 template <typename ResultType, typename ConcreteVisitor>
98 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitShortcutCandidate(
99     Map* map, ConsString* object) {
100   return static_cast<ConcreteVisitor*>(this)->VisitConsString(map, object);
101 }
102 
103 template <typename ResultType, typename ConcreteVisitor>
VisitNativeContext(Map * map,Context * object)104 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitNativeContext(
105     Map* map, Context* object) {
106   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
107   if (!visitor->ShouldVisit(object)) return ResultType();
108   int size = Context::BodyDescriptor::SizeOf(map, object);
109   if (visitor->ShouldVisitMapPointer())
110     visitor->VisitMapPointer(object, object->map_slot());
111   Context::BodyDescriptor::IterateBody(map, object, size, visitor);
112   return static_cast<ResultType>(size);
113 }
114 
115 template <typename ResultType, typename ConcreteVisitor>
VisitDataObject(Map * map,HeapObject * object)116 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitDataObject(
117     Map* map, HeapObject* object) {
118   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
119   if (!visitor->ShouldVisit(object)) return ResultType();
120   int size = map->instance_size();
121   if (visitor->ShouldVisitMapPointer())
122     visitor->VisitMapPointer(object, object->map_slot());
123   return static_cast<ResultType>(size);
124 }
125 
126 template <typename ResultType, typename ConcreteVisitor>
VisitJSObjectFast(Map * map,JSObject * object)127 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSObjectFast(
128     Map* map, JSObject* object) {
129   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
130   if (!visitor->ShouldVisit(object)) return ResultType();
131   int size = JSObject::FastBodyDescriptor::SizeOf(map, object);
132   if (visitor->ShouldVisitMapPointer())
133     visitor->VisitMapPointer(object, object->map_slot());
134   JSObject::FastBodyDescriptor::IterateBody(map, object, size, visitor);
135   return static_cast<ResultType>(size);
136 }
137 
138 template <typename ResultType, typename ConcreteVisitor>
VisitJSApiObject(Map * map,JSObject * object)139 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSApiObject(
140     Map* map, JSObject* object) {
141   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
142   if (!visitor->ShouldVisit(object)) return ResultType();
143   int size = JSObject::BodyDescriptor::SizeOf(map, object);
144   if (visitor->ShouldVisitMapPointer())
145     visitor->VisitMapPointer(object, object->map_slot());
146   JSObject::BodyDescriptor::IterateBody(map, object, size, visitor);
147   return static_cast<ResultType>(size);
148 }
149 
150 template <typename ResultType, typename ConcreteVisitor>
VisitStruct(Map * map,HeapObject * object)151 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitStruct(
152     Map* map, HeapObject* object) {
153   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
154   if (!visitor->ShouldVisit(object)) return ResultType();
155   int size = map->instance_size();
156   if (visitor->ShouldVisitMapPointer())
157     visitor->VisitMapPointer(object, object->map_slot());
158   StructBodyDescriptor::IterateBody(map, object, size, visitor);
159   return static_cast<ResultType>(size);
160 }
161 
162 template <typename ResultType, typename ConcreteVisitor>
VisitFreeSpace(Map * map,FreeSpace * object)163 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace(
164     Map* map, FreeSpace* object) {
165   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
166   if (!visitor->ShouldVisit(object)) return ResultType();
167   if (visitor->ShouldVisitMapPointer())
168     visitor->VisitMapPointer(object, object->map_slot());
169   return static_cast<ResultType>(FreeSpace::cast(object)->size());
170 }
171 
172 template <typename ConcreteVisitor>
VisitJSFunction(Map * map,JSFunction * object)173 int NewSpaceVisitor<ConcreteVisitor>::VisitJSFunction(Map* map,
174                                                       JSFunction* object) {
175   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
176   int size = JSFunction::BodyDescriptorWeak::SizeOf(map, object);
177   JSFunction::BodyDescriptorWeak::IterateBody(map, object, size, visitor);
178   return size;
179 }
180 
181 template <typename ConcreteVisitor>
VisitNativeContext(Map * map,Context * object)182 int NewSpaceVisitor<ConcreteVisitor>::VisitNativeContext(Map* map,
183                                                          Context* object) {
184   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
185   int size = Context::BodyDescriptor::SizeOf(map, object);
186   Context::BodyDescriptor::IterateBody(map, object, size, visitor);
187   return size;
188 }
189 
190 template <typename ConcreteVisitor>
VisitJSApiObject(Map * map,JSObject * object)191 int NewSpaceVisitor<ConcreteVisitor>::VisitJSApiObject(Map* map,
192                                                        JSObject* object) {
193   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
194   return visitor->VisitJSObject(map, object);
195 }
196 
197 template <typename ResultType, typename ConcreteVisitor>
VisitWeakArray(Map * map,HeapObject * object)198 ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitWeakArray(
199     Map* map, HeapObject* object) {
200   ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
201   if (!visitor->ShouldVisit(object)) return ResultType();
202   int size = WeakArrayBodyDescriptor::SizeOf(map, object);
203   if (visitor->ShouldVisitMapPointer())
204     visitor->VisitMapPointer(object, object->map_slot());
205   WeakArrayBodyDescriptor::IterateBody(map, object, size, visitor);
206   return size;
207 }
208 
209 }  // namespace internal
210 }  // namespace v8
211 
212 #endif  // V8_HEAP_OBJECTS_VISITING_INL_H_
213