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/layout-descriptor.h" | |
| 9 | 10 |
| 10 // This file provides base classes and auxiliary methods for defining | 11 // This file provides base classes and auxiliary methods for defining |
| 11 // static object visitors used during GC. | 12 // static object visitors used during GC. |
| 12 // Visiting HeapObject body with a normal ObjectVisitor requires performing | 13 // Visiting HeapObject body with a normal ObjectVisitor requires performing |
| 13 // two switches on object's instance type to determine object size and layout | 14 // two switches on object's instance type to determine object size and layout |
| 14 // and one or more virtual method calls on visitor itself. | 15 // and one or more virtual method calls on visitor itself. |
| 15 // Static visitor is different: it provides a dispatch table which contains | 16 // Static visitor is different: it provides a dispatch table which contains |
| 16 // pointers to specialized visit functions. Each map has the visitor_id | 17 // pointers to specialized visit functions. Each map has the visitor_id |
| 17 // field which contains an index of specialized visitor to use. | 18 // field which contains an index of specialized visitor to use. |
| 18 | 19 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 kVisitJSObject = kVisitJSObject2, | 99 kVisitJSObject = kVisitJSObject2, |
| 99 kVisitStruct = kVisitStruct2, | 100 kVisitStruct = kVisitStruct2, |
| 100 kMinObjectSizeInWords = 2 | 101 kMinObjectSizeInWords = 2 |
| 101 }; | 102 }; |
| 102 | 103 |
| 103 // Visitor ID should fit in one byte. | 104 // Visitor ID should fit in one byte. |
| 104 STATIC_ASSERT(kVisitorIdCount <= 256); | 105 STATIC_ASSERT(kVisitorIdCount <= 256); |
| 105 | 106 |
| 106 // Determine which specialized visitor should be used for given instance type | 107 // Determine which specialized visitor should be used for given instance type |
| 107 // and instance type. | 108 // and instance type. |
| 108 static VisitorId GetVisitorId(int instance_type, int instance_size); | 109 static VisitorId GetVisitorId(int instance_type, int instance_size, |
| 110 bool has_unboxed_fields); | |
| 109 | 111 |
| 112 // Determine which specialized visitor should be used for given map. | |
| 110 static VisitorId GetVisitorId(Map* map) { | 113 static VisitorId GetVisitorId(Map* map) { |
| 111 return GetVisitorId(map->instance_type(), map->instance_size()); | 114 return GetVisitorId(map->instance_type(), map->instance_size(), |
| 115 FLAG_unbox_double_fields && | |
| 116 !map->layout_descriptor()->IsFastPointerLayout()); | |
| 112 } | 117 } |
| 113 | 118 |
| 114 // For visitors that allow specialization by size calculate VisitorId based | 119 // For visitors that allow specialization by size calculate VisitorId based |
| 115 // on size, base visitor id and generic visitor id. | 120 // on size, base visitor id and generic visitor id. |
| 116 static VisitorId GetVisitorIdForSize(VisitorId base, VisitorId generic, | 121 static VisitorId GetVisitorIdForSize(VisitorId base, VisitorId generic, |
| 117 int object_size) { | 122 int object_size, |
| 123 bool has_unboxed_fields) { | |
| 118 DCHECK((base == kVisitDataObject) || (base == kVisitStruct) || | 124 DCHECK((base == kVisitDataObject) || (base == kVisitStruct) || |
| 119 (base == kVisitJSObject)); | 125 (base == kVisitJSObject)); |
| 120 DCHECK(IsAligned(object_size, kPointerSize)); | 126 DCHECK(IsAligned(object_size, kPointerSize)); |
| 121 DCHECK(kMinObjectSizeInWords * kPointerSize <= object_size); | 127 DCHECK(kMinObjectSizeInWords * kPointerSize <= object_size); |
| 122 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); | 128 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); |
| 129 DCHECK(!has_unboxed_fields || (base == kVisitJSObject)); | |
| 130 | |
| 131 if (has_unboxed_fields) return generic; | |
| 123 | 132 |
| 124 const VisitorId specialization = static_cast<VisitorId>( | 133 const VisitorId specialization = static_cast<VisitorId>( |
| 125 base + (object_size >> kPointerSizeLog2) - kMinObjectSizeInWords); | 134 base + (object_size >> kPointerSizeLog2) - kMinObjectSizeInWords); |
| 126 | 135 |
| 127 return Min(specialization, generic); | 136 return Min(specialization, generic); |
| 128 } | 137 } |
| 129 }; | 138 }; |
| 130 | 139 |
| 131 | 140 |
| 132 template <typename Callback> | 141 template <typename Callback> |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 151 | 160 |
| 152 void Register(StaticVisitorBase::VisitorId id, Callback callback) { | 161 void Register(StaticVisitorBase::VisitorId id, Callback callback) { |
| 153 DCHECK(id < StaticVisitorBase::kVisitorIdCount); // id is unsigned. | 162 DCHECK(id < StaticVisitorBase::kVisitorIdCount); // id is unsigned. |
| 154 callbacks_[id] = reinterpret_cast<base::AtomicWord>(callback); | 163 callbacks_[id] = reinterpret_cast<base::AtomicWord>(callback); |
| 155 } | 164 } |
| 156 | 165 |
| 157 template <typename Visitor, StaticVisitorBase::VisitorId base, | 166 template <typename Visitor, StaticVisitorBase::VisitorId base, |
| 158 StaticVisitorBase::VisitorId generic, int object_size_in_words> | 167 StaticVisitorBase::VisitorId generic, int object_size_in_words> |
| 159 void RegisterSpecialization() { | 168 void RegisterSpecialization() { |
| 160 static const int size = object_size_in_words * kPointerSize; | 169 static const int size = object_size_in_words * kPointerSize; |
| 161 Register(StaticVisitorBase::GetVisitorIdForSize(base, generic, size), | 170 Register(StaticVisitorBase::GetVisitorIdForSize(base, generic, size, false), |
| 162 &Visitor::template VisitSpecialized<size>); | 171 &Visitor::template VisitSpecialized<size>); |
| 163 } | 172 } |
| 164 | 173 |
| 165 | 174 |
| 166 template <typename Visitor, StaticVisitorBase::VisitorId base, | 175 template <typename Visitor, StaticVisitorBase::VisitorId base, |
| 167 StaticVisitorBase::VisitorId generic> | 176 StaticVisitorBase::VisitorId generic> |
| 168 void RegisterSpecializations() { | 177 void RegisterSpecializations() { |
| 169 STATIC_ASSERT((generic - base + StaticVisitorBase::kMinObjectSizeInWords) == | 178 STATIC_ASSERT((generic - base + StaticVisitorBase::kMinObjectSizeInWords) == |
| 170 10); | 179 10); |
| 171 RegisterSpecialization<Visitor, base, generic, 2>(); | 180 RegisterSpecialization<Visitor, base, generic, 2>(); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 182 private: | 191 private: |
| 183 base::AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount]; | 192 base::AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount]; |
| 184 }; | 193 }; |
| 185 | 194 |
| 186 | 195 |
| 187 template <typename StaticVisitor> | 196 template <typename StaticVisitor> |
| 188 class BodyVisitorBase : public AllStatic { | 197 class BodyVisitorBase : public AllStatic { |
| 189 public: | 198 public: |
| 190 INLINE(static void IteratePointers(Heap* heap, HeapObject* object, | 199 INLINE(static void IteratePointers(Heap* heap, HeapObject* object, |
| 191 int start_offset, int end_offset)) { | 200 int start_offset, int end_offset)) { |
| 192 Object** start_slot = | 201 DCHECK(!FLAG_unbox_double_fields || |
| 193 reinterpret_cast<Object**>(object->address() + start_offset); | 202 object->map()->layout_descriptor()->IsFastPointerLayout()); |
| 194 Object** end_slot = | 203 IterateRawPointers(heap, object, start_offset, end_offset); |
| 195 reinterpret_cast<Object**>(object->address() + end_offset); | 204 } |
| 196 StaticVisitor::VisitPointers(heap, start_slot, end_slot); | 205 |
| 206 INLINE(static void IterateBody(Heap* heap, HeapObject* object, | |
| 207 int start_offset, int end_offset)) { | |
| 208 if (!FLAG_unbox_double_fields || | |
| 209 object->map()->layout_descriptor()->IsFastPointerLayout()) { | |
| 210 IterateRawPointers(heap, object, start_offset, end_offset); | |
| 211 } else { | |
| 212 IterateBodyUsingLayoutDescriptor(heap, object, start_offset, end_offset); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 private: | |
| 217 INLINE(static void IterateRawPointers(Heap* heap, HeapObject* object, | |
| 218 int start_offset, int end_offset)) { | |
| 219 StaticVisitor::VisitPointers(heap, | |
| 220 HeapObject::RawField(object, start_offset), | |
| 221 HeapObject::RawField(object, end_offset)); | |
| 222 } | |
| 223 | |
| 224 static void IterateBodyUsingLayoutDescriptor(Heap* heap, HeapObject* object, | |
| 225 int start_offset, | |
| 226 int end_offset) { | |
| 227 DCHECK(FLAG_unbox_double_fields); | |
| 228 DCHECK(IsAligned(start_offset, kPointerSize) && | |
| 229 IsAligned(end_offset, kPointerSize)); | |
| 230 | |
| 231 InobjectPropertiesHelper helper(object->map()); | |
| 232 DCHECK(!helper.all_fields_tagged()); | |
| 233 | |
| 234 for (int offset = start_offset; offset < end_offset; | |
| 235 offset += kPointerSize) { | |
| 236 // Visit tagged fields only. | |
| 237 if (helper.IsTagged(offset)) { | |
| 238 IterateRawPointers(heap, object, offset, offset + kPointerSize); | |
|
Hannes Payer (out of office)
2014/11/06 12:29:46
Instead of calling this for each field, do you thi
Igor Sheludko
2014/11/07 08:03:52
Good point! But let me do that in a next CL.
Hannes Payer (out of office)
2014/11/10 15:26:08
Then please leave a todo.
Igor Sheludko
2014/11/10 15:43:54
Done.
| |
| 239 } | |
| 240 } | |
| 197 } | 241 } |
| 198 }; | 242 }; |
| 199 | 243 |
| 200 | 244 |
| 201 template <typename StaticVisitor, typename BodyDescriptor, typename ReturnType> | 245 template <typename StaticVisitor, typename BodyDescriptor, typename ReturnType> |
| 202 class FlexibleBodyVisitor : public BodyVisitorBase<StaticVisitor> { | 246 class FlexibleBodyVisitor : public BodyVisitorBase<StaticVisitor> { |
| 203 public: | 247 public: |
| 204 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { | 248 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { |
| 205 int object_size = BodyDescriptor::SizeOf(map, object); | 249 int object_size = BodyDescriptor::SizeOf(map, object); |
| 206 BodyVisitorBase<StaticVisitor>::IteratePointers( | 250 BodyVisitorBase<StaticVisitor>::IterateBody( |
| 207 map->GetHeap(), object, BodyDescriptor::kStartOffset, object_size); | 251 map->GetHeap(), object, BodyDescriptor::kStartOffset, object_size); |
| 208 return static_cast<ReturnType>(object_size); | 252 return static_cast<ReturnType>(object_size); |
| 209 } | 253 } |
| 210 | 254 |
| 211 template <int object_size> | 255 template <int object_size> |
| 212 static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) { | 256 static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) { |
| 213 DCHECK(BodyDescriptor::SizeOf(map, object) == object_size); | 257 DCHECK(BodyDescriptor::SizeOf(map, object) == object_size); |
| 214 BodyVisitorBase<StaticVisitor>::IteratePointers( | 258 BodyVisitorBase<StaticVisitor>::IteratePointers( |
| 215 map->GetHeap(), object, BodyDescriptor::kStartOffset, object_size); | 259 map->GetHeap(), object, BodyDescriptor::kStartOffset, object_size); |
| 216 return static_cast<ReturnType>(object_size); | 260 return static_cast<ReturnType>(object_size); |
| 217 } | 261 } |
| 218 }; | 262 }; |
| 219 | 263 |
| 220 | 264 |
| 221 template <typename StaticVisitor, typename BodyDescriptor, typename ReturnType> | 265 template <typename StaticVisitor, typename BodyDescriptor, typename ReturnType> |
| 222 class FixedBodyVisitor : public BodyVisitorBase<StaticVisitor> { | 266 class FixedBodyVisitor : public BodyVisitorBase<StaticVisitor> { |
| 223 public: | 267 public: |
| 224 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { | 268 INLINE(static ReturnType Visit(Map* map, HeapObject* object)) { |
| 225 BodyVisitorBase<StaticVisitor>::IteratePointers( | 269 BodyVisitorBase<StaticVisitor>::IterateBody(map->GetHeap(), object, |
| 226 map->GetHeap(), object, BodyDescriptor::kStartOffset, | 270 BodyDescriptor::kStartOffset, |
| 227 BodyDescriptor::kEndOffset); | 271 BodyDescriptor::kEndOffset); |
| 228 return static_cast<ReturnType>(BodyDescriptor::kSize); | 272 return static_cast<ReturnType>(BodyDescriptor::kSize); |
| 229 } | 273 } |
| 230 }; | 274 }; |
| 231 | 275 |
| 232 | 276 |
| 233 // Base class for visitors used for a linear new space iteration. | 277 // Base class for visitors used for a linear new space iteration. |
| 234 // IterateBody returns size of visited object. | 278 // IterateBody returns size of visited object. |
| 235 // Certain types of objects (i.e. Code objects) are not handled | 279 // Certain types of objects (i.e. Code objects) are not handled |
| 236 // by dispatch table of this visitor because they cannot appear | 280 // by dispatch table of this visitor because they cannot appear |
| 237 // in the new space. | 281 // in the new space. |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 // the next element. Given the head of the list, this function removes dead | 489 // the next element. Given the head of the list, this function removes dead |
| 446 // elements from the list and if requested records slots for next-element | 490 // elements from the list and if requested records slots for next-element |
| 447 // pointers. The template parameter T is a WeakListVisitor that defines how to | 491 // pointers. The template parameter T is a WeakListVisitor that defines how to |
| 448 // access the next-element pointers. | 492 // access the next-element pointers. |
| 449 template <class T> | 493 template <class T> |
| 450 Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer); | 494 Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer); |
| 451 } | 495 } |
| 452 } // namespace v8::internal | 496 } // namespace v8::internal |
| 453 | 497 |
| 454 #endif // V8_OBJECTS_VISITING_H_ | 498 #endif // V8_OBJECTS_VISITING_H_ |
| OLD | NEW |