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