OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #ifndef V8_OBJECTS_VISITING_H_ | 28 #ifndef V8_OBJECTS_VISITING_H_ |
29 #define V8_OBJECTS_VISITING_H_ | 29 #define V8_OBJECTS_VISITING_H_ |
30 | 30 |
31 #include "allocation.h" | 31 #include "allocation.h" |
32 | 32 |
33 #if V8_TARGET_ARCH_IA32 | |
34 #include "ia32/assembler-ia32.h" | |
35 #include "ia32/assembler-ia32-inl.h" | |
36 #elif V8_TARGET_ARCH_X64 | |
37 #include "x64/assembler-x64.h" | |
38 #include "x64/assembler-x64-inl.h" | |
39 #elif V8_TARGET_ARCH_ARM | |
40 #include "arm/assembler-arm.h" | |
41 #include "arm/assembler-arm-inl.h" | |
42 #elif V8_TARGET_ARCH_MIPS | |
43 #include "mips/assembler-mips.h" | |
44 #include "mips/assembler-mips-inl.h" | |
45 #else | |
46 #error Unsupported target architecture. | |
47 #endif | |
48 | |
49 // This file provides base classes and auxiliary methods for defining | 33 // This file provides base classes and auxiliary methods for defining |
50 // static object visitors used during GC. | 34 // static object visitors used during GC. |
51 // Visiting HeapObject body with a normal ObjectVisitor requires performing | 35 // Visiting HeapObject body with a normal ObjectVisitor requires performing |
52 // two switches on object's instance type to determine object size and layout | 36 // two switches on object's instance type to determine object size and layout |
53 // and one or more virtual method calls on visitor itself. | 37 // and one or more virtual method calls on visitor itself. |
54 // Static visitor is different: it provides a dispatch table which contains | 38 // Static visitor is different: it provides a dispatch table which contains |
55 // pointers to specialized visit functions. Each map has the visitor_id | 39 // pointers to specialized visit functions. Each map has the visitor_id |
56 // field which contains an index of specialized visitor to use. | 40 // field which contains an index of specialized visitor to use. |
57 | 41 |
58 namespace v8 { | 42 namespace v8 { |
59 namespace internal { | 43 namespace internal { |
60 | 44 |
61 | 45 |
62 // Base class for all static visitors. | 46 // Base class for all static visitors. |
63 class StaticVisitorBase : public AllStatic { | 47 class StaticVisitorBase : public AllStatic { |
64 public: | 48 public: |
65 enum VisitorId { | 49 enum VisitorId { |
66 kVisitSeqAsciiString = 0, | 50 kVisitSeqAsciiString = 0, |
67 kVisitSeqTwoByteString, | 51 kVisitSeqTwoByteString, |
68 kVisitShortcutCandidate, | 52 kVisitShortcutCandidate, |
69 kVisitByteArray, | 53 kVisitByteArray, |
| 54 kVisitFreeSpace, |
70 kVisitFixedArray, | 55 kVisitFixedArray, |
71 kVisitFixedDoubleArray, | 56 kVisitFixedDoubleArray, |
72 kVisitGlobalContext, | 57 kVisitGlobalContext, |
73 | 58 |
74 // For data objects, JS objects and structs along with generic visitor which | 59 // For data objects, JS objects and structs along with generic visitor which |
75 // can visit object of any size we provide visitors specialized by | 60 // can visit object of any size we provide visitors specialized by |
76 // object size in words. | 61 // object size in words. |
77 // Ids of specialized visitors are declared in a linear order (without | 62 // Ids of specialized visitors are declared in a linear order (without |
78 // holes) starting from the id of visitor specialized for 2 words objects | 63 // holes) starting from the id of visitor specialized for 2 words objects |
79 // (base visitor id) and ending with the id of generic visitor. | 64 // (base visitor id) and ending with the id of generic visitor. |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 } | 214 } |
230 }; | 215 }; |
231 | 216 |
232 | 217 |
233 template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType> | 218 template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType> |
234 class FlexibleBodyVisitor : public BodyVisitorBase<StaticVisitor> { | 219 class FlexibleBodyVisitor : public BodyVisitorBase<StaticVisitor> { |
235 public: | 220 public: |
236 static inline ReturnType Visit(Map* map, HeapObject* object) { | 221 static inline ReturnType Visit(Map* map, HeapObject* object) { |
237 int object_size = BodyDescriptor::SizeOf(map, object); | 222 int object_size = BodyDescriptor::SizeOf(map, object); |
238 BodyVisitorBase<StaticVisitor>::IteratePointers( | 223 BodyVisitorBase<StaticVisitor>::IteratePointers( |
239 map->heap(), | 224 map->GetHeap(), |
240 object, | 225 object, |
241 BodyDescriptor::kStartOffset, | 226 BodyDescriptor::kStartOffset, |
242 object_size); | 227 object_size); |
243 return static_cast<ReturnType>(object_size); | 228 return static_cast<ReturnType>(object_size); |
244 } | 229 } |
245 | 230 |
246 template<int object_size> | 231 template<int object_size> |
247 static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) { | 232 static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) { |
248 ASSERT(BodyDescriptor::SizeOf(map, object) == object_size); | 233 ASSERT(BodyDescriptor::SizeOf(map, object) == object_size); |
249 BodyVisitorBase<StaticVisitor>::IteratePointers( | 234 BodyVisitorBase<StaticVisitor>::IteratePointers( |
250 map->heap(), | 235 map->GetHeap(), |
251 object, | 236 object, |
252 BodyDescriptor::kStartOffset, | 237 BodyDescriptor::kStartOffset, |
253 object_size); | 238 object_size); |
254 return static_cast<ReturnType>(object_size); | 239 return static_cast<ReturnType>(object_size); |
255 } | 240 } |
256 }; | 241 }; |
257 | 242 |
258 | 243 |
259 template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType> | 244 template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType> |
260 class FixedBodyVisitor : public BodyVisitorBase<StaticVisitor> { | 245 class FixedBodyVisitor : public BodyVisitorBase<StaticVisitor> { |
261 public: | 246 public: |
262 static inline ReturnType Visit(Map* map, HeapObject* object) { | 247 static inline ReturnType Visit(Map* map, HeapObject* object) { |
263 BodyVisitorBase<StaticVisitor>::IteratePointers( | 248 BodyVisitorBase<StaticVisitor>::IteratePointers( |
264 map->heap(), | 249 map->GetHeap(), |
265 object, | 250 object, |
266 BodyDescriptor::kStartOffset, | 251 BodyDescriptor::kStartOffset, |
267 BodyDescriptor::kEndOffset); | 252 BodyDescriptor::kEndOffset); |
268 return static_cast<ReturnType>(BodyDescriptor::kSize); | 253 return static_cast<ReturnType>(BodyDescriptor::kSize); |
269 } | 254 } |
270 }; | 255 }; |
271 | 256 |
272 | 257 |
273 // Base class for visitors used for a linear new space iteration. | 258 // Base class for visitors used for a linear new space iteration. |
274 // IterateBody returns size of visited object. | 259 // IterateBody returns size of visited object. |
275 // Certain types of objects (i.e. Code objects) are not handled | 260 // Certain types of objects (i.e. Code objects) are not handled |
276 // by dispatch table of this visitor because they cannot appear | 261 // by dispatch table of this visitor because they cannot appear |
277 // in the new space. | 262 // in the new space. |
278 // | 263 // |
279 // This class is intended to be used in the following way: | 264 // This class is intended to be used in the following way: |
280 // | 265 // |
281 // class SomeVisitor : public StaticNewSpaceVisitor<SomeVisitor> { | 266 // class SomeVisitor : public StaticNewSpaceVisitor<SomeVisitor> { |
282 // ... | 267 // ... |
283 // } | 268 // } |
284 // | 269 // |
285 // This is an example of Curiously recurring template pattern | 270 // This is an example of Curiously recurring template pattern |
286 // (see http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). | 271 // (see http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). |
287 // We use CRTP to guarantee aggressive compile time optimizations (i.e. | 272 // We use CRTP to guarantee aggressive compile time optimizations (i.e. |
288 // inlining and specialization of StaticVisitor::VisitPointers methods). | 273 // inlining and specialization of StaticVisitor::VisitPointers methods). |
289 template<typename StaticVisitor> | 274 template<typename StaticVisitor> |
290 class StaticNewSpaceVisitor : public StaticVisitorBase { | 275 class StaticNewSpaceVisitor : public StaticVisitorBase { |
291 public: | 276 public: |
292 static void Initialize() { | 277 static void Initialize(); |
293 table_.Register(kVisitShortcutCandidate, | |
294 &FixedBodyVisitor<StaticVisitor, | |
295 ConsString::BodyDescriptor, | |
296 int>::Visit); | |
297 | |
298 table_.Register(kVisitConsString, | |
299 &FixedBodyVisitor<StaticVisitor, | |
300 ConsString::BodyDescriptor, | |
301 int>::Visit); | |
302 | |
303 table_.Register(kVisitSlicedString, | |
304 &FixedBodyVisitor<StaticVisitor, | |
305 SlicedString::BodyDescriptor, | |
306 int>::Visit); | |
307 | |
308 table_.Register(kVisitFixedArray, | |
309 &FlexibleBodyVisitor<StaticVisitor, | |
310 FixedArray::BodyDescriptor, | |
311 int>::Visit); | |
312 | |
313 table_.Register(kVisitFixedDoubleArray, &VisitFixedDoubleArray); | |
314 | |
315 table_.Register(kVisitGlobalContext, | |
316 &FixedBodyVisitor<StaticVisitor, | |
317 Context::ScavengeBodyDescriptor, | |
318 int>::Visit); | |
319 | |
320 table_.Register(kVisitByteArray, &VisitByteArray); | |
321 | |
322 table_.Register(kVisitSharedFunctionInfo, | |
323 &FixedBodyVisitor<StaticVisitor, | |
324 SharedFunctionInfo::BodyDescriptor, | |
325 int>::Visit); | |
326 | |
327 table_.Register(kVisitJSWeakMap, &VisitJSObject); | |
328 | |
329 table_.Register(kVisitJSRegExp, &VisitJSObject); | |
330 | |
331 table_.Register(kVisitSeqAsciiString, &VisitSeqAsciiString); | |
332 | |
333 table_.Register(kVisitSeqTwoByteString, &VisitSeqTwoByteString); | |
334 | |
335 table_.Register(kVisitJSFunction, | |
336 &JSObjectVisitor:: | |
337 template VisitSpecialized<JSFunction::kSize>); | |
338 | |
339 table_.RegisterSpecializations<DataObjectVisitor, | |
340 kVisitDataObject, | |
341 kVisitDataObjectGeneric>(); | |
342 table_.RegisterSpecializations<JSObjectVisitor, | |
343 kVisitJSObject, | |
344 kVisitJSObjectGeneric>(); | |
345 table_.RegisterSpecializations<StructVisitor, | |
346 kVisitStruct, | |
347 kVisitStructGeneric>(); | |
348 } | |
349 | 278 |
350 static inline int IterateBody(Map* map, HeapObject* obj) { | 279 static inline int IterateBody(Map* map, HeapObject* obj) { |
351 return table_.GetVisitor(map)(map, obj); | 280 return table_.GetVisitor(map)(map, obj); |
352 } | 281 } |
353 | 282 |
354 static inline void VisitPointers(Heap* heap, Object** start, Object** end) { | 283 static inline void VisitPointers(Heap* heap, Object** start, Object** end) { |
355 for (Object** p = start; p < end; p++) StaticVisitor::VisitPointer(heap, p); | 284 for (Object** p = start; p < end; p++) StaticVisitor::VisitPointer(heap, p); |
356 } | 285 } |
357 | 286 |
358 private: | 287 private: |
(...skipping 13 matching lines...) Expand all Loading... |
372 static inline int VisitSeqAsciiString(Map* map, HeapObject* object) { | 301 static inline int VisitSeqAsciiString(Map* map, HeapObject* object) { |
373 return SeqAsciiString::cast(object)-> | 302 return SeqAsciiString::cast(object)-> |
374 SeqAsciiStringSize(map->instance_type()); | 303 SeqAsciiStringSize(map->instance_type()); |
375 } | 304 } |
376 | 305 |
377 static inline int VisitSeqTwoByteString(Map* map, HeapObject* object) { | 306 static inline int VisitSeqTwoByteString(Map* map, HeapObject* object) { |
378 return SeqTwoByteString::cast(object)-> | 307 return SeqTwoByteString::cast(object)-> |
379 SeqTwoByteStringSize(map->instance_type()); | 308 SeqTwoByteStringSize(map->instance_type()); |
380 } | 309 } |
381 | 310 |
| 311 static inline int VisitFreeSpace(Map* map, HeapObject* object) { |
| 312 return FreeSpace::cast(object)->Size(); |
| 313 } |
| 314 |
382 class DataObjectVisitor { | 315 class DataObjectVisitor { |
383 public: | 316 public: |
384 template<int object_size> | 317 template<int object_size> |
385 static inline int VisitSpecialized(Map* map, HeapObject* object) { | 318 static inline int VisitSpecialized(Map* map, HeapObject* object) { |
386 return object_size; | 319 return object_size; |
387 } | 320 } |
388 | 321 |
389 static inline int Visit(Map* map, HeapObject* object) { | 322 static inline int Visit(Map* map, HeapObject* object) { |
390 return map->instance_size(); | 323 return map->instance_size(); |
391 } | 324 } |
(...skipping 11 matching lines...) Expand all Loading... |
403 | 336 |
404 static VisitorDispatchTable<Callback> table_; | 337 static VisitorDispatchTable<Callback> table_; |
405 }; | 338 }; |
406 | 339 |
407 | 340 |
408 template<typename StaticVisitor> | 341 template<typename StaticVisitor> |
409 VisitorDispatchTable<typename StaticNewSpaceVisitor<StaticVisitor>::Callback> | 342 VisitorDispatchTable<typename StaticNewSpaceVisitor<StaticVisitor>::Callback> |
410 StaticNewSpaceVisitor<StaticVisitor>::table_; | 343 StaticNewSpaceVisitor<StaticVisitor>::table_; |
411 | 344 |
412 | 345 |
413 void Code::CodeIterateBody(ObjectVisitor* v) { | |
414 int mode_mask = RelocInfo::kCodeTargetMask | | |
415 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | |
416 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | | |
417 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | |
418 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | | |
419 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | | |
420 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | |
421 | |
422 // Use the relocation info pointer before it is visited by | |
423 // the heap compaction in the next statement. | |
424 RelocIterator it(this, mode_mask); | |
425 | |
426 IteratePointer(v, kRelocationInfoOffset); | |
427 IteratePointer(v, kDeoptimizationDataOffset); | |
428 | |
429 for (; !it.done(); it.next()) { | |
430 it.rinfo()->Visit(v); | |
431 } | |
432 } | |
433 | |
434 | |
435 template<typename StaticVisitor> | |
436 void Code::CodeIterateBody(Heap* heap) { | |
437 int mode_mask = RelocInfo::kCodeTargetMask | | |
438 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | |
439 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | | |
440 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | |
441 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | | |
442 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | | |
443 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | |
444 | |
445 // Use the relocation info pointer before it is visited by | |
446 // the heap compaction in the next statement. | |
447 RelocIterator it(this, mode_mask); | |
448 | |
449 StaticVisitor::VisitPointer( | |
450 heap, | |
451 reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset)); | |
452 StaticVisitor::VisitPointer( | |
453 heap, | |
454 reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset)); | |
455 | |
456 for (; !it.done(); it.next()) { | |
457 it.rinfo()->template Visit<StaticVisitor>(heap); | |
458 } | |
459 } | |
460 | |
461 | |
462 } } // namespace v8::internal | 346 } } // namespace v8::internal |
463 | 347 |
464 #endif // V8_OBJECTS_VISITING_H_ | 348 #endif // V8_OBJECTS_VISITING_H_ |
OLD | NEW |