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 |