OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_OBJECTS_VISITING_H_ | 5 #ifndef V8_OBJECTS_VISITING_H_ |
6 #define V8_OBJECTS_VISITING_H_ | 6 #define V8_OBJECTS_VISITING_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 | 9 |
10 // This file provides base classes and auxiliary methods for defining | 10 // This file provides base classes and auxiliary methods for defining |
11 // static object visitors used during GC. | 11 // static object visitors used during GC. |
12 // Visiting HeapObject body with a normal ObjectVisitor requires performing | 12 // Visiting HeapObject body with a normal ObjectVisitor requires performing |
13 // two switches on object's instance type to determine object size and layout | 13 // two switches on object's instance type to determine object size and layout |
14 // and one or more virtual method calls on visitor itself. | 14 // and one or more virtual method calls on visitor itself. |
15 // Static visitor is different: it provides a dispatch table which contains | 15 // Static visitor is different: it provides a dispatch table which contains |
16 // pointers to specialized visit functions. Each map has the visitor_id | 16 // pointers to specialized visit functions. Each map has the visitor_id |
17 // field which contains an index of specialized visitor to use. | 17 // field which contains an index of specialized visitor to use. |
18 | 18 |
19 namespace v8 { | 19 namespace v8 { |
20 namespace internal { | 20 namespace internal { |
21 | 21 |
22 | 22 |
23 // Base class for all static visitors. | 23 // Base class for all static visitors. |
24 class StaticVisitorBase : public AllStatic { | 24 class StaticVisitorBase : public AllStatic { |
25 public: | 25 public: |
26 #define VISITOR_ID_LIST(V) \ | 26 #define VISITOR_ID_LIST(V) \ |
27 V(SeqOneByteString) \ | 27 V(SeqOneByteString) \ |
28 V(SeqTwoByteString) \ | 28 V(SeqTwoByteString) \ |
29 V(ShortcutCandidate) \ | 29 V(ShortcutCandidate) \ |
30 V(ByteArray) \ | 30 V(ByteArray) \ |
31 V(FreeSpace) \ | 31 V(FreeSpace) \ |
32 V(FixedArray) \ | 32 V(FixedArray) \ |
33 V(FixedDoubleArray) \ | 33 V(FixedDoubleArray) \ |
34 V(FixedTypedArray) \ | 34 V(FixedTypedArray) \ |
35 V(FixedFloat64Array) \ | 35 V(FixedFloat64Array) \ |
36 V(ConstantPoolArray) \ | 36 V(ConstantPoolArray) \ |
37 V(NativeContext) \ | 37 V(NativeContext) \ |
38 V(AllocationSite) \ | 38 V(AllocationSite) \ |
39 V(DataObject2) \ | 39 V(DataObject2) \ |
40 V(DataObject3) \ | 40 V(DataObject3) \ |
41 V(DataObject4) \ | 41 V(DataObject4) \ |
42 V(DataObject5) \ | 42 V(DataObject5) \ |
43 V(DataObject6) \ | 43 V(DataObject6) \ |
44 V(DataObject7) \ | 44 V(DataObject7) \ |
45 V(DataObject8) \ | 45 V(DataObject8) \ |
46 V(DataObject9) \ | 46 V(DataObject9) \ |
47 V(DataObjectGeneric) \ | 47 V(DataObjectGeneric) \ |
48 V(JSObject2) \ | 48 V(JSObject2) \ |
49 V(JSObject3) \ | 49 V(JSObject3) \ |
50 V(JSObject4) \ | 50 V(JSObject4) \ |
51 V(JSObject5) \ | 51 V(JSObject5) \ |
52 V(JSObject6) \ | 52 V(JSObject6) \ |
53 V(JSObject7) \ | 53 V(JSObject7) \ |
54 V(JSObject8) \ | 54 V(JSObject8) \ |
55 V(JSObject9) \ | 55 V(JSObject9) \ |
56 V(JSObjectGeneric) \ | 56 V(JSObjectGeneric) \ |
57 V(Struct2) \ | 57 V(Struct2) \ |
58 V(Struct3) \ | 58 V(Struct3) \ |
59 V(Struct4) \ | 59 V(Struct4) \ |
60 V(Struct5) \ | 60 V(Struct5) \ |
61 V(Struct6) \ | 61 V(Struct6) \ |
62 V(Struct7) \ | 62 V(Struct7) \ |
63 V(Struct8) \ | 63 V(Struct8) \ |
64 V(Struct9) \ | 64 V(Struct9) \ |
65 V(StructGeneric) \ | 65 V(StructGeneric) \ |
66 V(ConsString) \ | 66 V(ConsString) \ |
67 V(SlicedString) \ | 67 V(SlicedString) \ |
68 V(Symbol) \ | 68 V(Symbol) \ |
69 V(Oddball) \ | 69 V(Oddball) \ |
70 V(Code) \ | 70 V(Code) \ |
71 V(Map) \ | 71 V(Map) \ |
72 V(Cell) \ | 72 V(Cell) \ |
73 V(PropertyCell) \ | 73 V(PropertyCell) \ |
74 V(SharedFunctionInfo) \ | 74 V(SharedFunctionInfo) \ |
75 V(JSFunction) \ | 75 V(JSFunction) \ |
76 V(JSWeakCollection) \ | 76 V(JSWeakCollection) \ |
77 V(JSArrayBuffer) \ | 77 V(JSArrayBuffer) \ |
78 V(JSTypedArray) \ | 78 V(JSTypedArray) \ |
79 V(JSDataView) \ | 79 V(JSDataView) \ |
80 V(JSRegExp) | 80 V(JSRegExp) |
81 | 81 |
82 // For data objects, JS objects and structs along with generic visitor which | 82 // For data objects, JS objects and structs along with generic visitor which |
83 // can visit object of any size we provide visitors specialized by | 83 // can visit object of any size we provide visitors specialized by |
84 // object size in words. | 84 // object size in words. |
85 // Ids of specialized visitors are declared in a linear order (without | 85 // Ids of specialized visitors are declared in a linear order (without |
86 // holes) starting from the id of visitor specialized for 2 words objects | 86 // holes) starting from the id of visitor specialized for 2 words objects |
87 // (base visitor id) and ending with the id of generic visitor. | 87 // (base visitor id) and ending with the id of generic visitor. |
88 // Method GetVisitorIdForSize depends on this ordering to calculate visitor | 88 // Method GetVisitorIdForSize depends on this ordering to calculate visitor |
89 // id of specialized visitor from given instance size, base visitor id and | 89 // id of specialized visitor from given instance size, base visitor id and |
90 // generic visitor's id. | 90 // generic visitor's id. |
91 enum VisitorId { | 91 enum VisitorId { |
92 #define VISITOR_ID_ENUM_DECL(id) kVisit##id, | 92 #define VISITOR_ID_ENUM_DECL(id) kVisit##id, |
93 VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) | 93 VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) |
94 #undef VISITOR_ID_ENUM_DECL | 94 #undef VISITOR_ID_ENUM_DECL |
95 kVisitorIdCount, | 95 kVisitorIdCount, |
96 kVisitDataObject = kVisitDataObject2, | 96 kVisitDataObject = kVisitDataObject2, |
97 kVisitJSObject = kVisitJSObject2, | 97 kVisitJSObject = kVisitJSObject2, |
98 kVisitStruct = kVisitStruct2, | 98 kVisitStruct = kVisitStruct2, |
99 kMinObjectSizeInWords = 2 | 99 kMinObjectSizeInWords = 2 |
100 }; | 100 }; |
101 | 101 |
102 // Visitor ID should fit in one byte. | 102 // Visitor ID should fit in one byte. |
103 STATIC_ASSERT(kVisitorIdCount <= 256); | 103 STATIC_ASSERT(kVisitorIdCount <= 256); |
104 | 104 |
105 // Determine which specialized visitor should be used for given instance type | 105 // Determine which specialized visitor should be used for given instance type |
106 // and instance type. | 106 // and instance type. |
107 static VisitorId GetVisitorId(int instance_type, int instance_size); | 107 static VisitorId GetVisitorId(int instance_type, int instance_size); |
108 | 108 |
109 static VisitorId GetVisitorId(Map* map) { | 109 static VisitorId GetVisitorId(Map* map) { |
110 return GetVisitorId(map->instance_type(), map->instance_size()); | 110 return GetVisitorId(map->instance_type(), map->instance_size()); |
111 } | 111 } |
112 | 112 |
113 // For visitors that allow specialization by size calculate VisitorId based | 113 // For visitors that allow specialization by size calculate VisitorId based |
114 // on size, base visitor id and generic visitor id. | 114 // on size, base visitor id and generic visitor id. |
115 static VisitorId GetVisitorIdForSize(VisitorId base, | 115 static VisitorId GetVisitorIdForSize(VisitorId base, VisitorId generic, |
116 VisitorId generic, | |
117 int object_size) { | 116 int object_size) { |
118 DCHECK((base == kVisitDataObject) || | 117 DCHECK((base == kVisitDataObject) || (base == kVisitStruct) || |
119 (base == kVisitStruct) || | |
120 (base == kVisitJSObject)); | 118 (base == kVisitJSObject)); |
121 DCHECK(IsAligned(object_size, kPointerSize)); | 119 DCHECK(IsAligned(object_size, kPointerSize)); |
122 DCHECK(kMinObjectSizeInWords * kPointerSize <= object_size); | 120 DCHECK(kMinObjectSizeInWords * kPointerSize <= object_size); |
123 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); | 121 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); |
124 | 122 |
125 const VisitorId specialization = static_cast<VisitorId>( | 123 const VisitorId specialization = static_cast<VisitorId>( |
126 base + (object_size >> kPointerSizeLog2) - kMinObjectSizeInWords); | 124 base + (object_size >> kPointerSizeLog2) - kMinObjectSizeInWords); |
127 | 125 |
128 return Min(specialization, generic); | 126 return Min(specialization, generic); |
129 } | 127 } |
130 }; | 128 }; |
131 | 129 |
132 | 130 |
133 template<typename Callback> | 131 template <typename Callback> |
134 class VisitorDispatchTable { | 132 class VisitorDispatchTable { |
135 public: | 133 public: |
136 void CopyFrom(VisitorDispatchTable* other) { | 134 void CopyFrom(VisitorDispatchTable* other) { |
137 // We are not using memcpy to guarantee that during update | 135 // We are not using memcpy to guarantee that during update |
138 // every element of callbacks_ array will remain correct | 136 // every element of callbacks_ array will remain correct |
139 // pointer (memcpy might be implemented as a byte copying loop). | 137 // pointer (memcpy might be implemented as a byte copying loop). |
140 for (int i = 0; i < StaticVisitorBase::kVisitorIdCount; i++) { | 138 for (int i = 0; i < StaticVisitorBase::kVisitorIdCount; i++) { |
141 base::NoBarrier_Store(&callbacks_[i], other->callbacks_[i]); | 139 base::NoBarrier_Store(&callbacks_[i], other->callbacks_[i]); |
142 } | 140 } |
143 } | 141 } |
144 | 142 |
145 inline Callback GetVisitorById(StaticVisitorBase::VisitorId id) { | 143 inline Callback GetVisitorById(StaticVisitorBase::VisitorId id) { |
146 return reinterpret_cast<Callback>(callbacks_[id]); | 144 return reinterpret_cast<Callback>(callbacks_[id]); |
147 } | 145 } |
148 | 146 |
149 inline Callback GetVisitor(Map* map) { | 147 inline Callback GetVisitor(Map* map) { |
150 return reinterpret_cast<Callback>(callbacks_[map->visitor_id()]); | 148 return reinterpret_cast<Callback>(callbacks_[map->visitor_id()]); |
151 } | 149 } |
152 | 150 |
153 void Register(StaticVisitorBase::VisitorId id, Callback callback) { | 151 void Register(StaticVisitorBase::VisitorId id, Callback callback) { |
154 DCHECK(id < StaticVisitorBase::kVisitorIdCount); // id is unsigned. | 152 DCHECK(id < StaticVisitorBase::kVisitorIdCount); // id is unsigned. |
155 callbacks_[id] = reinterpret_cast<base::AtomicWord>(callback); | 153 callbacks_[id] = reinterpret_cast<base::AtomicWord>(callback); |
156 } | 154 } |
157 | 155 |
158 template<typename Visitor, | 156 template <typename Visitor, StaticVisitorBase::VisitorId base, |
159 StaticVisitorBase::VisitorId base, | 157 StaticVisitorBase::VisitorId generic, int object_size_in_words> |
160 StaticVisitorBase::VisitorId generic, | |
161 int object_size_in_words> | |
162 void RegisterSpecialization() { | 158 void RegisterSpecialization() { |
163 static const int size = object_size_in_words * kPointerSize; | 159 static const int size = object_size_in_words * kPointerSize; |
164 Register(StaticVisitorBase::GetVisitorIdForSize(base, generic, size), | 160 Register(StaticVisitorBase::GetVisitorIdForSize(base, generic, size), |
165 &Visitor::template VisitSpecialized<size>); | 161 &Visitor::template VisitSpecialized<size>); |
166 } | 162 } |
167 | 163 |
168 | 164 |
169 template<typename Visitor, | 165 template <typename Visitor, StaticVisitorBase::VisitorId base, |
170 StaticVisitorBase::VisitorId base, | 166 StaticVisitorBase::VisitorId generic> |
171 StaticVisitorBase::VisitorId generic> | |
172 void RegisterSpecializations() { | 167 void RegisterSpecializations() { |
173 STATIC_ASSERT( | 168 STATIC_ASSERT((generic - base + StaticVisitorBase::kMinObjectSizeInWords) == |
174 (generic - base + StaticVisitorBase::kMinObjectSizeInWords) == 10); | 169 10); |
175 RegisterSpecialization<Visitor, base, generic, 2>(); | 170 RegisterSpecialization<Visitor, base, generic, 2>(); |
176 RegisterSpecialization<Visitor, base, generic, 3>(); | 171 RegisterSpecialization<Visitor, base, generic, 3>(); |
177 RegisterSpecialization<Visitor, base, generic, 4>(); | 172 RegisterSpecialization<Visitor, base, generic, 4>(); |
178 RegisterSpecialization<Visitor, base, generic, 5>(); | 173 RegisterSpecialization<Visitor, base, generic, 5>(); |
179 RegisterSpecialization<Visitor, base, generic, 6>(); | 174 RegisterSpecialization<Visitor, base, generic, 6>(); |
180 RegisterSpecialization<Visitor, base, generic, 7>(); | 175 RegisterSpecialization<Visitor, base, generic, 7>(); |
181 RegisterSpecialization<Visitor, base, generic, 8>(); | 176 RegisterSpecialization<Visitor, base, generic, 8>(); |
182 RegisterSpecialization<Visitor, base, generic, 9>(); | 177 RegisterSpecialization<Visitor, base, generic, 9>(); |
183 Register(generic, &Visitor::Visit); | 178 Register(generic, &Visitor::Visit); |
184 } | 179 } |
185 | 180 |
186 private: | 181 private: |
187 base::AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount]; | 182 base::AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount]; |
188 }; | 183 }; |
189 | 184 |
190 | 185 |
191 template<typename StaticVisitor> | 186 template <typename StaticVisitor> |
192 class BodyVisitorBase : public AllStatic { | 187 class BodyVisitorBase : public AllStatic { |
193 public: | 188 public: |
194 INLINE(static void IteratePointers(Heap* heap, | 189 INLINE(static void IteratePointers(Heap* heap, HeapObject* object, |
195 HeapObject* object, | 190 int start_offset, int end_offset)) { |
196 int start_offset, | 191 Object** start_slot = |
197 int end_offset)) { | 192 reinterpret_cast<Object**>(object->address() + start_offset); |
198 Object** start_slot = reinterpret_cast<Object**>(object->address() + | 193 Object** end_slot = |
199 start_offset); | 194 reinterpret_cast<Object**>(object->address() + end_offset); |
200 Object** end_slot = reinterpret_cast<Object**>(object->address() + | |
201 end_offset); | |
202 StaticVisitor::VisitPointers(heap, start_slot, end_slot); | 195 StaticVisitor::VisitPointers(heap, start_slot, end_slot); |
203 } | 196 } |
204 }; | 197 }; |
205 | 198 |
206 | 199 |
207 template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType> | 200 template <typename StaticVisitor, typename BodyDescriptor, typename ReturnType> |
208 class FlexibleBodyVisitor : public BodyVisitorBase<StaticVisitor> { | 201 class FlexibleBodyVisitor : public BodyVisitorBase<StaticVisitor> { |
209 public: | 202 public: |
210 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { | 203 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { |
211 int object_size = BodyDescriptor::SizeOf(map, object); | 204 int object_size = BodyDescriptor::SizeOf(map, object); |
212 BodyVisitorBase<StaticVisitor>::IteratePointers( | 205 BodyVisitorBase<StaticVisitor>::IteratePointers( |
213 map->GetHeap(), | 206 map->GetHeap(), object, BodyDescriptor::kStartOffset, object_size); |
214 object, | |
215 BodyDescriptor::kStartOffset, | |
216 object_size); | |
217 return static_cast<ReturnType>(object_size); | 207 return static_cast<ReturnType>(object_size); |
218 } | 208 } |
219 | 209 |
220 template<int object_size> | 210 template <int object_size> |
221 static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) { | 211 static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) { |
222 DCHECK(BodyDescriptor::SizeOf(map, object) == object_size); | 212 DCHECK(BodyDescriptor::SizeOf(map, object) == object_size); |
223 BodyVisitorBase<StaticVisitor>::IteratePointers( | 213 BodyVisitorBase<StaticVisitor>::IteratePointers( |
224 map->GetHeap(), | 214 map->GetHeap(), object, BodyDescriptor::kStartOffset, object_size); |
225 object, | |
226 BodyDescriptor::kStartOffset, | |
227 object_size); | |
228 return static_cast<ReturnType>(object_size); | 215 return static_cast<ReturnType>(object_size); |
229 } | 216 } |
230 }; | 217 }; |
231 | 218 |
232 | 219 |
233 template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType> | 220 template <typename StaticVisitor, typename BodyDescriptor, typename ReturnType> |
234 class FixedBodyVisitor : public BodyVisitorBase<StaticVisitor> { | 221 class FixedBodyVisitor : public BodyVisitorBase<StaticVisitor> { |
235 public: | 222 public: |
236 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { | 223 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { |
237 BodyVisitorBase<StaticVisitor>::IteratePointers( | 224 BodyVisitorBase<StaticVisitor>::IteratePointers( |
238 map->GetHeap(), | 225 map->GetHeap(), object, BodyDescriptor::kStartOffset, |
239 object, | |
240 BodyDescriptor::kStartOffset, | |
241 BodyDescriptor::kEndOffset); | 226 BodyDescriptor::kEndOffset); |
242 return static_cast<ReturnType>(BodyDescriptor::kSize); | 227 return static_cast<ReturnType>(BodyDescriptor::kSize); |
243 } | 228 } |
244 }; | 229 }; |
245 | 230 |
246 | 231 |
247 // Base class for visitors used for a linear new space iteration. | 232 // Base class for visitors used for a linear new space iteration. |
248 // IterateBody returns size of visited object. | 233 // IterateBody returns size of visited object. |
249 // Certain types of objects (i.e. Code objects) are not handled | 234 // Certain types of objects (i.e. Code objects) are not handled |
250 // by dispatch table of this visitor because they cannot appear | 235 // by dispatch table of this visitor because they cannot appear |
251 // in the new space. | 236 // in the new space. |
252 // | 237 // |
253 // This class is intended to be used in the following way: | 238 // This class is intended to be used in the following way: |
254 // | 239 // |
255 // class SomeVisitor : public StaticNewSpaceVisitor<SomeVisitor> { | 240 // class SomeVisitor : public StaticNewSpaceVisitor<SomeVisitor> { |
256 // ... | 241 // ... |
257 // } | 242 // } |
258 // | 243 // |
259 // This is an example of Curiously recurring template pattern | 244 // This is an example of Curiously recurring template pattern |
260 // (see http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). | 245 // (see http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). |
261 // We use CRTP to guarantee aggressive compile time optimizations (i.e. | 246 // We use CRTP to guarantee aggressive compile time optimizations (i.e. |
262 // inlining and specialization of StaticVisitor::VisitPointers methods). | 247 // inlining and specialization of StaticVisitor::VisitPointers methods). |
263 template<typename StaticVisitor> | 248 template <typename StaticVisitor> |
264 class StaticNewSpaceVisitor : public StaticVisitorBase { | 249 class StaticNewSpaceVisitor : public StaticVisitorBase { |
265 public: | 250 public: |
266 static void Initialize(); | 251 static void Initialize(); |
267 | 252 |
268 INLINE(static int IterateBody(Map* map, HeapObject* obj)) { | 253 INLINE(static int IterateBody(Map* map, HeapObject* obj)) { |
269 return table_.GetVisitor(map)(map, obj); | 254 return table_.GetVisitor(map)(map, obj); |
270 } | 255 } |
271 | 256 |
272 INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { | 257 INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { |
273 for (Object** p = start; p < end; p++) StaticVisitor::VisitPointer(heap, p); | 258 for (Object** p = start; p < end; p++) StaticVisitor::VisitPointer(heap, p); |
274 } | 259 } |
275 | 260 |
276 private: | 261 private: |
277 INLINE(static int VisitJSFunction(Map* map, HeapObject* object)) { | 262 INLINE(static int VisitJSFunction(Map* map, HeapObject* object)) { |
278 Heap* heap = map->GetHeap(); | 263 Heap* heap = map->GetHeap(); |
279 VisitPointers(heap, | 264 VisitPointers(heap, |
280 HeapObject::RawField(object, JSFunction::kPropertiesOffset), | 265 HeapObject::RawField(object, JSFunction::kPropertiesOffset), |
281 HeapObject::RawField(object, JSFunction::kCodeEntryOffset)); | 266 HeapObject::RawField(object, JSFunction::kCodeEntryOffset)); |
282 | 267 |
283 // Don't visit code entry. We are using this visitor only during scavenges. | 268 // Don't visit code entry. We are using this visitor only during scavenges. |
284 | 269 |
285 VisitPointers( | 270 VisitPointers( |
286 heap, | 271 heap, HeapObject::RawField(object, |
287 HeapObject::RawField(object, | 272 JSFunction::kCodeEntryOffset + kPointerSize), |
288 JSFunction::kCodeEntryOffset + kPointerSize), | 273 HeapObject::RawField(object, JSFunction::kNonWeakFieldsEndOffset)); |
289 HeapObject::RawField(object, | |
290 JSFunction::kNonWeakFieldsEndOffset)); | |
291 return JSFunction::kSize; | 274 return JSFunction::kSize; |
292 } | 275 } |
293 | 276 |
294 INLINE(static int VisitByteArray(Map* map, HeapObject* object)) { | 277 INLINE(static int VisitByteArray(Map* map, HeapObject* object)) { |
295 return reinterpret_cast<ByteArray*>(object)->ByteArraySize(); | 278 return reinterpret_cast<ByteArray*>(object)->ByteArraySize(); |
296 } | 279 } |
297 | 280 |
298 INLINE(static int VisitFixedDoubleArray(Map* map, HeapObject* object)) { | 281 INLINE(static int VisitFixedDoubleArray(Map* map, HeapObject* object)) { |
299 int length = reinterpret_cast<FixedDoubleArray*>(object)->length(); | 282 int length = reinterpret_cast<FixedDoubleArray*>(object)->length(); |
300 return FixedDoubleArray::SizeFor(length); | 283 return FixedDoubleArray::SizeFor(length); |
301 } | 284 } |
302 | 285 |
303 INLINE(static int VisitFixedTypedArray(Map* map, HeapObject* object)) { | 286 INLINE(static int VisitFixedTypedArray(Map* map, HeapObject* object)) { |
304 return reinterpret_cast<FixedTypedArrayBase*>(object)->size(); | 287 return reinterpret_cast<FixedTypedArrayBase*>(object)->size(); |
305 } | 288 } |
306 | 289 |
307 INLINE(static int VisitJSObject(Map* map, HeapObject* object)) { | 290 INLINE(static int VisitJSObject(Map* map, HeapObject* object)) { |
308 return JSObjectVisitor::Visit(map, object); | 291 return JSObjectVisitor::Visit(map, object); |
309 } | 292 } |
310 | 293 |
311 INLINE(static int VisitSeqOneByteString(Map* map, HeapObject* object)) { | 294 INLINE(static int VisitSeqOneByteString(Map* map, HeapObject* object)) { |
312 return SeqOneByteString::cast(object)-> | 295 return SeqOneByteString::cast(object) |
313 SeqOneByteStringSize(map->instance_type()); | 296 ->SeqOneByteStringSize(map->instance_type()); |
314 } | 297 } |
315 | 298 |
316 INLINE(static int VisitSeqTwoByteString(Map* map, HeapObject* object)) { | 299 INLINE(static int VisitSeqTwoByteString(Map* map, HeapObject* object)) { |
317 return SeqTwoByteString::cast(object)-> | 300 return SeqTwoByteString::cast(object) |
318 SeqTwoByteStringSize(map->instance_type()); | 301 ->SeqTwoByteStringSize(map->instance_type()); |
319 } | 302 } |
320 | 303 |
321 INLINE(static int VisitFreeSpace(Map* map, HeapObject* object)) { | 304 INLINE(static int VisitFreeSpace(Map* map, HeapObject* object)) { |
322 return FreeSpace::cast(object)->Size(); | 305 return FreeSpace::cast(object)->Size(); |
323 } | 306 } |
324 | 307 |
325 INLINE(static int VisitJSArrayBuffer(Map* map, HeapObject* object)); | 308 INLINE(static int VisitJSArrayBuffer(Map* map, HeapObject* object)); |
326 INLINE(static int VisitJSTypedArray(Map* map, HeapObject* object)); | 309 INLINE(static int VisitJSTypedArray(Map* map, HeapObject* object)); |
327 INLINE(static int VisitJSDataView(Map* map, HeapObject* object)); | 310 INLINE(static int VisitJSDataView(Map* map, HeapObject* object)); |
328 | 311 |
329 class DataObjectVisitor { | 312 class DataObjectVisitor { |
330 public: | 313 public: |
331 template<int object_size> | 314 template <int object_size> |
332 static inline int VisitSpecialized(Map* map, HeapObject* object) { | 315 static inline int VisitSpecialized(Map* map, HeapObject* object) { |
333 return object_size; | 316 return object_size; |
334 } | 317 } |
335 | 318 |
336 INLINE(static int Visit(Map* map, HeapObject* object)) { | 319 INLINE(static int Visit(Map* map, HeapObject* object)) { |
337 return map->instance_size(); | 320 return map->instance_size(); |
338 } | 321 } |
339 }; | 322 }; |
340 | 323 |
341 typedef FlexibleBodyVisitor<StaticVisitor, | 324 typedef FlexibleBodyVisitor<StaticVisitor, StructBodyDescriptor, int> |
342 StructBodyDescriptor, | 325 StructVisitor; |
343 int> StructVisitor; | |
344 | 326 |
345 typedef FlexibleBodyVisitor<StaticVisitor, | 327 typedef FlexibleBodyVisitor<StaticVisitor, JSObject::BodyDescriptor, int> |
346 JSObject::BodyDescriptor, | 328 JSObjectVisitor; |
347 int> JSObjectVisitor; | |
348 | 329 |
349 typedef int (*Callback)(Map* map, HeapObject* object); | 330 typedef int (*Callback)(Map* map, HeapObject* object); |
350 | 331 |
351 static VisitorDispatchTable<Callback> table_; | 332 static VisitorDispatchTable<Callback> table_; |
352 }; | 333 }; |
353 | 334 |
354 | 335 |
355 template<typename StaticVisitor> | 336 template <typename StaticVisitor> |
356 VisitorDispatchTable<typename StaticNewSpaceVisitor<StaticVisitor>::Callback> | 337 VisitorDispatchTable<typename StaticNewSpaceVisitor<StaticVisitor>::Callback> |
357 StaticNewSpaceVisitor<StaticVisitor>::table_; | 338 StaticNewSpaceVisitor<StaticVisitor>::table_; |
358 | 339 |
359 | 340 |
360 // Base class for visitors used to transitively mark the entire heap. | 341 // Base class for visitors used to transitively mark the entire heap. |
361 // IterateBody returns nothing. | 342 // IterateBody returns nothing. |
362 // Certain types of objects might not be handled by this base class and | 343 // Certain types of objects might not be handled by this base class and |
363 // no visitor function is registered by the generic initialization. A | 344 // no visitor function is registered by the generic initialization. A |
364 // specialized visitor function needs to be provided by the inheriting | 345 // specialized visitor function needs to be provided by the inheriting |
365 // class itself for those cases. | 346 // class itself for those cases. |
366 // | 347 // |
367 // This class is intended to be used in the following way: | 348 // This class is intended to be used in the following way: |
368 // | 349 // |
369 // class SomeVisitor : public StaticMarkingVisitor<SomeVisitor> { | 350 // class SomeVisitor : public StaticMarkingVisitor<SomeVisitor> { |
370 // ... | 351 // ... |
371 // } | 352 // } |
372 // | 353 // |
373 // This is an example of Curiously recurring template pattern. | 354 // This is an example of Curiously recurring template pattern. |
374 template<typename StaticVisitor> | 355 template <typename StaticVisitor> |
375 class StaticMarkingVisitor : public StaticVisitorBase { | 356 class StaticMarkingVisitor : public StaticVisitorBase { |
376 public: | 357 public: |
377 static void Initialize(); | 358 static void Initialize(); |
378 | 359 |
379 INLINE(static void IterateBody(Map* map, HeapObject* obj)) { | 360 INLINE(static void IterateBody(Map* map, HeapObject* obj)) { |
380 table_.GetVisitor(map)(map, obj); | 361 table_.GetVisitor(map)(map, obj); |
381 } | 362 } |
382 | 363 |
383 INLINE(static void VisitPropertyCell(Map* map, HeapObject* object)); | 364 INLINE(static void VisitPropertyCell(Map* map, HeapObject* object)); |
384 INLINE(static void VisitCodeEntry(Heap* heap, Address entry_address)); | 365 INLINE(static void VisitCodeEntry(Heap* heap, Address entry_address)); |
385 INLINE(static void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo)); | 366 INLINE(static void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo)); |
386 INLINE(static void VisitCell(Heap* heap, RelocInfo* rinfo)); | 367 INLINE(static void VisitCell(Heap* heap, RelocInfo* rinfo)); |
387 INLINE(static void VisitDebugTarget(Heap* heap, RelocInfo* rinfo)); | 368 INLINE(static void VisitDebugTarget(Heap* heap, RelocInfo* rinfo)); |
388 INLINE(static void VisitCodeTarget(Heap* heap, RelocInfo* rinfo)); | 369 INLINE(static void VisitCodeTarget(Heap* heap, RelocInfo* rinfo)); |
389 INLINE(static void VisitCodeAgeSequence(Heap* heap, RelocInfo* rinfo)); | 370 INLINE(static void VisitCodeAgeSequence(Heap* heap, RelocInfo* rinfo)); |
390 INLINE(static void VisitExternalReference(RelocInfo* rinfo)) { } | 371 INLINE(static void VisitExternalReference(RelocInfo* rinfo)) {} |
391 INLINE(static void VisitRuntimeEntry(RelocInfo* rinfo)) { } | 372 INLINE(static void VisitRuntimeEntry(RelocInfo* rinfo)) {} |
392 // Skip the weak next code link in a code object. | 373 // Skip the weak next code link in a code object. |
393 INLINE(static void VisitNextCodeLink(Heap* heap, Object** slot)) { } | 374 INLINE(static void VisitNextCodeLink(Heap* heap, Object** slot)) {} |
394 | 375 |
395 // TODO(mstarzinger): This should be made protected once refactoring is done. | 376 // TODO(mstarzinger): This should be made protected once refactoring is done. |
396 // Mark non-optimize code for functions inlined into the given optimized | 377 // Mark non-optimize code for functions inlined into the given optimized |
397 // code. This will prevent it from being flushed. | 378 // code. This will prevent it from being flushed. |
398 static void MarkInlinedFunctionsCode(Heap* heap, Code* code); | 379 static void MarkInlinedFunctionsCode(Heap* heap, Code* code); |
399 | 380 |
400 protected: | 381 protected: |
401 INLINE(static void VisitMap(Map* map, HeapObject* object)); | 382 INLINE(static void VisitMap(Map* map, HeapObject* object)); |
402 INLINE(static void VisitCode(Map* map, HeapObject* object)); | 383 INLINE(static void VisitCode(Map* map, HeapObject* object)); |
403 INLINE(static void VisitSharedFunctionInfo(Map* map, HeapObject* object)); | 384 INLINE(static void VisitSharedFunctionInfo(Map* map, HeapObject* object)); |
(...skipping 18 matching lines...) Expand all Loading... |
422 | 403 |
423 // Helpers used by code flushing support that visit pointer fields and treat | 404 // Helpers used by code flushing support that visit pointer fields and treat |
424 // references to code objects either strongly or weakly. | 405 // references to code objects either strongly or weakly. |
425 static void VisitSharedFunctionInfoStrongCode(Heap* heap, HeapObject* object); | 406 static void VisitSharedFunctionInfoStrongCode(Heap* heap, HeapObject* object); |
426 static void VisitSharedFunctionInfoWeakCode(Heap* heap, HeapObject* object); | 407 static void VisitSharedFunctionInfoWeakCode(Heap* heap, HeapObject* object); |
427 static void VisitJSFunctionStrongCode(Heap* heap, HeapObject* object); | 408 static void VisitJSFunctionStrongCode(Heap* heap, HeapObject* object); |
428 static void VisitJSFunctionWeakCode(Heap* heap, HeapObject* object); | 409 static void VisitJSFunctionWeakCode(Heap* heap, HeapObject* object); |
429 | 410 |
430 class DataObjectVisitor { | 411 class DataObjectVisitor { |
431 public: | 412 public: |
432 template<int size> | 413 template <int size> |
433 static inline void VisitSpecialized(Map* map, HeapObject* object) { | 414 static inline void VisitSpecialized(Map* map, HeapObject* object) {} |
434 } | |
435 | 415 |
436 INLINE(static void Visit(Map* map, HeapObject* object)) { | 416 INLINE(static void Visit(Map* map, HeapObject* object)) {} |
437 } | |
438 }; | 417 }; |
439 | 418 |
440 typedef FlexibleBodyVisitor<StaticVisitor, | 419 typedef FlexibleBodyVisitor<StaticVisitor, FixedArray::BodyDescriptor, void> |
441 FixedArray::BodyDescriptor, | 420 FixedArrayVisitor; |
442 void> FixedArrayVisitor; | |
443 | 421 |
444 typedef FlexibleBodyVisitor<StaticVisitor, | 422 typedef FlexibleBodyVisitor<StaticVisitor, JSObject::BodyDescriptor, void> |
445 JSObject::BodyDescriptor, | 423 JSObjectVisitor; |
446 void> JSObjectVisitor; | |
447 | 424 |
448 typedef FlexibleBodyVisitor<StaticVisitor, | 425 typedef FlexibleBodyVisitor<StaticVisitor, StructBodyDescriptor, void> |
449 StructBodyDescriptor, | 426 StructObjectVisitor; |
450 void> StructObjectVisitor; | |
451 | 427 |
452 typedef void (*Callback)(Map* map, HeapObject* object); | 428 typedef void (*Callback)(Map* map, HeapObject* object); |
453 | 429 |
454 static VisitorDispatchTable<Callback> table_; | 430 static VisitorDispatchTable<Callback> table_; |
455 }; | 431 }; |
456 | 432 |
457 | 433 |
458 template<typename StaticVisitor> | 434 template <typename StaticVisitor> |
459 VisitorDispatchTable<typename StaticMarkingVisitor<StaticVisitor>::Callback> | 435 VisitorDispatchTable<typename StaticMarkingVisitor<StaticVisitor>::Callback> |
460 StaticMarkingVisitor<StaticVisitor>::table_; | 436 StaticMarkingVisitor<StaticVisitor>::table_; |
461 | 437 |
462 | 438 |
463 class WeakObjectRetainer; | 439 class WeakObjectRetainer; |
464 | 440 |
465 | 441 |
466 // A weak list is single linked list where each element has a weak pointer to | 442 // A weak list is single linked list where each element has a weak pointer to |
467 // the next element. Given the head of the list, this function removes dead | 443 // the next element. Given the head of the list, this function removes dead |
468 // elements from the list and if requested records slots for next-element | 444 // elements from the list and if requested records slots for next-element |
469 // pointers. The template parameter T is a WeakListVisitor that defines how to | 445 // pointers. The template parameter T is a WeakListVisitor that defines how to |
470 // access the next-element pointers. | 446 // access the next-element pointers. |
471 template <class T> | 447 template <class T> |
472 Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer); | 448 Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer); |
473 | 449 } |
474 } } // namespace v8::internal | 450 } // namespace v8::internal |
475 | 451 |
476 #endif // V8_OBJECTS_VISITING_H_ | 452 #endif // V8_OBJECTS_VISITING_H_ |
OLD | NEW |