Chromium Code Reviews| 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 #include "src/heap/embedder-tracing.h" | 9 #include "src/heap/embedder-tracing.h" |
| 10 #include "src/heap/heap.h" | 10 #include "src/heap/heap.h" |
| 11 #include "src/heap/spaces.h" | 11 #include "src/heap/spaces.h" |
| 12 #include "src/layout-descriptor.h" | 12 #include "src/layout-descriptor.h" |
| 13 #include "src/objects-body-descriptors.h" | 13 #include "src/objects-body-descriptors.h" |
| 14 | 14 |
| 15 // This file provides base classes and auxiliary methods for defining | 15 // This file provides base classes and auxiliary methods for defining |
| 16 // static object visitors used during GC. | 16 // static object visitors used during GC. |
| 17 // Visiting HeapObject body with a normal ObjectVisitor requires performing | 17 // Visiting HeapObject body with a normal ObjectVisitor requires performing |
| 18 // two switches on object's instance type to determine object size and layout | 18 // two switches on object's instance type to determine object size and layout |
| 19 // and one or more virtual method calls on visitor itself. | 19 // and one or more virtual method calls on visitor itself. |
| 20 // Static visitor is different: it provides a dispatch table which contains | 20 // Static visitor is different: it provides a dispatch table which contains |
| 21 // pointers to specialized visit functions. Each map has the visitor_id | 21 // pointers to specialized visit functions. Each map has the visitor_id |
| 22 // field which contains an index of specialized visitor to use. | 22 // field which contains an index of specialized visitor to use. |
| 23 | 23 |
| 24 namespace v8 { | 24 namespace v8 { |
| 25 namespace internal { | 25 namespace internal { |
| 26 | 26 |
| 27 | |
| 28 // Base class for all static visitors. | |
| 29 class StaticVisitorBase : public AllStatic { | |
| 30 public: | |
| 31 #define VISITOR_ID_LIST(V) \ | 27 #define VISITOR_ID_LIST(V) \ |
| 32 V(SeqOneByteString) \ | 28 V(SeqOneByteString) \ |
| 33 V(SeqTwoByteString) \ | 29 V(SeqTwoByteString) \ |
| 34 V(ShortcutCandidate) \ | 30 V(ShortcutCandidate) \ |
| 35 V(ByteArray) \ | 31 V(ByteArray) \ |
| 36 V(BytecodeArray) \ | 32 V(BytecodeArray) \ |
| 37 V(FreeSpace) \ | 33 V(FreeSpace) \ |
| 38 V(FixedArray) \ | 34 V(FixedArray) \ |
| 39 V(FixedDoubleArray) \ | 35 V(FixedDoubleArray) \ |
| 40 V(FixedTypedArray) \ | 36 V(FixedTypedArrayBase) \ |
| 41 V(FixedFloat64Array) \ | 37 V(FixedFloat64Array) \ |
| 42 V(NativeContext) \ | 38 V(NativeContext) \ |
| 43 V(AllocationSite) \ | 39 V(AllocationSite) \ |
| 44 V(DataObject) \ | 40 V(DataObject) \ |
| 45 V(JSObjectFast) \ | 41 V(JSObjectFast) \ |
| 46 V(JSObject) \ | 42 V(JSObject) \ |
| 47 V(JSApiObject) \ | 43 V(JSApiObject) \ |
| 48 V(Struct) \ | 44 V(Struct) \ |
| 49 V(ConsString) \ | 45 V(ConsString) \ |
| 50 V(SlicedString) \ | 46 V(SlicedString) \ |
| 51 V(ThinString) \ | 47 V(ThinString) \ |
| 52 V(Symbol) \ | 48 V(Symbol) \ |
| 53 V(Oddball) \ | 49 V(Oddball) \ |
| 54 V(Code) \ | 50 V(Code) \ |
| 55 V(Map) \ | 51 V(Map) \ |
| 56 V(Cell) \ | 52 V(Cell) \ |
| 57 V(PropertyCell) \ | 53 V(PropertyCell) \ |
| 58 V(WeakCell) \ | 54 V(WeakCell) \ |
| 59 V(TransitionArray) \ | 55 V(TransitionArray) \ |
| 60 V(SharedFunctionInfo) \ | 56 V(SharedFunctionInfo) \ |
| 61 V(JSFunction) \ | 57 V(JSFunction) \ |
| 62 V(JSWeakCollection) \ | 58 V(JSWeakCollection) \ |
| 63 V(JSArrayBuffer) \ | 59 V(JSArrayBuffer) \ |
| 64 V(JSRegExp) | 60 V(JSRegExp) |
| 65 | 61 |
| 66 // For data objects, JS objects and structs along with generic visitor which | 62 // For data objects, JS objects and structs along with generic visitor which |
| 67 // can visit object of any size we provide visitors specialized by | 63 // can visit object of any size we provide visitors specialized by |
| 68 // object size in words. | 64 // object size in words. |
| 69 // Ids of specialized visitors are declared in a linear order (without | 65 // Ids of specialized visitors are declared in a linear order (without |
| 70 // holes) starting from the id of visitor specialized for 2 words objects | 66 // holes) starting from the id of visitor specialized for 2 words objects |
| 71 // (base visitor id) and ending with the id of generic visitor. | 67 // (base visitor id) and ending with the id of generic visitor. |
| 72 // Method GetVisitorIdForSize depends on this ordering to calculate visitor | 68 // Method GetVisitorIdForSize depends on this ordering to calculate visitor |
| 73 // id of specialized visitor from given instance size, base visitor id and | 69 // id of specialized visitor from given instance size, base visitor id and |
| 74 // generic visitor's id. | 70 // generic visitor's id. |
| 75 enum VisitorId { | 71 enum VisitorId { |
| 76 #define VISITOR_ID_ENUM_DECL(id) kVisit##id, | 72 #define VISITOR_ID_ENUM_DECL(id) kVisit##id, |
| 77 VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) | 73 VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) |
| 78 #undef VISITOR_ID_ENUM_DECL | 74 #undef VISITOR_ID_ENUM_DECL |
| 79 kVisitorIdCount | 75 kVisitorIdCount |
| 80 }; | 76 }; |
| 81 | 77 |
| 78 // Base class for all static visitors. | |
| 79 class StaticVisitorBase : public AllStatic { | |
| 80 public: | |
| 82 // Visitor ID should fit in one byte. | 81 // Visitor ID should fit in one byte. |
| 83 STATIC_ASSERT(kVisitorIdCount <= 256); | 82 STATIC_ASSERT(kVisitorIdCount <= 256); |
| 84 | 83 |
| 85 // Determine which specialized visitor should be used for given instance type | 84 // Determine which specialized visitor should be used for given instance type |
| 86 // and instance type. | 85 // and instance type. |
| 87 static VisitorId GetVisitorId(int instance_type, int instance_size, | 86 static VisitorId GetVisitorId(int instance_type, int instance_size, |
| 88 bool has_unboxed_fields); | 87 bool has_unboxed_fields); |
| 89 | 88 |
| 90 // Determine which specialized visitor should be used for given map. | 89 // Determine which specialized visitor should be used for given map. |
| 91 static VisitorId GetVisitorId(Map* map); | 90 static VisitorId GetVisitorId(Map* map); |
| 92 }; | 91 }; |
| 93 | 92 |
| 94 | 93 |
| 95 template <typename Callback> | 94 template <typename Callback> |
| 96 class VisitorDispatchTable { | 95 class VisitorDispatchTable { |
| 97 public: | 96 public: |
| 98 void CopyFrom(VisitorDispatchTable* other) { | 97 void CopyFrom(VisitorDispatchTable* other) { |
| 99 // We are not using memcpy to guarantee that during update | 98 // We are not using memcpy to guarantee that during update |
| 100 // every element of callbacks_ array will remain correct | 99 // every element of callbacks_ array will remain correct |
| 101 // pointer (memcpy might be implemented as a byte copying loop). | 100 // pointer (memcpy might be implemented as a byte copying loop). |
| 102 for (int i = 0; i < StaticVisitorBase::kVisitorIdCount; i++) { | 101 for (int i = 0; i < kVisitorIdCount; i++) { |
| 103 base::NoBarrier_Store(&callbacks_[i], other->callbacks_[i]); | 102 base::NoBarrier_Store(&callbacks_[i], other->callbacks_[i]); |
| 104 } | 103 } |
| 105 } | 104 } |
| 106 | 105 |
| 107 inline Callback GetVisitor(Map* map); | 106 inline Callback GetVisitor(Map* map); |
| 108 | 107 |
| 109 inline Callback GetVisitorById(StaticVisitorBase::VisitorId id) { | 108 inline Callback GetVisitorById(VisitorId id) { |
| 110 return reinterpret_cast<Callback>(callbacks_[id]); | 109 return reinterpret_cast<Callback>(callbacks_[id]); |
| 111 } | 110 } |
| 112 | 111 |
| 113 void Register(StaticVisitorBase::VisitorId id, Callback callback) { | 112 void Register(VisitorId id, Callback callback) { |
| 114 DCHECK(id < StaticVisitorBase::kVisitorIdCount); // id is unsigned. | 113 DCHECK(id < kVisitorIdCount); // id is unsigned. |
| 115 callbacks_[id] = reinterpret_cast<base::AtomicWord>(callback); | 114 callbacks_[id] = reinterpret_cast<base::AtomicWord>(callback); |
| 116 } | 115 } |
| 117 | 116 |
| 118 private: | 117 private: |
| 119 base::AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount]; | 118 base::AtomicWord callbacks_[kVisitorIdCount]; |
| 120 }; | 119 }; |
| 121 | 120 |
| 122 | 121 |
| 123 template <typename StaticVisitor, typename BodyDescriptor, typename ReturnType> | 122 template <typename StaticVisitor, typename BodyDescriptor, typename ReturnType> |
| 124 class FlexibleBodyVisitor : public AllStatic { | 123 class FlexibleBodyVisitor : public AllStatic { |
| 125 public: | 124 public: |
| 126 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { | 125 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { |
| 127 int object_size = BodyDescriptor::SizeOf(map, object); | 126 int object_size = BodyDescriptor::SizeOf(map, object); |
| 128 BodyDescriptor::template IterateBody<StaticVisitor>(object, object_size); | 127 BodyDescriptor::template IterateBody<StaticVisitor>(object, object_size); |
| 129 return static_cast<ReturnType>(object_size); | 128 return static_cast<ReturnType>(object_size); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 typedef void (*Callback)(Map* map, HeapObject* object); | 341 typedef void (*Callback)(Map* map, HeapObject* object); |
| 343 | 342 |
| 344 static VisitorDispatchTable<Callback> table_; | 343 static VisitorDispatchTable<Callback> table_; |
| 345 }; | 344 }; |
| 346 | 345 |
| 347 | 346 |
| 348 template <typename StaticVisitor> | 347 template <typename StaticVisitor> |
| 349 VisitorDispatchTable<typename StaticMarkingVisitor<StaticVisitor>::Callback> | 348 VisitorDispatchTable<typename StaticMarkingVisitor<StaticVisitor>::Callback> |
| 350 StaticMarkingVisitor<StaticVisitor>::table_; | 349 StaticMarkingVisitor<StaticVisitor>::table_; |
| 351 | 350 |
| 351 #define TYPED_VISITOR_ID_LIST(V) \ | |
| 352 V(AllocationSite) \ | |
| 353 V(ByteArray) \ | |
| 354 V(BytecodeArray) \ | |
| 355 V(Cell) \ | |
| 356 V(Code) \ | |
| 357 V(ConsString) \ | |
| 358 V(FixedArray) \ | |
| 359 V(FixedDoubleArray) \ | |
| 360 V(FixedFloat64Array) \ | |
| 361 V(FixedTypedArrayBase) \ | |
| 362 V(JSArrayBuffer) \ | |
| 363 V(JSFunction) \ | |
| 364 V(JSObject) \ | |
| 365 V(JSRegExp) \ | |
| 366 V(JSWeakCollection) \ | |
| 367 V(Map) \ | |
| 368 V(Oddball) \ | |
| 369 V(PropertyCell) \ | |
| 370 V(SeqOneByteString) \ | |
| 371 V(SeqTwoByteString) \ | |
| 372 V(SharedFunctionInfo) \ | |
| 373 V(SlicedString) \ | |
| 374 V(Symbol) \ | |
| 375 V(TransitionArray) \ | |
| 376 V(ThinString) \ | |
| 377 V(WeakCell) | |
| 378 | |
| 379 // The base class for visitors that need to dispatch on object type. | |
| 380 // It is similar to StaticVisitor except it uses virtual dispatch | |
| 381 // instead of static dispatch table. The default behavour of all | |
| 382 // visit functions is to iterate body of the given object using | |
| 383 // the BodyDescriptor of the object. | |
| 384 // | |
| 385 // The visit functions return the size of the object cast to ResultType. | |
| 386 // | |
| 387 // This class is intended to be used in the following way: | |
| 388 // | |
| 389 // class SomeVisitor : public HeapVisitor<ResultType, SomeVisitor> { | |
| 390 // ... | |
| 391 // } | |
| 392 // | |
| 393 // This is an example of Curiously recurring template pattern. | |
| 394 // TODO(ulan): replace static visitors with the HeapVisitor. | |
| 395 template <typename ResultType, typename ConcreteVisitor> | |
| 396 class HeapVisitor : public ObjectVisitor { | |
| 397 public: | |
| 398 ResultType IterateBody(HeapObject* object); | |
| 399 | |
| 400 protected: | |
| 401 #define VISIT(type) virtual ResultType Visit##type(Map* map, type* object); | |
| 402 TYPED_VISITOR_ID_LIST(VISIT) | |
| 403 #undef VISIT | |
| 404 virtual ResultType VisitShortcutCandidate(Map* map, ConsString* object); | |
| 405 virtual ResultType VisitNativeContext(Map* map, Context* object); | |
| 406 virtual ResultType VisitDataObject(Map* map, HeapObject* object); | |
| 407 virtual ResultType VisitJSObjectFast(Map* map, JSObject* object); | |
| 408 virtual ResultType VisitJSApiObject(Map* map, JSObject* object); | |
| 409 virtual ResultType VisitStruct(Map* map, HeapObject* object); | |
| 410 virtual ResultType VisitFreeSpace(Map* map, FreeSpace* object); | |
|
Hannes Payer (out of office)
2017/04/27 14:29:50
Why can FreeSpace not be part of TYPED_VISITOR_ID_
ulan
2017/04/27 14:59:48
That would require FreeSpace::BodyDescriptor, whic
| |
| 411 }; | |
|
Hannes Payer (out of office)
2017/04/27 14:29:50
What would it take to generate all of them automat
ulan
2017/04/27 14:59:48
We would need the corresponding classes with BodyD
| |
| 352 | 412 |
| 353 class WeakObjectRetainer; | 413 class WeakObjectRetainer; |
| 354 | 414 |
| 355 | |
| 356 // A weak list is single linked list where each element has a weak pointer to | 415 // A weak list is single linked list where each element has a weak pointer to |
| 357 // the next element. Given the head of the list, this function removes dead | 416 // the next element. Given the head of the list, this function removes dead |
| 358 // elements from the list and if requested records slots for next-element | 417 // elements from the list and if requested records slots for next-element |
| 359 // pointers. The template parameter T is a WeakListVisitor that defines how to | 418 // pointers. The template parameter T is a WeakListVisitor that defines how to |
| 360 // access the next-element pointers. | 419 // access the next-element pointers. |
| 361 template <class T> | 420 template <class T> |
| 362 Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer); | 421 Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer); |
| 363 } // namespace internal | 422 } // namespace internal |
| 364 } // namespace v8 | 423 } // namespace v8 |
| 365 | 424 |
| 366 #endif // V8_OBJECTS_VISITING_H_ | 425 #endif // V8_OBJECTS_VISITING_H_ |
| OLD | NEW |