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 |