1 | // Copyright 2015 the V8 project authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef V8_OBJECTS_BODY_DESCRIPTORS_INL_H_ |
6 | #define V8_OBJECTS_BODY_DESCRIPTORS_INL_H_ |
7 | |
8 | #include "src/objects-body-descriptors.h" |
9 | |
10 | #include <algorithm> |
11 | |
12 | #include "src/feedback-vector.h" |
13 | #include "src/objects/cell.h" |
14 | #include "src/objects/data-handler.h" |
15 | #include "src/objects/foreign-inl.h" |
16 | #include "src/objects/hash-table.h" |
17 | #include "src/objects/js-collection.h" |
18 | #include "src/objects/js-weak-refs.h" |
19 | #include "src/objects/oddball.h" |
20 | #include "src/objects/ordered-hash-table.h" |
21 | #include "src/reloc-info.h" |
22 | #include "src/transitions.h" |
23 | #include "src/wasm/wasm-objects-inl.h" |
24 | |
25 | namespace v8 { |
26 | namespace internal { |
27 | |
28 | template <int start_offset> |
29 | int FlexibleBodyDescriptor<start_offset>::SizeOf(Map map, HeapObject object) { |
30 | return object->SizeFromMap(map); |
31 | } |
32 | |
33 | template <int start_offset> |
34 | int FlexibleWeakBodyDescriptor<start_offset>::SizeOf(Map map, |
35 | HeapObject object) { |
36 | return object->SizeFromMap(map); |
37 | } |
38 | |
39 | bool BodyDescriptorBase::IsValidJSObjectSlotImpl(Map map, HeapObject obj, |
40 | int offset) { |
41 | #ifdef V8_COMPRESS_POINTERS |
42 | STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize); |
43 | int embedder_fields_offset = JSObject::GetEmbedderFieldsStartOffset(map); |
44 | int inobject_fields_offset = map->GetInObjectPropertyOffset(0); |
45 | // |embedder_fields_offset| may be greater than |inobject_fields_offset| if |
46 | // the object does not have embedder fields but the check handles this |
47 | // case properly. |
48 | if (embedder_fields_offset <= offset && offset < inobject_fields_offset) { |
49 | // offset points to embedder fields area: |
50 | // [embedder_fields_offset, inobject_fields_offset). |
51 | STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize)); |
52 | return ((offset - embedder_fields_offset) & (kEmbedderDataSlotSize - 1)) == |
53 | EmbedderDataSlot::kTaggedPayloadOffset; |
54 | } |
55 | #else |
56 | // We store raw aligned pointers as Smis, so it's safe to treat the whole |
57 | // embedder field area as tagged slots. |
58 | STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize); |
59 | #endif |
60 | if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) { |
61 | return true; |
62 | } else { |
63 | DCHECK(FLAG_unbox_double_fields); |
64 | DCHECK(IsAligned(offset, kSystemPointerSize)); |
65 | |
66 | LayoutDescriptorHelper helper(map); |
67 | DCHECK(!helper.all_fields_tagged()); |
68 | return helper.IsTagged(offset); |
69 | } |
70 | } |
71 | |
72 | template <typename ObjectVisitor> |
73 | void BodyDescriptorBase::IterateJSObjectBodyImpl(Map map, HeapObject obj, |
74 | int start_offset, |
75 | int end_offset, |
76 | ObjectVisitor* v) { |
77 | #ifdef V8_COMPRESS_POINTERS |
78 | STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize); |
79 | int header_size = JSObject::GetHeaderSize(map); |
80 | int inobject_fields_offset = map->GetInObjectPropertyOffset(0); |
81 | // We are always requested to process header and embedder fields. |
82 | DCHECK_LE(inobject_fields_offset, end_offset); |
83 | // Embedder fields are located between header and inobject properties. |
84 | if (header_size < inobject_fields_offset) { |
85 | // There are embedder fields. |
86 | IteratePointers(obj, start_offset, header_size, v); |
87 | // Iterate only tagged payload of the embedder slots and skip raw payload. |
88 | DCHECK_EQ(header_size, JSObject::GetEmbedderFieldsStartOffset(map)); |
89 | for (int offset = header_size + EmbedderDataSlot::kTaggedPayloadOffset; |
90 | offset < inobject_fields_offset; offset += kEmbedderDataSlotSize) { |
91 | IteratePointer(obj, offset, v); |
92 | } |
93 | // Proceed processing inobject properties. |
94 | start_offset = inobject_fields_offset; |
95 | } |
96 | #else |
97 | // We store raw aligned pointers as Smis, so it's safe to iterate the whole |
98 | // embedder field area as tagged slots. |
99 | STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize); |
100 | #endif |
101 | if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) { |
102 | IteratePointers(obj, start_offset, end_offset, v); |
103 | } else { |
104 | DCHECK(FLAG_unbox_double_fields); |
105 | DCHECK(IsAligned(start_offset, kSystemPointerSize) && |
106 | IsAligned(end_offset, kSystemPointerSize)); |
107 | |
108 | LayoutDescriptorHelper helper(map); |
109 | DCHECK(!helper.all_fields_tagged()); |
110 | for (int offset = start_offset; offset < end_offset;) { |
111 | int end_of_region_offset; |
112 | if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) { |
113 | IteratePointers(obj, offset, end_of_region_offset, v); |
114 | } |
115 | offset = end_of_region_offset; |
116 | } |
117 | } |
118 | } |
119 | |
120 | template <typename ObjectVisitor> |
121 | DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(HeapObject obj, |
122 | int start_offset, |
123 | int end_offset, |
124 | ObjectVisitor* v) { |
125 | v->VisitPointers(obj, obj.RawField(start_offset), obj.RawField(end_offset)); |
126 | } |
127 | |
128 | template <typename ObjectVisitor> |
129 | void BodyDescriptorBase::IteratePointer(HeapObject obj, int offset, |
130 | ObjectVisitor* v) { |
131 | v->VisitPointer(obj, obj.RawField(offset)); |
132 | } |
133 | |
134 | template <typename ObjectVisitor> |
135 | DISABLE_CFI_PERF void BodyDescriptorBase::IterateMaybeWeakPointers( |
136 | HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) { |
137 | v->VisitPointers(obj, obj.RawMaybeWeakField(start_offset), |
138 | obj.RawMaybeWeakField(end_offset)); |
139 | } |
140 | |
141 | template <typename ObjectVisitor> |
142 | void BodyDescriptorBase::IterateMaybeWeakPointer(HeapObject obj, int offset, |
143 | ObjectVisitor* v) { |
144 | v->VisitPointer(obj, obj.RawMaybeWeakField(offset)); |
145 | } |
146 | |
147 | template <typename ObjectVisitor> |
148 | DISABLE_CFI_PERF void BodyDescriptorBase::IterateCustomWeakPointers( |
149 | HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) { |
150 | v->VisitCustomWeakPointers(obj, obj.RawField(start_offset), |
151 | obj.RawField(end_offset)); |
152 | } |
153 | |
154 | template <typename ObjectVisitor> |
155 | DISABLE_CFI_PERF void BodyDescriptorBase::IterateEphemeron(HeapObject obj, |
156 | int index, |
157 | int key_offset, |
158 | int value_offset, |
159 | ObjectVisitor* v) { |
160 | v->VisitEphemeron(obj, index, obj.RawField(key_offset), |
161 | obj.RawField(value_offset)); |
162 | } |
163 | |
164 | template <typename ObjectVisitor> |
165 | void BodyDescriptorBase::IterateCustomWeakPointer(HeapObject obj, int offset, |
166 | ObjectVisitor* v) { |
167 | v->VisitCustomWeakPointer(obj, obj.RawField(offset)); |
168 | } |
169 | |
170 | class JSObject::BodyDescriptor final : public BodyDescriptorBase { |
171 | public: |
172 | static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset; |
173 | |
174 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
175 | if (offset < kStartOffset) return false; |
176 | return IsValidJSObjectSlotImpl(map, obj, offset); |
177 | } |
178 | |
179 | template <typename ObjectVisitor> |
180 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
181 | ObjectVisitor* v) { |
182 | IterateJSObjectBodyImpl(map, obj, kStartOffset, object_size, v); |
183 | } |
184 | |
185 | static inline int SizeOf(Map map, HeapObject object) { |
186 | return map->instance_size(); |
187 | } |
188 | }; |
189 | |
190 | class JSObject::FastBodyDescriptor final : public BodyDescriptorBase { |
191 | public: |
192 | static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset; |
193 | |
194 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
195 | return offset >= kStartOffset; |
196 | } |
197 | |
198 | template <typename ObjectVisitor> |
199 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
200 | ObjectVisitor* v) { |
201 | IteratePointers(obj, kStartOffset, object_size, v); |
202 | } |
203 | |
204 | static inline int SizeOf(Map map, HeapObject object) { |
205 | return map->instance_size(); |
206 | } |
207 | }; |
208 | |
209 | class WeakCell::BodyDescriptor final : public BodyDescriptorBase { |
210 | public: |
211 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
212 | return offset >= HeapObject::kHeaderSize; |
213 | } |
214 | |
215 | template <typename ObjectVisitor> |
216 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
217 | ObjectVisitor* v) { |
218 | IteratePointers(obj, HeapObject::kHeaderSize, kTargetOffset, v); |
219 | IterateCustomWeakPointer(obj, kTargetOffset, v); |
220 | IteratePointers(obj, kTargetOffset + kTaggedSize, object_size, v); |
221 | } |
222 | |
223 | static inline int SizeOf(Map map, HeapObject object) { |
224 | return map->instance_size(); |
225 | } |
226 | }; |
227 | |
228 | class JSWeakRef::BodyDescriptor final : public BodyDescriptorBase { |
229 | public: |
230 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
231 | return IsValidJSObjectSlotImpl(map, obj, offset); |
232 | } |
233 | |
234 | template <typename ObjectVisitor> |
235 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
236 | ObjectVisitor* v) { |
237 | IteratePointers(obj, JSReceiver::kPropertiesOrHashOffset, kTargetOffset, v); |
238 | IterateCustomWeakPointer(obj, kTargetOffset, v); |
239 | IterateJSObjectBodyImpl(map, obj, kTargetOffset + kTaggedSize, object_size, |
240 | v); |
241 | } |
242 | |
243 | static inline int SizeOf(Map map, HeapObject object) { |
244 | return map->instance_size(); |
245 | } |
246 | }; |
247 | |
248 | class SharedFunctionInfo::BodyDescriptor final : public BodyDescriptorBase { |
249 | public: |
250 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
251 | return FixedBodyDescriptor<kStartOfPointerFieldsOffset, |
252 | kEndOfTaggedFieldsOffset, |
253 | kAlignedSize>::IsValidSlot(map, obj, offset); |
254 | } |
255 | |
256 | template <typename ObjectVisitor> |
257 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
258 | ObjectVisitor* v) { |
259 | IterateCustomWeakPointer(obj, kFunctionDataOffset, v); |
260 | IteratePointers(obj, SharedFunctionInfo::kStartOfStrongFieldsOffset, |
261 | SharedFunctionInfo::kEndOfTaggedFieldsOffset, v); |
262 | } |
263 | |
264 | static inline int SizeOf(Map map, HeapObject object) { |
265 | return map->instance_size(); |
266 | } |
267 | }; |
268 | |
269 | class AllocationSite::BodyDescriptor final : public BodyDescriptorBase { |
270 | public: |
271 | STATIC_ASSERT(AllocationSite::kCommonPointerFieldEndOffset == |
272 | AllocationSite::kPretenureDataOffset); |
273 | STATIC_ASSERT(AllocationSite::kPretenureDataOffset + kInt32Size == |
274 | AllocationSite::kPretenureCreateCountOffset); |
275 | STATIC_ASSERT(AllocationSite::kPretenureCreateCountOffset + kInt32Size == |
276 | AllocationSite::kWeakNextOffset); |
277 | |
278 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
279 | if (offset >= AllocationSite::kStartOffset && |
280 | offset < AllocationSite::kCommonPointerFieldEndOffset) { |
281 | return true; |
282 | } |
283 | // check for weak_next offset |
284 | if (map->instance_size() == AllocationSite::kSizeWithWeakNext && |
285 | offset == AllocationSite::kWeakNextOffset) { |
286 | return true; |
287 | } |
288 | return false; |
289 | } |
290 | |
291 | template <typename ObjectVisitor> |
292 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
293 | ObjectVisitor* v) { |
294 | // Iterate over all the common pointer fields |
295 | IteratePointers(obj, AllocationSite::kStartOffset, |
296 | AllocationSite::kCommonPointerFieldEndOffset, v); |
297 | // Skip PretenureDataOffset and PretenureCreateCount which are Int32 fields. |
298 | // Visit weak_next only if it has weak_next field. |
299 | if (object_size == AllocationSite::kSizeWithWeakNext) { |
300 | IterateCustomWeakPointers(obj, AllocationSite::kWeakNextOffset, |
301 | AllocationSite::kSizeWithWeakNext, v); |
302 | } |
303 | } |
304 | |
305 | static inline int SizeOf(Map map, HeapObject object) { |
306 | return map->instance_size(); |
307 | } |
308 | }; |
309 | |
310 | class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase { |
311 | public: |
312 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
313 | if (offset < kEndOfTaggedFieldsOffset) return true; |
314 | if (offset < kHeaderSize) return false; |
315 | return IsValidJSObjectSlotImpl(map, obj, offset); |
316 | } |
317 | |
318 | template <typename ObjectVisitor> |
319 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
320 | ObjectVisitor* v) { |
321 | // JSArrayBuffer instances contain raw data that the GC does not know about. |
322 | IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v); |
323 | IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v); |
324 | } |
325 | |
326 | static inline int SizeOf(Map map, HeapObject object) { |
327 | return map->instance_size(); |
328 | } |
329 | }; |
330 | |
331 | class JSArrayBufferView::BodyDescriptor final : public BodyDescriptorBase { |
332 | public: |
333 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
334 | if (offset < kEndOfTaggedFieldsOffset) return true; |
335 | if (offset < kHeaderSize) return false; |
336 | return IsValidJSObjectSlotImpl(map, obj, offset); |
337 | } |
338 | |
339 | template <typename ObjectVisitor> |
340 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
341 | ObjectVisitor* v) { |
342 | // JSArrayBufferView contains raw data that the GC does not know about. |
343 | IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v); |
344 | IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v); |
345 | } |
346 | |
347 | static inline int SizeOf(Map map, HeapObject object) { |
348 | return map->instance_size(); |
349 | } |
350 | }; |
351 | |
352 | template <typename Derived> |
353 | class V8_EXPORT_PRIVATE SmallOrderedHashTable<Derived>::BodyDescriptor final |
354 | : public BodyDescriptorBase { |
355 | public: |
356 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
357 | Derived table = Derived::cast(obj); |
358 | // Only data table part contains tagged values. |
359 | return (offset >= DataTableStartOffset()) && |
360 | (offset < table->GetBucketsStartOffset()); |
361 | } |
362 | |
363 | template <typename ObjectVisitor> |
364 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
365 | ObjectVisitor* v) { |
366 | Derived table = Derived::cast(obj); |
367 | int start_offset = DataTableStartOffset(); |
368 | int end_offset = table->GetBucketsStartOffset(); |
369 | IteratePointers(obj, start_offset, end_offset, v); |
370 | } |
371 | |
372 | static inline int SizeOf(Map map, HeapObject obj) { |
373 | Derived table = Derived::cast(obj); |
374 | return table->SizeFor(table->Capacity()); |
375 | } |
376 | }; |
377 | |
378 | class ByteArray::BodyDescriptor final : public BodyDescriptorBase { |
379 | public: |
380 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } |
381 | |
382 | template <typename ObjectVisitor> |
383 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
384 | ObjectVisitor* v) {} |
385 | |
386 | static inline int SizeOf(Map map, HeapObject obj) { |
387 | return ByteArray::SizeFor(ByteArray::cast(obj)->synchronized_length()); |
388 | } |
389 | }; |
390 | |
391 | class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase { |
392 | public: |
393 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
394 | return offset >= kConstantPoolOffset && |
395 | offset <= kSourcePositionTableOffset; |
396 | } |
397 | |
398 | template <typename ObjectVisitor> |
399 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
400 | ObjectVisitor* v) { |
401 | IteratePointer(obj, kConstantPoolOffset, v); |
402 | IteratePointer(obj, kHandlerTableOffset, v); |
403 | IteratePointer(obj, kSourcePositionTableOffset, v); |
404 | } |
405 | |
406 | static inline int SizeOf(Map map, HeapObject obj) { |
407 | return BytecodeArray::SizeFor( |
408 | BytecodeArray::cast(obj)->synchronized_length()); |
409 | } |
410 | }; |
411 | |
412 | class BigInt::BodyDescriptor final : public BodyDescriptorBase { |
413 | public: |
414 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } |
415 | |
416 | template <typename ObjectVisitor> |
417 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
418 | ObjectVisitor* v) {} |
419 | |
420 | static inline int SizeOf(Map map, HeapObject obj) { |
421 | return BigInt::SizeFor(BigInt::cast(obj)->synchronized_length()); |
422 | } |
423 | }; |
424 | |
425 | class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase { |
426 | public: |
427 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } |
428 | |
429 | template <typename ObjectVisitor> |
430 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
431 | ObjectVisitor* v) {} |
432 | |
433 | static inline int SizeOf(Map map, HeapObject obj) { |
434 | return FixedDoubleArray::SizeFor( |
435 | FixedDoubleArray::cast(obj)->synchronized_length()); |
436 | } |
437 | }; |
438 | |
439 | class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase { |
440 | public: |
441 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
442 | return offset == kBasePointerOffset; |
443 | } |
444 | |
445 | template <typename ObjectVisitor> |
446 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
447 | ObjectVisitor* v) { |
448 | IteratePointer(obj, kBasePointerOffset, v); |
449 | } |
450 | |
451 | static inline int SizeOf(Map map, HeapObject object) { |
452 | return FixedTypedArrayBase::cast(object)->size(); |
453 | } |
454 | }; |
455 | |
456 | class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase { |
457 | public: |
458 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } |
459 | |
460 | template <typename ObjectVisitor> |
461 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
462 | ObjectVisitor* v) {} |
463 | |
464 | static inline int SizeOf(Map map, HeapObject obj) { |
465 | return FeedbackMetadata::SizeFor( |
466 | FeedbackMetadata::cast(obj)->synchronized_slot_count()); |
467 | } |
468 | }; |
469 | |
470 | class FeedbackVector::BodyDescriptor final : public BodyDescriptorBase { |
471 | public: |
472 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
473 | return offset == kSharedFunctionInfoOffset || |
474 | offset == kOptimizedCodeOffset || |
475 | offset == kClosureFeedbackCellArrayOffset || |
476 | offset >= kFeedbackSlotsOffset; |
477 | } |
478 | |
479 | template <typename ObjectVisitor> |
480 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
481 | ObjectVisitor* v) { |
482 | IteratePointer(obj, kSharedFunctionInfoOffset, v); |
483 | IterateMaybeWeakPointer(obj, kOptimizedCodeOffset, v); |
484 | IteratePointer(obj, kClosureFeedbackCellArrayOffset, v); |
485 | IterateMaybeWeakPointers(obj, kFeedbackSlotsOffset, object_size, v); |
486 | } |
487 | |
488 | static inline int SizeOf(Map map, HeapObject obj) { |
489 | return FeedbackVector::SizeFor(FeedbackVector::cast(obj)->length()); |
490 | } |
491 | }; |
492 | |
493 | class PreparseData::BodyDescriptor final : public BodyDescriptorBase { |
494 | public: |
495 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
496 | return offset >= PreparseData::cast(obj)->inner_start_offset(); |
497 | } |
498 | |
499 | template <typename ObjectVisitor> |
500 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
501 | ObjectVisitor* v) { |
502 | PreparseData data = PreparseData::cast(obj); |
503 | int start_offset = data->inner_start_offset(); |
504 | int end_offset = start_offset + data->children_length() * kTaggedSize; |
505 | IteratePointers(obj, start_offset, end_offset, v); |
506 | } |
507 | |
508 | static inline int SizeOf(Map map, HeapObject obj) { |
509 | PreparseData data = PreparseData::cast(obj); |
510 | return PreparseData::SizeFor(data->data_length(), data->children_length()); |
511 | } |
512 | }; |
513 | |
514 | class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase { |
515 | public: |
516 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
517 | return offset >= HeapObject::kHeaderSize; |
518 | } |
519 | |
520 | template <typename ObjectVisitor> |
521 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
522 | ObjectVisitor* v) { |
523 | IteratePointers(obj, HeapObject::kHeaderSize, kObjectCreateMapOffset, v); |
524 | IterateMaybeWeakPointer(obj, kObjectCreateMapOffset, v); |
525 | IteratePointers(obj, kObjectCreateMapOffset + kTaggedSize, object_size, v); |
526 | } |
527 | |
528 | static inline int SizeOf(Map map, HeapObject obj) { |
529 | return obj->SizeFromMap(map); |
530 | } |
531 | }; |
532 | |
533 | class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase { |
534 | public: |
535 | STATIC_ASSERT(kTableOffset + kTaggedSize == kSize); |
536 | |
537 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
538 | return IsValidJSObjectSlotImpl(map, obj, offset); |
539 | } |
540 | |
541 | template <typename ObjectVisitor> |
542 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
543 | ObjectVisitor* v) { |
544 | IterateJSObjectBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v); |
545 | } |
546 | |
547 | static inline int SizeOf(Map map, HeapObject object) { |
548 | return map->instance_size(); |
549 | } |
550 | }; |
551 | |
552 | class Foreign::BodyDescriptor final : public BodyDescriptorBase { |
553 | public: |
554 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } |
555 | |
556 | template <typename ObjectVisitor> |
557 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
558 | ObjectVisitor* v) { |
559 | v->VisitExternalReference( |
560 | Foreign::cast(obj), reinterpret_cast<Address*>( |
561 | obj.RawField(kForeignAddressOffset).address())); |
562 | } |
563 | |
564 | static inline int SizeOf(Map map, HeapObject object) { return kSize; } |
565 | }; |
566 | |
567 | class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase { |
568 | public: |
569 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } |
570 | |
571 | template <typename ObjectVisitor> |
572 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
573 | ObjectVisitor* v) {} |
574 | |
575 | static inline int SizeOf(Map map, HeapObject object) { return kSize; } |
576 | }; |
577 | |
578 | class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase { |
579 | public: |
580 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } |
581 | |
582 | template <typename ObjectVisitor> |
583 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
584 | ObjectVisitor* v) {} |
585 | |
586 | static inline int SizeOf(Map map, HeapObject object) { return kSize; } |
587 | }; |
588 | |
589 | class Code::BodyDescriptor final : public BodyDescriptorBase { |
590 | public: |
591 | STATIC_ASSERT(kRelocationInfoOffset + kTaggedSize == |
592 | kDeoptimizationDataOffset); |
593 | STATIC_ASSERT(kDeoptimizationDataOffset + kTaggedSize == |
594 | kSourcePositionTableOffset); |
595 | STATIC_ASSERT(kSourcePositionTableOffset + kTaggedSize == |
596 | kCodeDataContainerOffset); |
597 | STATIC_ASSERT(kCodeDataContainerOffset + kTaggedSize == kDataStart); |
598 | |
599 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
600 | // Slots in code can't be invalid because we never trim code objects. |
601 | return true; |
602 | } |
603 | |
604 | static constexpr int kRelocModeMask = |
605 | RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
606 | RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) | |
607 | RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
608 | RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
609 | RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | |
610 | RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) | |
611 | RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) | |
612 | RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
613 | |
614 | template <typename ObjectVisitor> |
615 | static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) { |
616 | // GC does not visit data/code in the header and in the body directly. |
617 | IteratePointers(obj, kRelocationInfoOffset, kDataStart, v); |
618 | |
619 | RelocIterator it(Code::cast(obj), kRelocModeMask); |
620 | v->VisitRelocInfo(&it); |
621 | } |
622 | |
623 | template <typename ObjectVisitor> |
624 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
625 | ObjectVisitor* v) { |
626 | IterateBody(map, obj, v); |
627 | } |
628 | |
629 | static inline int SizeOf(Map map, HeapObject object) { |
630 | return Code::unchecked_cast(object)->CodeSize(); |
631 | } |
632 | }; |
633 | |
634 | class SeqOneByteString::BodyDescriptor final : public BodyDescriptorBase { |
635 | public: |
636 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } |
637 | |
638 | template <typename ObjectVisitor> |
639 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
640 | ObjectVisitor* v) {} |
641 | |
642 | static inline int SizeOf(Map map, HeapObject obj) { |
643 | SeqOneByteString string = SeqOneByteString::cast(obj); |
644 | return string->SizeFor(string->synchronized_length()); |
645 | } |
646 | }; |
647 | |
648 | class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase { |
649 | public: |
650 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } |
651 | |
652 | template <typename ObjectVisitor> |
653 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
654 | ObjectVisitor* v) {} |
655 | |
656 | static inline int SizeOf(Map map, HeapObject obj) { |
657 | SeqTwoByteString string = SeqTwoByteString::cast(obj); |
658 | return string->SizeFor(string->synchronized_length()); |
659 | } |
660 | }; |
661 | |
662 | class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase { |
663 | public: |
664 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
665 | SLOW_DCHECK(std::is_sorted(std::begin(kTaggedFieldOffsets), |
666 | std::end(kTaggedFieldOffsets))); |
667 | STATIC_ASSERT(sizeof(*kTaggedFieldOffsets) == sizeof(uint16_t)); |
668 | if (offset < int{8 * sizeof(*kTaggedFieldOffsets)} && |
669 | std::binary_search(std::begin(kTaggedFieldOffsets), |
670 | std::end(kTaggedFieldOffsets), |
671 | static_cast<uint16_t>(offset))) { |
672 | return true; |
673 | } |
674 | return IsValidJSObjectSlotImpl(map, obj, offset); |
675 | } |
676 | |
677 | template <typename ObjectVisitor> |
678 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
679 | ObjectVisitor* v) { |
680 | IteratePointers(obj, kPropertiesOrHashOffset, JSObject::kHeaderSize, v); |
681 | for (uint16_t offset : kTaggedFieldOffsets) { |
682 | IteratePointer(obj, offset, v); |
683 | } |
684 | IterateJSObjectBodyImpl(map, obj, kSize, object_size, v); |
685 | } |
686 | |
687 | static inline int SizeOf(Map map, HeapObject object) { |
688 | return map->instance_size(); |
689 | } |
690 | }; |
691 | |
692 | class Map::BodyDescriptor final : public BodyDescriptorBase { |
693 | public: |
694 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
695 | return offset >= Map::kPointerFieldsBeginOffset && |
696 | offset < Map::kPointerFieldsEndOffset; |
697 | } |
698 | |
699 | template <typename ObjectVisitor> |
700 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
701 | ObjectVisitor* v) { |
702 | IteratePointers(obj, Map::kPointerFieldsBeginOffset, |
703 | Map::kTransitionsOrPrototypeInfoOffset, v); |
704 | IterateMaybeWeakPointer(obj, kTransitionsOrPrototypeInfoOffset, v); |
705 | IteratePointers(obj, Map::kTransitionsOrPrototypeInfoOffset + kTaggedSize, |
706 | Map::kPointerFieldsEndOffset, v); |
707 | } |
708 | |
709 | static inline int SizeOf(Map map, HeapObject obj) { return Map::kSize; } |
710 | }; |
711 | |
712 | class DataHandler::BodyDescriptor final : public BodyDescriptorBase { |
713 | public: |
714 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
715 | return offset >= HeapObject::kHeaderSize; |
716 | } |
717 | |
718 | template <typename ObjectVisitor> |
719 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
720 | ObjectVisitor* v) { |
721 | static_assert(kSmiHandlerOffset < kData1Offset, |
722 | "Field order must be in sync with this iteration code" ); |
723 | static_assert(kData1Offset < kSizeWithData1, |
724 | "Field order must be in sync with this iteration code" ); |
725 | IteratePointers(obj, kSmiHandlerOffset, kData1Offset, v); |
726 | IterateMaybeWeakPointers(obj, kData1Offset, object_size, v); |
727 | } |
728 | |
729 | static inline int SizeOf(Map map, HeapObject object) { |
730 | return object->SizeFromMap(map); |
731 | } |
732 | }; |
733 | |
734 | class NativeContext::BodyDescriptor final : public BodyDescriptorBase { |
735 | public: |
736 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
737 | return offset < NativeContext::kEndOfTaggedFieldsOffset; |
738 | } |
739 | |
740 | template <typename ObjectVisitor> |
741 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
742 | ObjectVisitor* v) { |
743 | IteratePointers(obj, NativeContext::kStartOfStrongFieldsOffset, |
744 | NativeContext::kEndOfStrongFieldsOffset, v); |
745 | IterateCustomWeakPointers(obj, NativeContext::kStartOfWeakFieldsOffset, |
746 | NativeContext::kEndOfWeakFieldsOffset, v); |
747 | } |
748 | |
749 | static inline int SizeOf(Map map, HeapObject object) { |
750 | return NativeContext::kSize; |
751 | } |
752 | }; |
753 | |
754 | class CodeDataContainer::BodyDescriptor final : public BodyDescriptorBase { |
755 | public: |
756 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
757 | return offset >= CodeDataContainer::kHeaderSize && |
758 | offset < CodeDataContainer::kSize; |
759 | } |
760 | |
761 | template <typename ObjectVisitor> |
762 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
763 | ObjectVisitor* v) { |
764 | IteratePointers(obj, CodeDataContainer::kHeaderSize, |
765 | CodeDataContainer::kPointerFieldsStrongEndOffset, v); |
766 | IterateCustomWeakPointers( |
767 | obj, CodeDataContainer::kPointerFieldsStrongEndOffset, |
768 | CodeDataContainer::kPointerFieldsWeakEndOffset, v); |
769 | } |
770 | |
771 | static inline int SizeOf(Map map, HeapObject object) { |
772 | return CodeDataContainer::kSize; |
773 | } |
774 | }; |
775 | |
776 | class EmbedderDataArray::BodyDescriptor final : public BodyDescriptorBase { |
777 | public: |
778 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
779 | #ifdef V8_COMPRESS_POINTERS |
780 | STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize); |
781 | STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize)); |
782 | return (offset < EmbedderDataArray::kHeaderSize) || |
783 | (((offset - EmbedderDataArray::kHeaderSize) & |
784 | (kEmbedderDataSlotSize - 1)) == |
785 | EmbedderDataSlot::kTaggedPayloadOffset); |
786 | #else |
787 | STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize); |
788 | // We store raw aligned pointers as Smis, so it's safe to iterate the whole |
789 | // array. |
790 | return true; |
791 | #endif |
792 | } |
793 | |
794 | template <typename ObjectVisitor> |
795 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
796 | ObjectVisitor* v) { |
797 | #ifdef V8_COMPRESS_POINTERS |
798 | STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize); |
799 | // Iterate only tagged payload of the embedder slots and skip raw payload. |
800 | for (int offset = EmbedderDataArray::OffsetOfElementAt(0) + |
801 | EmbedderDataSlot::kTaggedPayloadOffset; |
802 | offset < object_size; offset += kEmbedderDataSlotSize) { |
803 | IteratePointer(obj, offset, v); |
804 | } |
805 | #else |
806 | // We store raw aligned pointers as Smis, so it's safe to iterate the whole |
807 | // array. |
808 | STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize); |
809 | IteratePointers(obj, EmbedderDataArray::kHeaderSize, object_size, v); |
810 | #endif |
811 | } |
812 | |
813 | static inline int SizeOf(Map map, HeapObject object) { |
814 | return object->SizeFromMap(map); |
815 | } |
816 | }; |
817 | |
818 | template <typename Op, typename ReturnType, typename T1, typename T2, |
819 | typename T3, typename T4> |
820 | ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) { |
821 | if (type < FIRST_NONSTRING_TYPE) { |
822 | switch (type & kStringRepresentationMask) { |
823 | case kSeqStringTag: |
824 | return ReturnType(); |
825 | case kConsStringTag: |
826 | return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3, p4); |
827 | case kThinStringTag: |
828 | return Op::template apply<ThinString::BodyDescriptor>(p1, p2, p3, p4); |
829 | case kSlicedStringTag: |
830 | return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3, p4); |
831 | case kExternalStringTag: |
832 | if ((type & kStringEncodingMask) == kOneByteStringTag) { |
833 | return Op::template apply<ExternalOneByteString::BodyDescriptor>( |
834 | p1, p2, p3, p4); |
835 | } else { |
836 | return Op::template apply<ExternalTwoByteString::BodyDescriptor>( |
837 | p1, p2, p3, p4); |
838 | } |
839 | } |
840 | UNREACHABLE(); |
841 | } |
842 | |
843 | switch (type) { |
844 | case EMBEDDER_DATA_ARRAY_TYPE: |
845 | return Op::template apply<EmbedderDataArray::BodyDescriptor>(p1, p2, p3, |
846 | p4); |
847 | case FIXED_ARRAY_TYPE: |
848 | case OBJECT_BOILERPLATE_DESCRIPTION_TYPE: |
849 | case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE: |
850 | case HASH_TABLE_TYPE: |
851 | case ORDERED_HASH_MAP_TYPE: |
852 | case ORDERED_HASH_SET_TYPE: |
853 | case ORDERED_NAME_DICTIONARY_TYPE: |
854 | case NAME_DICTIONARY_TYPE: |
855 | case GLOBAL_DICTIONARY_TYPE: |
856 | case NUMBER_DICTIONARY_TYPE: |
857 | case SIMPLE_NUMBER_DICTIONARY_TYPE: |
858 | case STRING_TABLE_TYPE: |
859 | case SCOPE_INFO_TYPE: |
860 | case SCRIPT_CONTEXT_TABLE_TYPE: |
861 | return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3, p4); |
862 | case EPHEMERON_HASH_TABLE_TYPE: |
863 | return Op::template apply<EphemeronHashTable::BodyDescriptor>(p1, p2, p3, |
864 | p4); |
865 | case AWAIT_CONTEXT_TYPE: |
866 | case BLOCK_CONTEXT_TYPE: |
867 | case CATCH_CONTEXT_TYPE: |
868 | case DEBUG_EVALUATE_CONTEXT_TYPE: |
869 | case EVAL_CONTEXT_TYPE: |
870 | case FUNCTION_CONTEXT_TYPE: |
871 | case MODULE_CONTEXT_TYPE: |
872 | case SCRIPT_CONTEXT_TYPE: |
873 | case WITH_CONTEXT_TYPE: |
874 | return Op::template apply<Context::BodyDescriptor>(p1, p2, p3, p4); |
875 | case NATIVE_CONTEXT_TYPE: |
876 | return Op::template apply<NativeContext::BodyDescriptor>(p1, p2, p3, p4); |
877 | case WEAK_FIXED_ARRAY_TYPE: |
878 | return Op::template apply<WeakFixedArray::BodyDescriptor>(p1, p2, p3, p4); |
879 | case WEAK_ARRAY_LIST_TYPE: |
880 | return Op::template apply<WeakArrayList::BodyDescriptor>(p1, p2, p3, p4); |
881 | case FIXED_DOUBLE_ARRAY_TYPE: |
882 | return ReturnType(); |
883 | case FEEDBACK_METADATA_TYPE: |
884 | return Op::template apply<FeedbackMetadata::BodyDescriptor>(p1, p2, p3, |
885 | p4); |
886 | case PROPERTY_ARRAY_TYPE: |
887 | return Op::template apply<PropertyArray::BodyDescriptor>(p1, p2, p3, p4); |
888 | case DESCRIPTOR_ARRAY_TYPE: |
889 | return Op::template apply<DescriptorArray::BodyDescriptor>(p1, p2, p3, |
890 | p4); |
891 | case TRANSITION_ARRAY_TYPE: |
892 | return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3, |
893 | p4); |
894 | case FEEDBACK_CELL_TYPE: |
895 | return Op::template apply<FeedbackCell::BodyDescriptor>(p1, p2, p3, p4); |
896 | case FEEDBACK_VECTOR_TYPE: |
897 | return Op::template apply<FeedbackVector::BodyDescriptor>(p1, p2, p3, p4); |
898 | case JS_OBJECT_TYPE: |
899 | case JS_ERROR_TYPE: |
900 | case JS_ARGUMENTS_TYPE: |
901 | case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE: |
902 | case JS_PROMISE_TYPE: |
903 | case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
904 | case JS_GENERATOR_OBJECT_TYPE: |
905 | case JS_ASYNC_FUNCTION_OBJECT_TYPE: |
906 | case JS_ASYNC_GENERATOR_OBJECT_TYPE: |
907 | case JS_VALUE_TYPE: |
908 | case JS_DATE_TYPE: |
909 | case JS_ARRAY_TYPE: |
910 | case JS_ARRAY_ITERATOR_TYPE: |
911 | case JS_MODULE_NAMESPACE_TYPE: |
912 | case JS_SET_TYPE: |
913 | case JS_MAP_TYPE: |
914 | case JS_SET_KEY_VALUE_ITERATOR_TYPE: |
915 | case JS_SET_VALUE_ITERATOR_TYPE: |
916 | case JS_MAP_KEY_ITERATOR_TYPE: |
917 | case JS_MAP_KEY_VALUE_ITERATOR_TYPE: |
918 | case JS_MAP_VALUE_ITERATOR_TYPE: |
919 | case JS_STRING_ITERATOR_TYPE: |
920 | case JS_REGEXP_STRING_ITERATOR_TYPE: |
921 | case JS_REGEXP_TYPE: |
922 | case JS_GLOBAL_PROXY_TYPE: |
923 | case JS_GLOBAL_OBJECT_TYPE: |
924 | case JS_API_OBJECT_TYPE: |
925 | case JS_SPECIAL_API_OBJECT_TYPE: |
926 | case JS_MESSAGE_OBJECT_TYPE: |
927 | case JS_BOUND_FUNCTION_TYPE: |
928 | case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE: |
929 | case JS_FINALIZATION_GROUP_TYPE: |
930 | #ifdef V8_INTL_SUPPORT |
931 | case JS_INTL_V8_BREAK_ITERATOR_TYPE: |
932 | case JS_INTL_COLLATOR_TYPE: |
933 | case JS_INTL_DATE_TIME_FORMAT_TYPE: |
934 | case JS_INTL_LIST_FORMAT_TYPE: |
935 | case JS_INTL_LOCALE_TYPE: |
936 | case JS_INTL_NUMBER_FORMAT_TYPE: |
937 | case JS_INTL_PLURAL_RULES_TYPE: |
938 | case JS_INTL_RELATIVE_TIME_FORMAT_TYPE: |
939 | case JS_INTL_SEGMENT_ITERATOR_TYPE: |
940 | case JS_INTL_SEGMENTER_TYPE: |
941 | #endif // V8_INTL_SUPPORT |
942 | case WASM_EXCEPTION_TYPE: |
943 | case WASM_GLOBAL_TYPE: |
944 | case WASM_MEMORY_TYPE: |
945 | case WASM_MODULE_TYPE: |
946 | case WASM_TABLE_TYPE: |
947 | return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3, p4); |
948 | case WASM_INSTANCE_TYPE: |
949 | return Op::template apply<WasmInstanceObject::BodyDescriptor>(p1, p2, p3, |
950 | p4); |
951 | case JS_WEAK_MAP_TYPE: |
952 | case JS_WEAK_SET_TYPE: |
953 | return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3, |
954 | p4); |
955 | case JS_ARRAY_BUFFER_TYPE: |
956 | return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3, p4); |
957 | case JS_DATA_VIEW_TYPE: |
958 | return Op::template apply<JSDataView::BodyDescriptor>(p1, p2, p3, p4); |
959 | case JS_TYPED_ARRAY_TYPE: |
960 | return Op::template apply<JSTypedArray::BodyDescriptor>(p1, p2, p3, p4); |
961 | case JS_FUNCTION_TYPE: |
962 | return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3, p4); |
963 | case WEAK_CELL_TYPE: |
964 | return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3, p4); |
965 | case JS_WEAK_REF_TYPE: |
966 | return Op::template apply<JSWeakRef::BodyDescriptor>(p1, p2, p3, p4); |
967 | case ODDBALL_TYPE: |
968 | return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3, p4); |
969 | case JS_PROXY_TYPE: |
970 | return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3, p4); |
971 | case FOREIGN_TYPE: |
972 | return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3, p4); |
973 | case MAP_TYPE: |
974 | return Op::template apply<Map::BodyDescriptor>(p1, p2, p3, p4); |
975 | case CODE_TYPE: |
976 | return Op::template apply<Code::BodyDescriptor>(p1, p2, p3, p4); |
977 | case CELL_TYPE: |
978 | return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3, p4); |
979 | case PROPERTY_CELL_TYPE: |
980 | return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3, p4); |
981 | case SYMBOL_TYPE: |
982 | return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3, p4); |
983 | case BYTECODE_ARRAY_TYPE: |
984 | return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3, p4); |
985 | case SMALL_ORDERED_HASH_SET_TYPE: |
986 | return Op::template apply< |
987 | SmallOrderedHashTable<SmallOrderedHashSet>::BodyDescriptor>(p1, p2, |
988 | p3, p4); |
989 | case SMALL_ORDERED_HASH_MAP_TYPE: |
990 | return Op::template apply< |
991 | SmallOrderedHashTable<SmallOrderedHashMap>::BodyDescriptor>(p1, p2, |
992 | p3, p4); |
993 | case SMALL_ORDERED_NAME_DICTIONARY_TYPE: |
994 | return Op::template apply< |
995 | SmallOrderedHashTable<SmallOrderedNameDictionary>::BodyDescriptor>( |
996 | p1, p2, p3, p4); |
997 | case CODE_DATA_CONTAINER_TYPE: |
998 | return Op::template apply<CodeDataContainer::BodyDescriptor>(p1, p2, p3, |
999 | p4); |
1000 | case PREPARSE_DATA_TYPE: |
1001 | return Op::template apply<PreparseData::BodyDescriptor>(p1, p2, p3, p4); |
1002 | case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE: |
1003 | return Op::template apply< |
1004 | UncompiledDataWithoutPreparseData::BodyDescriptor>(p1, p2, p3, p4); |
1005 | case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE: |
1006 | return Op::template apply<UncompiledDataWithPreparseData::BodyDescriptor>( |
1007 | p1, p2, p3, p4); |
1008 | case HEAP_NUMBER_TYPE: |
1009 | case MUTABLE_HEAP_NUMBER_TYPE: |
1010 | case FILLER_TYPE: |
1011 | case BYTE_ARRAY_TYPE: |
1012 | case FREE_SPACE_TYPE: |
1013 | case BIGINT_TYPE: |
1014 | return ReturnType(); |
1015 | |
1016 | #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \ |
1017 | case FIXED_##TYPE##_ARRAY_TYPE: \ |
1018 | return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3, \ |
1019 | p4); |
1020 | TYPED_ARRAYS(TYPED_ARRAY_CASE) |
1021 | #undef TYPED_ARRAY_CASE |
1022 | |
1023 | case SHARED_FUNCTION_INFO_TYPE: { |
1024 | return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3, |
1025 | p4); |
1026 | } |
1027 | case ALLOCATION_SITE_TYPE: |
1028 | return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3, p4); |
1029 | |
1030 | #define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE: |
1031 | STRUCT_LIST(MAKE_STRUCT_CASE) |
1032 | #undef MAKE_STRUCT_CASE |
1033 | if (type == PROTOTYPE_INFO_TYPE) { |
1034 | return Op::template apply<PrototypeInfo::BodyDescriptor>(p1, p2, p3, |
1035 | p4); |
1036 | } else { |
1037 | return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4); |
1038 | } |
1039 | case CALL_HANDLER_INFO_TYPE: |
1040 | return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4); |
1041 | case LOAD_HANDLER_TYPE: |
1042 | case STORE_HANDLER_TYPE: |
1043 | return Op::template apply<DataHandler::BodyDescriptor>(p1, p2, p3, p4); |
1044 | default: |
1045 | PrintF("Unknown type: %d\n" , type); |
1046 | UNREACHABLE(); |
1047 | } |
1048 | } |
1049 | |
1050 | |
1051 | template <typename ObjectVisitor> |
1052 | void HeapObject::IterateFast(ObjectVisitor* v) { |
1053 | BodyDescriptorBase::IteratePointer(*this, kMapOffset, v); |
1054 | IterateBodyFast(v); |
1055 | } |
1056 | |
1057 | |
1058 | template <typename ObjectVisitor> |
1059 | void HeapObject::IterateBodyFast(ObjectVisitor* v) { |
1060 | Map m = map(); |
1061 | IterateBodyFast(m, SizeFromMap(m), v); |
1062 | } |
1063 | |
1064 | |
1065 | struct CallIterateBody { |
1066 | template <typename BodyDescriptor, typename ObjectVisitor> |
1067 | static void apply(Map map, HeapObject obj, int object_size, |
1068 | ObjectVisitor* v) { |
1069 | BodyDescriptor::IterateBody(map, obj, object_size, v); |
1070 | } |
1071 | }; |
1072 | |
1073 | template <typename ObjectVisitor> |
1074 | void HeapObject::IterateBodyFast(Map map, int object_size, ObjectVisitor* v) { |
1075 | BodyDescriptorApply<CallIterateBody, void>(map->instance_type(), map, *this, |
1076 | object_size, v); |
1077 | } |
1078 | |
1079 | class EphemeronHashTable::BodyDescriptor final : public BodyDescriptorBase { |
1080 | public: |
1081 | static bool IsValidSlot(Map map, HeapObject obj, int offset) { |
1082 | return (offset >= EphemeronHashTable::kHeaderSize); |
1083 | } |
1084 | |
1085 | template <typename ObjectVisitor> |
1086 | static inline void IterateBody(Map map, HeapObject obj, int object_size, |
1087 | ObjectVisitor* v) { |
1088 | int entries_start = EphemeronHashTable::kHeaderSize + |
1089 | EphemeronHashTable::kElementsStartIndex * kTaggedSize; |
1090 | IteratePointers(obj, EphemeronHashTable::kHeaderSize, entries_start, v); |
1091 | EphemeronHashTable table = EphemeronHashTable::unchecked_cast(obj); |
1092 | int entries = table.Capacity(); |
1093 | for (int i = 0; i < entries; ++i) { |
1094 | const int key_index = EphemeronHashTable::EntryToIndex(i); |
1095 | const int value_index = EphemeronHashTable::EntryToValueIndex(i); |
1096 | IterateEphemeron(obj, i, OffsetOfElementAt(key_index), |
1097 | OffsetOfElementAt(value_index), v); |
1098 | } |
1099 | } |
1100 | |
1101 | static inline int SizeOf(Map map, HeapObject object) { |
1102 | return object->SizeFromMap(map); |
1103 | } |
1104 | }; |
1105 | |
1106 | } // namespace internal |
1107 | } // namespace v8 |
1108 | |
1109 | #endif // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_ |
1110 | |