| 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 |