Line data Source code
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 2025088 : int FlexibleBodyDescriptor<start_offset>::SizeOf(Map map, HeapObject object) {
30 27930105 : return object->SizeFromMap(map);
31 : }
32 :
33 : template <int start_offset>
34 844763 : int FlexibleWeakBodyDescriptor<start_offset>::SizeOf(Map map,
35 : HeapObject object) {
36 11137126 : return object->SizeFromMap(map);
37 : }
38 :
39 38 : 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 38 : 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 0 : LayoutDescriptorHelper helper(map);
67 : DCHECK(!helper.all_fields_tagged());
68 0 : return helper.IsTagged(offset);
69 : }
70 : }
71 :
72 : template <typename ObjectVisitor>
73 87468860 : 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 87468860 : if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) {
102 37468835 : 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 202197 : LayoutDescriptorHelper helper(map);
109 : DCHECK(!helper.all_fields_tagged());
110 1126191 : for (int offset = start_offset; offset < end_offset;) {
111 : int end_of_region_offset;
112 461248 : if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
113 261562 : IteratePointers(obj, offset, end_of_region_offset, v);
114 : }
115 462504 : offset = end_of_region_offset;
116 : }
117 : }
118 87861589 : }
119 :
120 : template <typename ObjectVisitor>
121 285914138 : DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(HeapObject obj,
122 : int start_offset,
123 : int end_offset,
124 : ObjectVisitor* v) {
125 432776967 : v->VisitPointers(obj, obj.RawField(start_offset), obj.RawField(end_offset));
126 286371940 : }
127 :
128 : template <typename ObjectVisitor>
129 6120226 : void BodyDescriptorBase::IteratePointer(HeapObject obj, int offset,
130 : ObjectVisitor* v) {
131 42744495 : v->VisitPointer(obj, obj.RawField(offset));
132 6120226 : }
133 :
134 : template <typename ObjectVisitor>
135 8456441 : DISABLE_CFI_PERF void BodyDescriptorBase::IterateMaybeWeakPointers(
136 : HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) {
137 5726840 : v->VisitPointers(obj, obj.RawMaybeWeakField(start_offset),
138 : obj.RawMaybeWeakField(end_offset));
139 8485891 : }
140 :
141 : template <typename ObjectVisitor>
142 15770972 : void BodyDescriptorBase::IterateMaybeWeakPointer(HeapObject obj, int offset,
143 : ObjectVisitor* v) {
144 37215711 : v->VisitPointer(obj, obj.RawMaybeWeakField(offset));
145 15770971 : }
146 :
147 : template <typename ObjectVisitor>
148 : DISABLE_CFI_PERF void BodyDescriptorBase::IterateCustomWeakPointers(
149 : HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) {
150 6324726 : 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 223050 : 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 132459441 : 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 38 : if (offset < kStartOffset) return false;
176 38 : return IsValidJSObjectSlotImpl(map, obj, offset);
177 : }
178 :
179 : template <typename ObjectVisitor>
180 13130 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
181 : ObjectVisitor* v) {
182 86475538 : IterateJSObjectBodyImpl(map, obj, kStartOffset, object_size, v);
183 13130 : }
184 :
185 13130 : static inline int SizeOf(Map map, HeapObject object) {
186 13130 : 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 3755463 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
200 : ObjectVisitor* v) {
201 21767477 : IteratePointers(obj, kStartOffset, object_size, v);
202 3755462 : }
203 :
204 3755463 : static inline int SizeOf(Map map, HeapObject object) {
205 3755463 : 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 0 : return offset >= HeapObject::kHeaderSize;
213 : }
214 :
215 : template <typename ObjectVisitor>
216 361 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
217 : ObjectVisitor* v) {
218 341 : IteratePointers(obj, HeapObject::kHeaderSize, kTargetOffset, v);
219 : IterateCustomWeakPointer(obj, kTargetOffset, v);
220 341 : IteratePointers(obj, kTargetOffset + kTaggedSize, object_size, v);
221 361 : }
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 0 : return IsValidJSObjectSlotImpl(map, obj, offset);
232 : }
233 :
234 : template <typename ObjectVisitor>
235 350 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
236 : ObjectVisitor* v) {
237 157 : IteratePointers(obj, JSReceiver::kPropertiesOrHashOffset, kTargetOffset, v);
238 : IterateCustomWeakPointer(obj, kTargetOffset, v);
239 350 : IterateJSObjectBodyImpl(map, obj, kTargetOffset + kTaggedSize, object_size,
240 : v);
241 350 : }
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 66229116 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
258 : ObjectVisitor* v) {
259 : IterateCustomWeakPointer(obj, kFunctionDataOffset, v);
260 22856170 : IteratePointers(obj, SharedFunctionInfo::kStartOfStrongFieldsOffset,
261 : SharedFunctionInfo::kEndOfTaggedFieldsOffset, v);
262 65351339 : }
263 :
264 3999197 : static inline int SizeOf(Map map, HeapObject object) {
265 3999197 : 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 0 : static bool IsValidSlot(Map map, HeapObject obj, int offset) {
279 0 : if (offset >= AllocationSite::kStartOffset &&
280 : offset < AllocationSite::kCommonPointerFieldEndOffset) {
281 : return true;
282 : }
283 : // check for weak_next offset
284 0 : if (map->instance_size() == AllocationSite::kSizeWithWeakNext &&
285 : offset == AllocationSite::kWeakNextOffset) {
286 : return true;
287 : }
288 : return false;
289 : }
290 :
291 : template <typename ObjectVisitor>
292 1868374 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
293 : ObjectVisitor* v) {
294 : // Iterate over all the common pointer fields
295 1861578 : 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 183097 : if (object_size == AllocationSite::kSizeWithWeakNext) {
300 : IterateCustomWeakPointers(obj, AllocationSite::kWeakNextOffset,
301 : AllocationSite::kSizeWithWeakNext, v);
302 : }
303 1842173 : }
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 0 : if (offset < kEndOfTaggedFieldsOffset) return true;
314 0 : if (offset < kHeaderSize) return false;
315 0 : return IsValidJSObjectSlotImpl(map, obj, offset);
316 : }
317 :
318 : template <typename ObjectVisitor>
319 462074 : 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 163521 : IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
323 462242 : IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
324 462458 : }
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 0 : if (offset < kEndOfTaggedFieldsOffset) return true;
335 0 : if (offset < kHeaderSize) return false;
336 0 : return IsValidJSObjectSlotImpl(map, obj, offset);
337 : }
338 :
339 : template <typename ObjectVisitor>
340 299049 : 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 201300 : IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
344 301396 : IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
345 298312 : }
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 0 : (offset < table->GetBucketsStartOffset());
361 : }
362 :
363 : template <typename ObjectVisitor>
364 0 : 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 0 : IteratePointers(obj, start_offset, end_offset, v);
370 0 : }
371 :
372 0 : static inline int SizeOf(Map map, HeapObject obj) {
373 : Derived table = Derived::cast(obj);
374 0 : 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 0 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
384 0 : 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 0 : return offset >= kConstantPoolOffset &&
395 0 : offset <= kSourcePositionTableOffset;
396 : }
397 :
398 : template <typename ObjectVisitor>
399 2089176 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
400 : ObjectVisitor* v) {
401 605913 : IteratePointer(obj, kConstantPoolOffset, v);
402 605913 : IteratePointer(obj, kHandlerTableOffset, v);
403 605913 : IteratePointer(obj, kSourcePositionTableOffset, v);
404 2093166 : }
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 0 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
418 0 : 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 0 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
431 0 : 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 0 : return offset == kBasePointerOffset;
443 : }
444 :
445 : template <typename ObjectVisitor>
446 3771 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
447 : ObjectVisitor* v) {
448 72243 : IteratePointer(obj, kBasePointerOffset, v);
449 3771 : }
450 :
451 3771 : static inline int SizeOf(Map map, HeapObject object) {
452 454825 : 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 0 : return offset == kSharedFunctionInfoOffset ||
474 0 : offset == kOptimizedCodeOffset ||
475 0 : offset == kClosureFeedbackCellArrayOffset ||
476 0 : offset >= kFeedbackSlotsOffset;
477 : }
478 :
479 : template <typename ObjectVisitor>
480 4449852 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
481 : ObjectVisitor* v) {
482 2013420 : IteratePointer(obj, kSharedFunctionInfoOffset, v);
483 2013420 : IterateMaybeWeakPointer(obj, kOptimizedCodeOffset, v);
484 2013420 : IteratePointer(obj, kClosureFeedbackCellArrayOffset, v);
485 2013440 : IterateMaybeWeakPointers(obj, kFeedbackSlotsOffset, object_size, v);
486 4447149 : }
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 0 : return offset >= PreparseData::cast(obj)->inner_start_offset();
497 : }
498 :
499 : template <typename ObjectVisitor>
500 63623 : 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 63623 : int end_offset = start_offset + data->children_length() * kTaggedSize;
505 11809 : IteratePointers(obj, start_offset, end_offset, v);
506 63618 : }
507 :
508 1070 : static inline int SizeOf(Map map, HeapObject obj) {
509 : PreparseData data = PreparseData::cast(obj);
510 1070 : 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 0 : return offset >= HeapObject::kHeaderSize;
518 : }
519 :
520 : template <typename ObjectVisitor>
521 5467380 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
522 : ObjectVisitor* v) {
523 1921226 : IteratePointers(obj, HeapObject::kHeaderSize, kObjectCreateMapOffset, v);
524 1921226 : IterateMaybeWeakPointer(obj, kObjectCreateMapOffset, v);
525 1921226 : IteratePointers(obj, kObjectCreateMapOffset + kTaggedSize, object_size, v);
526 5464849 : }
527 :
528 78730 : static inline int SizeOf(Map map, HeapObject obj) {
529 5275113 : 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 0 : return IsValidJSObjectSlotImpl(map, obj, offset);
539 : }
540 :
541 : template <typename ObjectVisitor>
542 0 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
543 : ObjectVisitor* v) {
544 126789 : IterateJSObjectBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v);
545 0 : }
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 5962008 : 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 117584544 : 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 32176214 : IteratePointers(obj, kRelocationInfoOffset, kDataStart, v);
618 :
619 121045079 : RelocIterator it(Code::cast(obj), kRelocModeMask);
620 120394401 : v->VisitRelocInfo(&it);
621 118746773 : }
622 :
623 : template <typename ObjectVisitor>
624 82404955 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
625 : ObjectVisitor* v) {
626 117548707 : IterateBody(map, obj, v);
627 83643565 : }
628 :
629 : static inline int SizeOf(Map map, HeapObject object) {
630 202671216 : 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 0 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
640 0 : ObjectVisitor* v) {}
641 :
642 5366360 : static inline int SizeOf(Map map, HeapObject obj) {
643 : SeqOneByteString string = SeqOneByteString::cast(obj);
644 5366360 : 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 0 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
654 0 : ObjectVisitor* v) {}
655 :
656 351426 : static inline int SizeOf(Map map, HeapObject obj) {
657 : SeqTwoByteString string = SeqTwoByteString::cast(obj);
658 351426 : return string->SizeFor(string->synchronized_length());
659 : }
660 : };
661 :
662 : class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
663 : public:
664 0 : 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 0 : if (offset < int{8 * sizeof(*kTaggedFieldOffsets)} &&
669 0 : std::binary_search(std::begin(kTaggedFieldOffsets),
670 : std::end(kTaggedFieldOffsets),
671 : static_cast<uint16_t>(offset))) {
672 : return true;
673 : }
674 0 : return IsValidJSObjectSlotImpl(map, obj, offset);
675 : }
676 :
677 : template <typename ObjectVisitor>
678 34551 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
679 : ObjectVisitor* v) {
680 11965 : IteratePointers(obj, kPropertiesOrHashOffset, JSObject::kHeaderSize, v);
681 1208190 : for (uint16_t offset : kTaggedFieldOffsets) {
682 203405 : IteratePointer(obj, offset, v);
683 : }
684 34545 : IterateJSObjectBodyImpl(map, obj, kSize, object_size, v);
685 34546 : }
686 :
687 559 : static inline int SizeOf(Map map, HeapObject object) {
688 559 : 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 0 : return offset >= Map::kPointerFieldsBeginOffset &&
696 0 : offset < Map::kPointerFieldsEndOffset;
697 : }
698 :
699 : template <typename ObjectVisitor>
700 40729900 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
701 : ObjectVisitor* v) {
702 11836326 : IteratePointers(obj, Map::kPointerFieldsBeginOffset,
703 : Map::kTransitionsOrPrototypeInfoOffset, v);
704 11836325 : IterateMaybeWeakPointer(obj, kTransitionsOrPrototypeInfoOffset, v);
705 11836325 : IteratePointers(obj, Map::kTransitionsOrPrototypeInfoOffset + kTaggedSize,
706 : Map::kPointerFieldsEndOffset, v);
707 40017599 : }
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 0 : return offset >= HeapObject::kHeaderSize;
716 : }
717 :
718 : template <typename ObjectVisitor>
719 926398 : 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 271988 : IteratePointers(obj, kSmiHandlerOffset, kData1Offset, v);
726 271988 : IterateMaybeWeakPointers(obj, kData1Offset, object_size, v);
727 924586 : }
728 :
729 : static inline int SizeOf(Map map, HeapObject object) {
730 883282 : 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 0 : return offset < NativeContext::kEndOfTaggedFieldsOffset;
738 : }
739 :
740 : template <typename ObjectVisitor>
741 56454 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
742 : ObjectVisitor* v) {
743 34362 : IteratePointers(obj, NativeContext::kStartOfStrongFieldsOffset,
744 : NativeContext::kEndOfStrongFieldsOffset, v);
745 : IterateCustomWeakPointers(obj, NativeContext::kStartOfWeakFieldsOffset,
746 : NativeContext::kEndOfWeakFieldsOffset, v);
747 56457 : }
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 0 : return offset >= CodeDataContainer::kHeaderSize &&
758 0 : offset < CodeDataContainer::kSize;
759 : }
760 :
761 : template <typename ObjectVisitor>
762 88178476 : static inline void IterateBody(Map map, HeapObject obj, int object_size,
763 : ObjectVisitor* v) {
764 32031565 : IteratePointers(obj, CodeDataContainer::kHeaderSize,
765 : CodeDataContainer::kPointerFieldsStrongEndOffset, v);
766 : IterateCustomWeakPointers(
767 : obj, CodeDataContainer::kPointerFieldsStrongEndOffset,
768 : CodeDataContainer::kPointerFieldsWeakEndOffset, v);
769 87486094 : }
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 0 : 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 56400 : IteratePointers(obj, EmbedderDataArray::kHeaderSize, object_size, v);
810 : #endif
811 0 : }
812 :
813 : static inline int SizeOf(Map map, HeapObject object) {
814 109161 : return object->SizeFromMap(map);
815 : }
816 : };
817 :
818 : template <typename Op, typename ReturnType, typename T1, typename T2,
819 : typename T3, typename T4>
820 128742270 : ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
821 128742270 : if (type < FIRST_NONSTRING_TYPE) {
822 69608274 : switch (type & kStringRepresentationMask) {
823 : case kSeqStringTag:
824 : return ReturnType();
825 : case kConsStringTag:
826 0 : return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3, p4);
827 : case kThinStringTag:
828 15 : return Op::template apply<ThinString::BodyDescriptor>(p1, p2, p3, p4);
829 : case kSlicedStringTag:
830 0 : 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 0 : UNREACHABLE();
841 : }
842 :
843 59133996 : 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 10 : 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 0 : 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 0 : return Op::template apply<Context::BodyDescriptor>(p1, p2, p3, p4);
875 : case NATIVE_CONTEXT_TYPE:
876 0 : return Op::template apply<NativeContext::BodyDescriptor>(p1, p2, p3, p4);
877 : case WEAK_FIXED_ARRAY_TYPE:
878 0 : return Op::template apply<WeakFixedArray::BodyDescriptor>(p1, p2, p3, p4);
879 : case WEAK_ARRAY_LIST_TYPE:
880 0 : return Op::template apply<WeakArrayList::BodyDescriptor>(p1, p2, p3, p4);
881 : case FIXED_DOUBLE_ARRAY_TYPE:
882 0 : return ReturnType();
883 : case FEEDBACK_METADATA_TYPE:
884 : return Op::template apply<FeedbackMetadata::BodyDescriptor>(p1, p2, p3,
885 0 : p4);
886 : case PROPERTY_ARRAY_TYPE:
887 0 : 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 0 : p4);
891 : case TRANSITION_ARRAY_TYPE:
892 : return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3,
893 0 : p4);
894 : case FEEDBACK_CELL_TYPE:
895 0 : return Op::template apply<FeedbackCell::BodyDescriptor>(p1, p2, p3, p4);
896 : case FEEDBACK_VECTOR_TYPE:
897 0 : 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 35 : 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 0 : p4);
951 : case JS_WEAK_MAP_TYPE:
952 : case JS_WEAK_SET_TYPE:
953 : return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3,
954 0 : p4);
955 : case JS_ARRAY_BUFFER_TYPE:
956 0 : return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3, p4);
957 : case JS_DATA_VIEW_TYPE:
958 0 : return Op::template apply<JSDataView::BodyDescriptor>(p1, p2, p3, p4);
959 : case JS_TYPED_ARRAY_TYPE:
960 0 : return Op::template apply<JSTypedArray::BodyDescriptor>(p1, p2, p3, p4);
961 : case JS_FUNCTION_TYPE:
962 3 : return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3, p4);
963 : case WEAK_CELL_TYPE:
964 0 : return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3, p4);
965 : case JS_WEAK_REF_TYPE:
966 0 : return Op::template apply<JSWeakRef::BodyDescriptor>(p1, p2, p3, p4);
967 : case ODDBALL_TYPE:
968 0 : return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3, p4);
969 : case JS_PROXY_TYPE:
970 0 : return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3, p4);
971 : case FOREIGN_TYPE:
972 0 : return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3, p4);
973 : case MAP_TYPE:
974 0 : 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 0 : return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3, p4);
979 : case PROPERTY_CELL_TYPE:
980 0 : return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3, p4);
981 : case SYMBOL_TYPE:
982 0 : return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3, p4);
983 : case BYTECODE_ARRAY_TYPE:
984 0 : 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 0 : p3, p4);
989 : case SMALL_ORDERED_HASH_MAP_TYPE:
990 : return Op::template apply<
991 : SmallOrderedHashTable<SmallOrderedHashMap>::BodyDescriptor>(p1, p2,
992 0 : p3, p4);
993 : case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
994 : return Op::template apply<
995 : SmallOrderedHashTable<SmallOrderedNameDictionary>::BodyDescriptor>(
996 0 : p1, p2, p3, p4);
997 : case CODE_DATA_CONTAINER_TYPE:
998 : return Op::template apply<CodeDataContainer::BodyDescriptor>(p1, p2, p3,
999 0 : p4);
1000 : case PREPARSE_DATA_TYPE:
1001 0 : return Op::template apply<PreparseData::BodyDescriptor>(p1, p2, p3, p4);
1002 : case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE:
1003 : return Op::template apply<
1004 0 : UncompiledDataWithoutPreparseData::BodyDescriptor>(p1, p2, p3, p4);
1005 : case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE:
1006 : return Op::template apply<UncompiledDataWithPreparseData::BodyDescriptor>(
1007 0 : 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 383105 : 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 0 : 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 0 : p4);
1026 : }
1027 : case ALLOCATION_SITE_TYPE:
1028 0 : 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 999013 : if (type == PROTOTYPE_INFO_TYPE) {
1034 : return Op::template apply<PrototypeInfo::BodyDescriptor>(p1, p2, p3,
1035 0 : p4);
1036 : } else {
1037 0 : return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
1038 : }
1039 : case CALL_HANDLER_INFO_TYPE:
1040 0 : return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
1041 : case LOAD_HANDLER_TYPE:
1042 : case STORE_HANDLER_TYPE:
1043 0 : return Op::template apply<DataHandler::BodyDescriptor>(p1, p2, p3, p4);
1044 : default:
1045 0 : PrintF("Unknown type: %d\n", type);
1046 0 : UNREACHABLE();
1047 : }
1048 : }
1049 :
1050 :
1051 : template <typename ObjectVisitor>
1052 13504281 : void HeapObject::IterateFast(ObjectVisitor* v) {
1053 : BodyDescriptorBase::IteratePointer(*this, kMapOffset, v);
1054 13504281 : IterateBodyFast(v);
1055 13504281 : }
1056 :
1057 :
1058 : template <typename ObjectVisitor>
1059 23601929 : void HeapObject::IterateBodyFast(ObjectVisitor* v) {
1060 : Map m = map();
1061 23601929 : IterateBodyFast(m, SizeFromMap(m), v);
1062 23601517 : }
1063 :
1064 :
1065 : struct CallIterateBody {
1066 : template <typename BodyDescriptor, typename ObjectVisitor>
1067 0 : static void apply(Map map, HeapObject obj, int object_size,
1068 : ObjectVisitor* v) {
1069 3459946 : BodyDescriptor::IterateBody(map, obj, object_size, v);
1070 0 : }
1071 : };
1072 :
1073 : template <typename ObjectVisitor>
1074 : void HeapObject::IterateBodyFast(Map map, int object_size, ObjectVisitor* v) {
1075 129374179 : 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 0 : return (offset >= EphemeronHashTable::kHeaderSize);
1083 : }
1084 :
1085 : template <typename ObjectVisitor>
1086 45864 : 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 39128 : IteratePointers(obj, EphemeronHashTable::kHeaderSize, entries_start, v);
1091 : EphemeronHashTable table = EphemeronHashTable::unchecked_cast(obj);
1092 : int entries = table.Capacity();
1093 425596 : 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 45860 : }
1100 :
1101 : static inline int SizeOf(Map map, HeapObject object) {
1102 0 : return object->SizeFromMap(map);
1103 : }
1104 : };
1105 :
1106 : } // namespace internal
1107 : } // namespace v8
1108 :
1109 : #endif // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
|