• 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/ic/handler-configuration.h"
12 #include "src/objects/arguments-inl.h"
13 #include "src/objects/bigint.h"
14 #include "src/objects/call-site-info.h"
15 #include "src/objects/cell.h"
16 #include "src/objects/data-handler.h"
17 #include "src/objects/embedder-data-array-inl.h"
18 #include "src/objects/fixed-array.h"
19 #include "src/objects/foreign-inl.h"
20 #include "src/objects/free-space-inl.h"
21 #include "src/objects/hash-table.h"
22 #include "src/objects/heap-number.h"
23 #include "src/objects/js-collection.h"
24 #include "src/objects/js-weak-refs.h"
25 #include "src/objects/literal-objects.h"
26 #include "src/objects/megadom-handler-inl.h"
27 #include "src/objects/objects-body-descriptors.h"
28 #include "src/objects/ordered-hash-table-inl.h"
29 #include "src/objects/property-descriptor-object.h"
30 #include "src/objects/source-text-module.h"
31 #include "src/objects/swiss-name-dictionary-inl.h"
32 #include "src/objects/synthetic-module.h"
33 #include "src/objects/template-objects.h"
34 #include "src/objects/torque-defined-classes-inl.h"
35 #include "src/objects/transitions.h"
36 #include "src/objects/turbofan-types-inl.h"
37 
38 #if V8_ENABLE_WEBASSEMBLY
39 #include "src/wasm/wasm-objects-inl.h"
40 #endif  // V8_ENABLE_WEBASSEMBLY
41 
42 namespace v8 {
43 namespace internal {
44 
45 template <int start_offset>
SizeOf(Map map,HeapObject object)46 int FlexibleBodyDescriptor<start_offset>::SizeOf(Map map, HeapObject object) {
47   return object.SizeFromMap(map);
48 }
49 
50 template <int start_offset>
SizeOf(Map map,HeapObject object)51 int FlexibleWeakBodyDescriptor<start_offset>::SizeOf(Map map,
52                                                      HeapObject object) {
53   return object.SizeFromMap(map);
54 }
55 
IsValidJSObjectSlotImpl(Map map,HeapObject obj,int offset)56 bool BodyDescriptorBase::IsValidJSObjectSlotImpl(Map map, HeapObject obj,
57                                                  int offset) {
58 #ifdef V8_COMPRESS_POINTERS
59   STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
60   int embedder_fields_offset = JSObject::GetEmbedderFieldsStartOffset(map);
61   int inobject_fields_offset = map.GetInObjectPropertyOffset(0);
62   // |embedder_fields_offset| may be greater than |inobject_fields_offset| if
63   // the object does not have embedder fields but the check handles this
64   // case properly.
65   if (embedder_fields_offset <= offset && offset < inobject_fields_offset) {
66     // offset points to embedder fields area:
67     // [embedder_fields_offset, inobject_fields_offset).
68     STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize));
69     return ((offset - embedder_fields_offset) & (kEmbedderDataSlotSize - 1)) ==
70            EmbedderDataSlot::kTaggedPayloadOffset;
71   }
72 #else
73   // We store raw aligned pointers as Smis, so it's safe to treat the whole
74   // embedder field area as tagged slots.
75   STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
76 #endif
77   return true;
78 }
79 
80 template <typename ObjectVisitor>
IterateJSObjectBodyImpl(Map map,HeapObject obj,int start_offset,int end_offset,ObjectVisitor * v)81 void BodyDescriptorBase::IterateJSObjectBodyImpl(Map map, HeapObject obj,
82                                                  int start_offset,
83                                                  int end_offset,
84                                                  ObjectVisitor* v) {
85 #ifdef V8_COMPRESS_POINTERS
86   STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
87   int header_end_offset = JSObject::GetHeaderSize(map);
88   int inobject_fields_start_offset = map.GetInObjectPropertyOffset(0);
89   // We are always requested to process header and embedder fields.
90   DCHECK_LE(inobject_fields_start_offset, end_offset);
91   // Embedder fields are located between header and inobject properties.
92   if (header_end_offset < inobject_fields_start_offset) {
93     // There are embedder fields.
94     DCHECK_EQ(header_end_offset, JSObject::GetEmbedderFieldsStartOffset(map));
95     IteratePointers(obj, start_offset, header_end_offset, v);
96     for (int offset = header_end_offset; offset < inobject_fields_start_offset;
97          offset += kEmbedderDataSlotSize) {
98       IteratePointer(obj, offset + EmbedderDataSlot::kTaggedPayloadOffset, v);
99       v->VisitExternalPointer(
100           obj, obj.RawExternalPointerField(
101                    offset + EmbedderDataSlot::kExternalPointerOffset));
102     }
103     // Proceed processing inobject properties.
104     start_offset = inobject_fields_start_offset;
105   }
106 #else
107   // We store raw aligned pointers as Smis, so it's safe to iterate the whole
108   // embedder field area as tagged slots.
109   STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
110 #endif
111   IteratePointers(obj, start_offset, end_offset, v);
112 }
113 
114 template <typename ObjectVisitor>
IteratePointers(HeapObject obj,int start_offset,int end_offset,ObjectVisitor * v)115 DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(HeapObject obj,
116                                                           int start_offset,
117                                                           int end_offset,
118                                                           ObjectVisitor* v) {
119   if (start_offset == HeapObject::kMapOffset) {
120     v->VisitMapPointer(obj);
121     start_offset += kTaggedSize;
122   }
123   v->VisitPointers(obj, obj.RawField(start_offset), obj.RawField(end_offset));
124 }
125 
126 template <typename ObjectVisitor>
IteratePointer(HeapObject obj,int offset,ObjectVisitor * v)127 void BodyDescriptorBase::IteratePointer(HeapObject obj, int offset,
128                                         ObjectVisitor* v) {
129   DCHECK_NE(offset, HeapObject::kMapOffset);
130   v->VisitPointer(obj, obj.RawField(offset));
131 }
132 
133 template <typename ObjectVisitor>
IterateMaybeWeakPointers(HeapObject obj,int start_offset,int end_offset,ObjectVisitor * v)134 DISABLE_CFI_PERF void BodyDescriptorBase::IterateMaybeWeakPointers(
135     HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) {
136   v->VisitPointers(obj, obj.RawMaybeWeakField(start_offset),
137                    obj.RawMaybeWeakField(end_offset));
138 }
139 
140 template <typename ObjectVisitor>
IterateMaybeWeakPointer(HeapObject obj,int offset,ObjectVisitor * v)141 void BodyDescriptorBase::IterateMaybeWeakPointer(HeapObject obj, int offset,
142                                                  ObjectVisitor* v) {
143   DCHECK_NE(offset, HeapObject::kMapOffset);
144   v->VisitPointer(obj, obj.RawMaybeWeakField(offset));
145 }
146 
147 template <typename ObjectVisitor>
IterateCustomWeakPointers(HeapObject obj,int start_offset,int end_offset,ObjectVisitor * v)148 DISABLE_CFI_PERF void BodyDescriptorBase::IterateCustomWeakPointers(
149     HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) {
150   v->VisitCustomWeakPointers(obj, obj.RawField(start_offset),
151                              obj.RawField(end_offset));
152 }
153 
154 template <typename ObjectVisitor>
IterateEphemeron(HeapObject obj,int index,int key_offset,int value_offset,ObjectVisitor * v)155 DISABLE_CFI_PERF void BodyDescriptorBase::IterateEphemeron(HeapObject obj,
156                                                            int index,
157                                                            int key_offset,
158                                                            int value_offset,
159                                                            ObjectVisitor* v) {
160   v->VisitEphemeron(obj, index, obj.RawField(key_offset),
161                     obj.RawField(value_offset));
162 }
163 
164 template <typename ObjectVisitor>
IterateCustomWeakPointer(HeapObject obj,int offset,ObjectVisitor * v)165 void BodyDescriptorBase::IterateCustomWeakPointer(HeapObject obj, int offset,
166                                                   ObjectVisitor* v) {
167   v->VisitCustomWeakPointer(obj, obj.RawField(offset));
168 }
169 
170 class HeapNumber::BodyDescriptor final : public BodyDescriptorBase {
171  public:
IsValidSlot(Map map,HeapObject obj,int offset)172   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
173 
174   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)175   static inline void IterateBody(Map map, HeapObject obj, int object_size,
176                                  ObjectVisitor* v) {}
177 
SizeOf(Map map,HeapObject object)178   static inline int SizeOf(Map map, HeapObject object) {
179     return HeapNumber::kSize;
180   }
181 };
182 
183 // This is a descriptor for one/two pointer fillers.
184 class FreeSpaceFillerBodyDescriptor final : public DataOnlyBodyDescriptor {
185  public:
SizeOf(Map map,HeapObject raw_object)186   static inline int SizeOf(Map map, HeapObject raw_object) {
187     return map.instance_size();
188   }
189 };
190 
191 class FreeSpace::BodyDescriptor final : public DataOnlyBodyDescriptor {
192  public:
SizeOf(Map map,HeapObject raw_object)193   static inline int SizeOf(Map map, HeapObject raw_object) {
194     return FreeSpace::unchecked_cast(raw_object).Size();
195   }
196 };
197 
198 class JSObject::BodyDescriptor final : public BodyDescriptorBase {
199  public:
200   static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
201 
IsValidSlot(Map map,HeapObject obj,int offset)202   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
203     if (offset < kStartOffset) return false;
204     return IsValidJSObjectSlotImpl(map, obj, offset);
205   }
206 
207   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)208   static inline void IterateBody(Map map, HeapObject obj, int object_size,
209                                  ObjectVisitor* v) {
210     IterateJSObjectBodyImpl(map, obj, kStartOffset, object_size, v);
211   }
212 
SizeOf(Map map,HeapObject object)213   static inline int SizeOf(Map map, HeapObject object) {
214     return map.instance_size();
215   }
216 };
217 
218 class JSObject::FastBodyDescriptor final : public BodyDescriptorBase {
219  public:
220   static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
221 
IsValidSlot(Map map,HeapObject obj,int offset)222   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
223     return offset >= kStartOffset;
224   }
225 
226   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)227   static inline void IterateBody(Map map, HeapObject obj, int object_size,
228                                  ObjectVisitor* v) {
229     IteratePointers(obj, kStartOffset, object_size, v);
230   }
231 
SizeOf(Map map,HeapObject object)232   static inline int SizeOf(Map map, HeapObject object) {
233     return map.instance_size();
234   }
235 };
236 
237 class WeakCell::BodyDescriptor final : public BodyDescriptorBase {
238  public:
IsValidSlot(Map map,HeapObject obj,int offset)239   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
240     return offset >= HeapObject::kHeaderSize;
241   }
242 
243   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)244   static inline void IterateBody(Map map, HeapObject obj, int object_size,
245                                  ObjectVisitor* v) {
246     IteratePointers(obj, HeapObject::kHeaderSize, kTargetOffset, v);
247     IterateCustomWeakPointer(obj, kTargetOffset, v);
248     IterateCustomWeakPointer(obj, kUnregisterTokenOffset, v);
249     IteratePointers(obj, kUnregisterTokenOffset + kTaggedSize, object_size, v);
250   }
251 
SizeOf(Map map,HeapObject object)252   static inline int SizeOf(Map map, HeapObject object) {
253     return map.instance_size();
254   }
255 };
256 
257 class JSWeakRef::BodyDescriptor final : public BodyDescriptorBase {
258  public:
IsValidSlot(Map map,HeapObject obj,int offset)259   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
260     return IsValidJSObjectSlotImpl(map, obj, offset);
261   }
262 
263   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)264   static inline void IterateBody(Map map, HeapObject obj, int object_size,
265                                  ObjectVisitor* v) {
266     IteratePointers(obj, JSReceiver::kPropertiesOrHashOffset, kTargetOffset, v);
267     IterateCustomWeakPointer(obj, kTargetOffset, v);
268     IterateJSObjectBodyImpl(map, obj, kTargetOffset + kTaggedSize, object_size,
269                             v);
270   }
271 
SizeOf(Map map,HeapObject object)272   static inline int SizeOf(Map map, HeapObject object) {
273     return map.instance_size();
274   }
275 };
276 
277 class JSFinalizationRegistry::BodyDescriptor final : public BodyDescriptorBase {
278  public:
IsValidSlot(Map map,HeapObject obj,int offset)279   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
280     return IsValidJSObjectSlotImpl(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     IteratePointers(obj, JSObject::BodyDescriptor::kStartOffset,
287                     kNextDirtyOffset, v);
288     IterateCustomWeakPointer(obj, kNextDirtyOffset, v);
289     IterateJSObjectBodyImpl(map, obj, kNextDirtyOffset + kTaggedSize,
290                             object_size, v);
291   }
292 
SizeOf(Map map,HeapObject object)293   static inline int SizeOf(Map map, HeapObject object) {
294     return map.instance_size();
295   }
296 };
297 
298 class AllocationSite::BodyDescriptor final : public BodyDescriptorBase {
299  public:
300   STATIC_ASSERT(AllocationSite::kCommonPointerFieldEndOffset ==
301                 AllocationSite::kPretenureDataOffset);
302   STATIC_ASSERT(AllocationSite::kPretenureDataOffset + kInt32Size ==
303                 AllocationSite::kPretenureCreateCountOffset);
304   STATIC_ASSERT(AllocationSite::kPretenureCreateCountOffset + kInt32Size ==
305                 AllocationSite::kWeakNextOffset);
306 
IsValidSlot(Map map,HeapObject obj,int offset)307   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
308     if (offset >= AllocationSite::kStartOffset &&
309         offset < AllocationSite::kCommonPointerFieldEndOffset) {
310       return true;
311     }
312     // check for weak_next offset
313     if (map.instance_size() == AllocationSite::kSizeWithWeakNext &&
314         offset == AllocationSite::kWeakNextOffset) {
315       return true;
316     }
317     return false;
318   }
319 
320   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)321   static inline void IterateBody(Map map, HeapObject obj, int object_size,
322                                  ObjectVisitor* v) {
323     // Iterate over all the common pointer fields
324     IteratePointers(obj, AllocationSite::kStartOffset,
325                     AllocationSite::kCommonPointerFieldEndOffset, v);
326     // Skip PretenureDataOffset and PretenureCreateCount which are Int32 fields.
327     // Visit weak_next only if it has weak_next field.
328     if (object_size == AllocationSite::kSizeWithWeakNext) {
329       IterateCustomWeakPointers(obj, AllocationSite::kWeakNextOffset,
330                                 AllocationSite::kSizeWithWeakNext, v);
331     }
332   }
333 
SizeOf(Map map,HeapObject object)334   static inline int SizeOf(Map map, HeapObject object) {
335     return map.instance_size();
336   }
337 };
338 
339 class JSFunction::BodyDescriptor final : public BodyDescriptorBase {
340  public:
341   static const int kStartOffset = JSObject::BodyDescriptor::kStartOffset;
342 
IsValidSlot(Map map,HeapObject obj,int offset)343   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
344     if (offset < kStartOffset) return false;
345     return IsValidJSObjectSlotImpl(map, obj, offset);
346   }
347 
348   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)349   static inline void IterateBody(Map map, HeapObject obj, int object_size,
350                                  ObjectVisitor* v) {
351     // Iterate JSFunction header fields first.
352     int header_size = JSFunction::GetHeaderSize(map.has_prototype_slot());
353     DCHECK_GE(object_size, header_size);
354     IteratePointers(obj, kStartOffset, kCodeOffset, v);
355     // Code field is treated as a custom weak pointer. This field is visited as
356     // a weak pointer if the Code is baseline code and the bytecode array
357     // corresponding to this function is old. In the rest of the cases this
358     // field is treated as strong pointer.
359     IterateCustomWeakPointer(obj, kCodeOffset, v);
360     // Iterate rest of the header fields
361     DCHECK_GE(header_size, kCodeOffset);
362     IteratePointers(obj, kCodeOffset + kTaggedSize, header_size, v);
363     // Iterate rest of the fields starting after the header.
364     IterateJSObjectBodyImpl(map, obj, header_size, object_size, v);
365   }
366 
SizeOf(Map map,HeapObject object)367   static inline int SizeOf(Map map, HeapObject object) {
368     return map.instance_size();
369   }
370 };
371 
372 class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
373  public:
IsValidSlot(Map map,HeapObject obj,int offset)374   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
375     if (offset < kEndOfTaggedFieldsOffset) return true;
376     if (offset < kHeaderSize) return false;
377     return IsValidJSObjectSlotImpl(map, obj, offset);
378   }
379 
380   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)381   static inline void IterateBody(Map map, HeapObject obj, int object_size,
382                                  ObjectVisitor* v) {
383     // JSArrayBuffer instances contain raw data that the GC does not know about.
384     IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
385     IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
386   }
387 
SizeOf(Map map,HeapObject object)388   static inline int SizeOf(Map map, HeapObject object) {
389     return map.instance_size();
390   }
391 };
392 
393 class JSTypedArray::BodyDescriptor final : public BodyDescriptorBase {
394  public:
IsValidSlot(Map map,HeapObject obj,int offset)395   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
396     if (offset < kEndOfTaggedFieldsOffset) return true;
397     // TODO(v8:4153): Remove this.
398     if (offset == kBasePointerOffset) return true;
399     if (offset < kHeaderSize) return false;
400     return IsValidJSObjectSlotImpl(map, obj, offset);
401   }
402 
403   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)404   static inline void IterateBody(Map map, HeapObject obj, int object_size,
405                                  ObjectVisitor* v) {
406     // JSTypedArray contains raw data that the GC does not know about.
407     IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
408     // TODO(v8:4153): Remove this.
409     IteratePointer(obj, kBasePointerOffset, v);
410     IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
411   }
412 
SizeOf(Map map,HeapObject object)413   static inline int SizeOf(Map map, HeapObject object) {
414     return map.instance_size();
415   }
416 };
417 
418 class JSDataView::BodyDescriptor final : public BodyDescriptorBase {
419  public:
IsValidSlot(Map map,HeapObject obj,int offset)420   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
421     if (offset < kEndOfTaggedFieldsOffset) return true;
422     if (offset < kHeaderSize) return false;
423     return IsValidJSObjectSlotImpl(map, obj, offset);
424   }
425 
426   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)427   static inline void IterateBody(Map map, HeapObject obj, int object_size,
428                                  ObjectVisitor* v) {
429     // JSDataView contains raw data that the GC does not know about.
430     IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
431     IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
432   }
433 
SizeOf(Map map,HeapObject object)434   static inline int SizeOf(Map map, HeapObject object) {
435     return map.instance_size();
436   }
437 };
438 
439 class JSExternalObject::BodyDescriptor final : public BodyDescriptorBase {
440  public:
IsValidSlot(Map map,HeapObject obj,int offset)441   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
442 
443   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)444   static inline void IterateBody(Map map, HeapObject obj, int object_size,
445                                  ObjectVisitor* v) {
446     IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
447     v->VisitExternalPointer(obj, obj.RawExternalPointerField(kValueOffset));
448   }
449 
SizeOf(Map map,HeapObject object)450   static inline int SizeOf(Map map, HeapObject object) {
451     return map.instance_size();
452   }
453 };
454 
455 template <typename Derived>
456 class V8_EXPORT_PRIVATE SmallOrderedHashTable<Derived>::BodyDescriptor final
457     : public BodyDescriptorBase {
458  public:
IsValidSlot(Map map,HeapObject obj,int offset)459   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
460     Derived table = Derived::cast(obj);
461     // Only data table part contains tagged values.
462     return (offset >= DataTableStartOffset()) &&
463            (offset < table.GetBucketsStartOffset());
464   }
465 
466   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)467   static inline void IterateBody(Map map, HeapObject obj, int object_size,
468                                  ObjectVisitor* v) {
469     Derived table = Derived::cast(obj);
470     int start_offset = DataTableStartOffset();
471     int end_offset = table.GetBucketsStartOffset();
472     IteratePointers(obj, start_offset, end_offset, v);
473   }
474 
SizeOf(Map map,HeapObject obj)475   static inline int SizeOf(Map map, HeapObject obj) {
476     Derived table = Derived::cast(obj);
477     return Derived::SizeFor(table.Capacity());
478   }
479 };
480 
481 class V8_EXPORT_PRIVATE SwissNameDictionary::BodyDescriptor final
482     : public BodyDescriptorBase {
483  public:
IsValidSlot(Map map,HeapObject obj,int offset)484   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
485     // Using |unchecked_cast| here and elsewhere in this class because the
486     // Scavenger may be calling us while the map word contains the forwarding
487     // address (a Smi) rather than a map.
488 
489     SwissNameDictionary table = SwissNameDictionary::unchecked_cast(obj);
490     STATIC_ASSERT(MetaTablePointerOffset() + kTaggedSize ==
491                   DataTableStartOffset());
492     return offset >= MetaTablePointerOffset() &&
493            (offset < table.DataTableEndOffset(table.Capacity()));
494   }
495 
496   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)497   static inline void IterateBody(Map map, HeapObject obj, int object_size,
498                                  ObjectVisitor* v) {
499     SwissNameDictionary table = SwissNameDictionary::unchecked_cast(obj);
500     STATIC_ASSERT(MetaTablePointerOffset() + kTaggedSize ==
501                   DataTableStartOffset());
502     int start_offset = MetaTablePointerOffset();
503     int end_offset = table.DataTableEndOffset(table.Capacity());
504     IteratePointers(obj, start_offset, end_offset, v);
505   }
506 
SizeOf(Map map,HeapObject obj)507   static inline int SizeOf(Map map, HeapObject obj) {
508     SwissNameDictionary table = SwissNameDictionary::unchecked_cast(obj);
509     return SwissNameDictionary::SizeFor(table.Capacity());
510   }
511 };
512 
513 class ByteArray::BodyDescriptor final : public BodyDescriptorBase {
514  public:
IsValidSlot(Map map,HeapObject obj,int offset)515   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
516 
517   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)518   static inline void IterateBody(Map map, HeapObject obj, int object_size,
519                                  ObjectVisitor* v) {}
520 
SizeOf(Map map,HeapObject obj)521   static inline int SizeOf(Map map, HeapObject obj) {
522     return ByteArray::SizeFor(ByteArray::cast(obj).length(kAcquireLoad));
523   }
524 };
525 
526 class BytecodeArray::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 >= kConstantPoolOffset &&
530            offset <= kSourcePositionTableOffset;
531   }
532 
533   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)534   static inline void IterateBody(Map map, HeapObject obj, int object_size,
535                                  ObjectVisitor* v) {
536     IteratePointer(obj, kConstantPoolOffset, v);
537     IteratePointer(obj, kHandlerTableOffset, v);
538     IteratePointer(obj, kSourcePositionTableOffset, v);
539   }
540 
SizeOf(Map map,HeapObject obj)541   static inline int SizeOf(Map map, HeapObject obj) {
542     return BytecodeArray::SizeFor(
543         BytecodeArray::cast(obj).length(kAcquireLoad));
544   }
545 };
546 
547 class BigInt::BodyDescriptor final : public BodyDescriptorBase {
548  public:
IsValidSlot(Map map,HeapObject obj,int offset)549   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
550 
551   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)552   static inline void IterateBody(Map map, HeapObject obj, int object_size,
553                                  ObjectVisitor* v) {}
554 
SizeOf(Map map,HeapObject obj)555   static inline int SizeOf(Map map, HeapObject obj) {
556     return BigInt::SizeFor(BigInt::cast(obj).length(kAcquireLoad));
557   }
558 };
559 
560 class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase {
561  public:
IsValidSlot(Map map,HeapObject obj,int offset)562   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
563 
564   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)565   static inline void IterateBody(Map map, HeapObject obj, int object_size,
566                                  ObjectVisitor* v) {}
567 
SizeOf(Map map,HeapObject obj)568   static inline int SizeOf(Map map, HeapObject obj) {
569     return FixedDoubleArray::SizeFor(
570         FixedDoubleArray::cast(obj).length(kAcquireLoad));
571   }
572 };
573 
574 class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
575  public:
IsValidSlot(Map map,HeapObject obj,int offset)576   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
577 
578   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)579   static inline void IterateBody(Map map, HeapObject obj, int object_size,
580                                  ObjectVisitor* v) {}
581 
SizeOf(Map map,HeapObject obj)582   static inline int SizeOf(Map map, HeapObject obj) {
583     return FeedbackMetadata::SizeFor(
584         FeedbackMetadata::cast(obj).slot_count(kAcquireLoad));
585   }
586 };
587 
588 class PreparseData::BodyDescriptor final : public BodyDescriptorBase {
589  public:
IsValidSlot(Map map,HeapObject obj,int offset)590   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
591     return offset >= PreparseData::cast(obj).inner_start_offset();
592   }
593 
594   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)595   static inline void IterateBody(Map map, HeapObject obj, int object_size,
596                                  ObjectVisitor* v) {
597     PreparseData data = PreparseData::cast(obj);
598     int start_offset = data.inner_start_offset();
599     int end_offset = start_offset + data.children_length() * kTaggedSize;
600     IteratePointers(obj, start_offset, end_offset, v);
601   }
602 
SizeOf(Map map,HeapObject obj)603   static inline int SizeOf(Map map, HeapObject obj) {
604     PreparseData data = PreparseData::cast(obj);
605     return PreparseData::SizeFor(data.data_length(), data.children_length());
606   }
607 };
608 
609 class PromiseOnStack::BodyDescriptor final : public BodyDescriptorBase {
610  public:
IsValidSlot(Map map,HeapObject obj,int offset)611   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
612     return offset >= HeapObject::kHeaderSize;
613   }
614 
615   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)616   static inline void IterateBody(Map map, HeapObject obj, int object_size,
617                                  ObjectVisitor* v) {
618     IteratePointers(obj, Struct::kHeaderSize, kPromiseOffset, v);
619     IterateMaybeWeakPointer(obj, kPromiseOffset, v);
620     STATIC_ASSERT(kPromiseOffset + kTaggedSize == kHeaderSize);
621   }
622 
SizeOf(Map map,HeapObject obj)623   static inline int SizeOf(Map map, HeapObject obj) {
624     return obj.SizeFromMap(map);
625   }
626 };
627 
628 class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase {
629  public:
IsValidSlot(Map map,HeapObject obj,int offset)630   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
631     return offset >= HeapObject::kHeaderSize;
632   }
633 
634   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)635   static inline void IterateBody(Map map, HeapObject obj, int object_size,
636                                  ObjectVisitor* v) {
637     IteratePointers(obj, HeapObject::kHeaderSize, kObjectCreateMapOffset, v);
638     IterateMaybeWeakPointer(obj, kObjectCreateMapOffset, v);
639     STATIC_ASSERT(kObjectCreateMapOffset + kTaggedSize == kHeaderSize);
640   }
641 
SizeOf(Map map,HeapObject obj)642   static inline int SizeOf(Map map, HeapObject obj) {
643     return obj.SizeFromMap(map);
644   }
645 };
646 
647 class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
648  public:
649   STATIC_ASSERT(kTableOffset + kTaggedSize == kHeaderSizeOfAllWeakCollections);
650 
IsValidSlot(Map map,HeapObject obj,int offset)651   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
652     return IsValidJSObjectSlotImpl(map, obj, offset);
653   }
654 
655   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)656   static inline void IterateBody(Map map, HeapObject obj, int object_size,
657                                  ObjectVisitor* v) {
658     IterateJSObjectBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v);
659   }
660 
SizeOf(Map map,HeapObject object)661   static inline int SizeOf(Map map, HeapObject object) {
662     return map.instance_size();
663   }
664 };
665 
666 class Foreign::BodyDescriptor final : public BodyDescriptorBase {
667  public:
IsValidSlot(Map map,HeapObject obj,int offset)668   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
669 
670   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)671   static inline void IterateBody(Map map, HeapObject obj, int object_size,
672                                  ObjectVisitor* v) {
673     v->VisitExternalReference(
674         Foreign::cast(obj), reinterpret_cast<Address*>(
675                                 obj.RawField(kForeignAddressOffset).address()));
676     v->VisitExternalPointer(obj,
677                             obj.RawExternalPointerField(kForeignAddressOffset));
678   }
679 
SizeOf(Map map,HeapObject object)680   static inline int SizeOf(Map map, HeapObject object) { return kSize; }
681 };
682 
683 #if V8_ENABLE_WEBASSEMBLY
684 class WasmTypeInfo::BodyDescriptor final : public BodyDescriptorBase {
685  public:
IsValidSlot(Map map,HeapObject obj,int offset)686   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
687     UNREACHABLE();
688   }
689 
690   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)691   static inline void IterateBody(Map map, HeapObject obj, int object_size,
692                                  ObjectVisitor* v) {
693     Foreign::BodyDescriptor::IterateBody<ObjectVisitor>(map, obj, object_size,
694                                                         v);
695     IteratePointer(obj, kSupertypesOffset, v);
696     IteratePointer(obj, kSubtypesOffset, v);
697     IteratePointer(obj, kInstanceOffset, v);
698   }
699 
SizeOf(Map map,HeapObject object)700   static inline int SizeOf(Map map, HeapObject object) { return kSize; }
701 };
702 
703 class WasmApiFunctionRef::BodyDescriptor final : public BodyDescriptorBase {
704  public:
IsValidSlot(Map map,HeapObject obj,int offset)705   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
706     UNREACHABLE();
707   }
708 
709   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)710   static inline void IterateBody(Map map, HeapObject obj, int object_size,
711                                  ObjectVisitor* v) {
712     IteratePointers(obj, kStartOfStrongFieldsOffset, kEndOfStrongFieldsOffset,
713                     v);
714   }
715 
SizeOf(Map map,HeapObject object)716   static inline int SizeOf(Map map, HeapObject object) { return kSize; }
717 };
718 
719 class WasmInternalFunction::BodyDescriptor final : public BodyDescriptorBase {
720  public:
IsValidSlot(Map map,HeapObject obj,int offset)721   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
722     UNREACHABLE();
723   }
724 
725   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)726   static inline void IterateBody(Map map, HeapObject obj, int object_size,
727                                  ObjectVisitor* v) {
728     Foreign::BodyDescriptor::IterateBody<ObjectVisitor>(map, obj, object_size,
729                                                         v);
730     IteratePointers(obj, kStartOfStrongFieldsOffset, kEndOfStrongFieldsOffset,
731                     v);
732   }
733 
SizeOf(Map map,HeapObject object)734   static inline int SizeOf(Map map, HeapObject object) { return kSize; }
735 };
736 
737 class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
738  public:
IsValidSlot(Map map,HeapObject obj,int offset)739   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
740     SLOW_DCHECK(std::is_sorted(std::begin(kTaggedFieldOffsets),
741                                std::end(kTaggedFieldOffsets)));
742     STATIC_ASSERT(sizeof(*kTaggedFieldOffsets) == sizeof(uint16_t));
743     if (offset < int{8 * sizeof(*kTaggedFieldOffsets)} &&
744         std::binary_search(std::begin(kTaggedFieldOffsets),
745                            std::end(kTaggedFieldOffsets),
746                            static_cast<uint16_t>(offset))) {
747       return true;
748     }
749     return IsValidJSObjectSlotImpl(map, obj, offset);
750   }
751 
752   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)753   static inline void IterateBody(Map map, HeapObject obj, int object_size,
754                                  ObjectVisitor* v) {
755     IteratePointers(obj, kPropertiesOrHashOffset, JSObject::kHeaderSize, v);
756     for (uint16_t offset : kTaggedFieldOffsets) {
757       IteratePointer(obj, offset, v);
758     }
759     IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
760   }
761 
SizeOf(Map map,HeapObject object)762   static inline int SizeOf(Map map, HeapObject object) {
763     return map.instance_size();
764   }
765 };
766 
767 class WasmArray::BodyDescriptor final : public BodyDescriptorBase {
768  public:
IsValidSlot(Map map,HeapObject obj,int offset)769   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
770     // Fields in WasmArrays never change their types in place, so
771     // there should never be a need to call this function.
772     UNREACHABLE();
773     return false;
774   }
775 
776   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)777   static inline void IterateBody(Map map, HeapObject obj, int object_size,
778                                  ObjectVisitor* v) {
779     // The type is safe to use because it's kept alive by the {map}'s
780     // WasmTypeInfo.
781     if (!WasmArray::GcSafeType(map)->element_type().is_reference()) return;
782     IteratePointers(obj, WasmArray::kHeaderSize, object_size, v);
783   }
784 
SizeOf(Map map,HeapObject object)785   static inline int SizeOf(Map map, HeapObject object) {
786     return WasmArray::SizeFor(map, WasmArray::cast(object).length());
787   }
788 };
789 
790 class WasmStruct::BodyDescriptor final : public BodyDescriptorBase {
791  public:
IsValidSlot(Map map,HeapObject obj,int offset)792   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
793     // Fields in WasmStructs never change their types in place, so
794     // there should never be a need to call this function.
795     UNREACHABLE();
796     return false;
797   }
798 
799   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)800   static inline void IterateBody(Map map, HeapObject obj, int object_size,
801                                  ObjectVisitor* v) {
802     WasmStruct wasm_struct = WasmStruct::cast(obj);
803     // The {type} is safe to use because it's kept alive by the {map}'s
804     // WasmTypeInfo.
805     wasm::StructType* type = WasmStruct::GcSafeType(map);
806     for (uint32_t i = 0; i < type->field_count(); i++) {
807       if (!type->field(i).is_reference()) continue;
808       int offset = static_cast<int>(type->field_offset(i));
809       v->VisitPointer(wasm_struct, wasm_struct.RawField(offset));
810     }
811   }
812 
SizeOf(Map map,HeapObject object)813   static inline int SizeOf(Map map, HeapObject object) {
814     return WasmStruct::GcSafeSize(map);
815   }
816 };
817 
818 #endif  // V8_ENABLE_WEBASSEMBLY
819 
820 class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
821  public:
IsValidSlot(Map map,HeapObject obj,int offset)822   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
823 
824   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)825   static inline void IterateBody(Map map, HeapObject obj, int object_size,
826                                  ObjectVisitor* v) {
827     ExternalString string = ExternalString::cast(obj);
828     v->VisitExternalPointer(obj,
829                             string.RawExternalPointerField(kResourceOffset));
830     if (string.is_uncached()) return;
831     v->VisitExternalPointer(
832         obj, string.RawExternalPointerField(kResourceDataOffset));
833   }
834 
SizeOf(Map map,HeapObject object)835   static inline int SizeOf(Map map, HeapObject object) { return kSize; }
836 };
837 
838 class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
839  public:
IsValidSlot(Map map,HeapObject obj,int offset)840   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
841 
842   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)843   static inline void IterateBody(Map map, HeapObject obj, int object_size,
844                                  ObjectVisitor* v) {
845     ExternalString string = ExternalString::cast(obj);
846     v->VisitExternalPointer(obj,
847                             string.RawExternalPointerField(kResourceOffset));
848     if (string.is_uncached()) return;
849     v->VisitExternalPointer(
850         obj, string.RawExternalPointerField(kResourceDataOffset));
851   }
852 
SizeOf(Map map,HeapObject object)853   static inline int SizeOf(Map map, HeapObject object) { return kSize; }
854 };
855 
856 class CoverageInfo::BodyDescriptor final : public BodyDescriptorBase {
857  public:
IsValidSlot(Map map,HeapObject obj,int offset)858   static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
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 
SizeOf(Map map,HeapObject object)864   static inline int SizeOf(Map map, HeapObject object) {
865     CoverageInfo info = CoverageInfo::cast(object);
866     return CoverageInfo::SizeFor(info.slot_count());
867   }
868 };
869 
870 class Code::BodyDescriptor final : public BodyDescriptorBase {
871  public:
872   STATIC_ASSERT(kRelocationInfoOffset + kTaggedSize ==
873                 kDeoptimizationDataOrInterpreterDataOffset);
874   STATIC_ASSERT(kDeoptimizationDataOrInterpreterDataOffset + kTaggedSize ==
875                 kPositionTableOffset);
876   STATIC_ASSERT(kPositionTableOffset + kTaggedSize == kCodeDataContainerOffset);
877   STATIC_ASSERT(kCodeDataContainerOffset + kTaggedSize == kDataStart);
878 
IsValidSlot(Map map,HeapObject obj,int offset)879   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
880     // Slots in code can't be invalid because we never trim code objects.
881     return true;
882   }
883 
884   static constexpr int kRelocModeMask =
885       RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
886       RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
887       RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
888       RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) |
889       RelocInfo::ModeMask(RelocInfo::DATA_EMBEDDED_OBJECT) |
890       RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
891       RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
892       RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
893       RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) |
894       RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
895 
896   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,ObjectVisitor * v)897   static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) {
898     // GC does not visit data/code in the header and in the body directly.
899     IteratePointers(obj, kRelocationInfoOffset, kDataStart, v);
900 
901     RelocIterator it(Code::cast(obj), kRelocModeMask);
902     v->VisitRelocInfo(&it);
903   }
904 
905   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)906   static inline void IterateBody(Map map, HeapObject obj, int object_size,
907                                  ObjectVisitor* v) {
908     IterateBody(map, obj, v);
909   }
910 
SizeOf(Map map,HeapObject object)911   static inline int SizeOf(Map map, HeapObject object) {
912     return Code::unchecked_cast(object).CodeSize();
913   }
914 };
915 
916 class Map::BodyDescriptor final : public BodyDescriptorBase {
917  public:
IsValidSlot(Map map,HeapObject obj,int offset)918   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
919     static_assert(
920         Map::kEndOfStrongFieldsOffset == Map::kStartOfWeakFieldsOffset,
921         "Leverage that weak fields directly follow strong fields for the "
922         "check below");
923     return offset >= Map::kStartOfStrongFieldsOffset &&
924            offset < Map::kEndOfWeakFieldsOffset;
925   }
926 
927   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)928   static inline void IterateBody(Map map, HeapObject obj, int object_size,
929                                  ObjectVisitor* v) {
930     IteratePointers(obj, Map::kStartOfStrongFieldsOffset,
931                     Map::kEndOfStrongFieldsOffset, v);
932     IterateMaybeWeakPointer(obj, kTransitionsOrPrototypeInfoOffset, v);
933   }
934 
SizeOf(Map map,HeapObject obj)935   static inline int SizeOf(Map map, HeapObject obj) { return Map::kSize; }
936 };
937 
938 class DataHandler::BodyDescriptor final : public BodyDescriptorBase {
939  public:
IsValidSlot(Map map,HeapObject obj,int offset)940   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
941     return offset >= HeapObject::kHeaderSize;
942   }
943 
944   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)945   static inline void IterateBody(Map map, HeapObject obj, int object_size,
946                                  ObjectVisitor* v) {
947     static_assert(kSmiHandlerOffset < kData1Offset,
948                   "Field order must be in sync with this iteration code");
949     static_assert(kData1Offset < kSizeWithData1,
950                   "Field order must be in sync with this iteration code");
951     IteratePointers(obj, kSmiHandlerOffset, kData1Offset, v);
952     IterateMaybeWeakPointers(obj, kData1Offset, object_size, v);
953   }
954 
SizeOf(Map map,HeapObject object)955   static inline int SizeOf(Map map, HeapObject object) {
956     return object.SizeFromMap(map);
957   }
958 };
959 
960 class NativeContext::BodyDescriptor final : public BodyDescriptorBase {
961  public:
IsValidSlot(Map map,HeapObject obj,int offset)962   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
963     return offset < NativeContext::kEndOfTaggedFieldsOffset;
964   }
965 
966   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)967   static inline void IterateBody(Map map, HeapObject obj, int object_size,
968                                  ObjectVisitor* v) {
969     IteratePointers(obj, NativeContext::kStartOfStrongFieldsOffset,
970                     NativeContext::kEndOfStrongFieldsOffset, v);
971     IterateCustomWeakPointers(obj, NativeContext::kStartOfWeakFieldsOffset,
972                               NativeContext::kEndOfWeakFieldsOffset, v);
973     v->VisitExternalPointer(obj,
974                             obj.RawExternalPointerField(kMicrotaskQueueOffset));
975   }
976 
SizeOf(Map map,HeapObject object)977   static inline int SizeOf(Map map, HeapObject object) {
978     return NativeContext::kSize;
979   }
980 };
981 
982 class CodeDataContainer::BodyDescriptor final : public BodyDescriptorBase {
983  public:
IsValidSlot(Map map,HeapObject obj,int offset)984   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
985     return offset >= CodeDataContainer::kHeaderSize &&
986            offset <= CodeDataContainer::kPointerFieldsWeakEndOffset;
987   }
988 
989   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)990   static inline void IterateBody(Map map, HeapObject obj, int object_size,
991                                  ObjectVisitor* v) {
992     IteratePointers(obj, CodeDataContainer::kHeaderSize,
993                     CodeDataContainer::kPointerFieldsStrongEndOffset, v);
994     IterateCustomWeakPointers(
995         obj, CodeDataContainer::kPointerFieldsStrongEndOffset,
996         CodeDataContainer::kPointerFieldsWeakEndOffset, v);
997 
998     if (V8_EXTERNAL_CODE_SPACE_BOOL) {
999       v->VisitCodePointer(obj, obj.RawCodeField(kCodeOffset));
1000       v->VisitExternalPointer(
1001           obj, obj.RawExternalPointerField(kCodeEntryPointOffset));
1002     }
1003   }
1004 
SizeOf(Map map,HeapObject object)1005   static inline int SizeOf(Map map, HeapObject object) {
1006     return CodeDataContainer::kSize;
1007   }
1008 };
1009 
1010 class EmbedderDataArray::BodyDescriptor final : public BodyDescriptorBase {
1011  public:
IsValidSlot(Map map,HeapObject obj,int offset)1012   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
1013 #ifdef V8_COMPRESS_POINTERS
1014     STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
1015     STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize));
1016     return (offset < EmbedderDataArray::kHeaderSize) ||
1017            (((offset - EmbedderDataArray::kHeaderSize) &
1018              (kEmbedderDataSlotSize - 1)) ==
1019             EmbedderDataSlot::kTaggedPayloadOffset);
1020 #else
1021     STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
1022     // We store raw aligned pointers as Smis, so it's safe to iterate the whole
1023     // array.
1024     return true;
1025 #endif
1026   }
1027 
1028   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)1029   static inline void IterateBody(Map map, HeapObject obj, int object_size,
1030                                  ObjectVisitor* v) {
1031 #ifdef V8_COMPRESS_POINTERS
1032     STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
1033     for (int offset = EmbedderDataArray::OffsetOfElementAt(0);
1034          offset < object_size; offset += kEmbedderDataSlotSize) {
1035       IteratePointer(obj, offset + EmbedderDataSlot::kTaggedPayloadOffset, v);
1036       v->VisitExternalPointer(
1037           obj, obj.RawExternalPointerField(
1038                    offset + EmbedderDataSlot::kExternalPointerOffset));
1039     }
1040 
1041 #else
1042     // We store raw aligned pointers as Smis, so it's safe to iterate the whole
1043     // array.
1044     STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
1045     IteratePointers(obj, EmbedderDataArray::kHeaderSize, object_size, v);
1046 #endif
1047   }
1048 
SizeOf(Map map,HeapObject object)1049   static inline int SizeOf(Map map, HeapObject object) {
1050     return object.SizeFromMap(map);
1051   }
1052 };
1053 
1054 template <typename Op, typename... Args>
BodyDescriptorApply(InstanceType type,Args &&...args)1055 auto BodyDescriptorApply(InstanceType type, Args&&... args) {
1056 #define CALL_APPLY(ClassName) \
1057   Op::template apply<ClassName::BodyDescriptor>(std::forward<Args>(args)...)
1058 
1059   if (type < FIRST_NONSTRING_TYPE) {
1060     switch (type & kStringRepresentationMask) {
1061       case kSeqStringTag:
1062         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1063           return CALL_APPLY(SeqOneByteString);
1064         } else {
1065           return CALL_APPLY(SeqTwoByteString);
1066         }
1067       case kConsStringTag:
1068         return CALL_APPLY(ConsString);
1069       case kThinStringTag:
1070         return CALL_APPLY(ThinString);
1071       case kSlicedStringTag:
1072         return CALL_APPLY(SlicedString);
1073       case kExternalStringTag:
1074         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1075           return CALL_APPLY(ExternalOneByteString);
1076         } else {
1077           return CALL_APPLY(ExternalTwoByteString);
1078         }
1079     }
1080     UNREACHABLE();
1081   }
1082   if (InstanceTypeChecker::IsJSApiObject(type)) {
1083     return CALL_APPLY(JSObject);
1084   }
1085 
1086   switch (type) {
1087     case EMBEDDER_DATA_ARRAY_TYPE:
1088       return CALL_APPLY(EmbedderDataArray);
1089     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
1090     case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
1091     case HASH_TABLE_TYPE:
1092     case ORDERED_HASH_MAP_TYPE:
1093     case ORDERED_HASH_SET_TYPE:
1094     case ORDERED_NAME_DICTIONARY_TYPE:
1095     case NAME_DICTIONARY_TYPE:
1096     case GLOBAL_DICTIONARY_TYPE:
1097     case NUMBER_DICTIONARY_TYPE:
1098     case SIMPLE_NUMBER_DICTIONARY_TYPE:
1099     case NAME_TO_INDEX_HASH_TABLE_TYPE:
1100     case REGISTERED_SYMBOL_TABLE_TYPE:
1101     case SCRIPT_CONTEXT_TABLE_TYPE:
1102       return CALL_APPLY(FixedArray);
1103     case EPHEMERON_HASH_TABLE_TYPE:
1104       return CALL_APPLY(EphemeronHashTable);
1105     case AWAIT_CONTEXT_TYPE:
1106     case BLOCK_CONTEXT_TYPE:
1107     case CATCH_CONTEXT_TYPE:
1108     case DEBUG_EVALUATE_CONTEXT_TYPE:
1109     case EVAL_CONTEXT_TYPE:
1110     case FUNCTION_CONTEXT_TYPE:
1111     case MODULE_CONTEXT_TYPE:
1112     case SCRIPT_CONTEXT_TYPE:
1113     case WITH_CONTEXT_TYPE:
1114       return CALL_APPLY(Context);
1115     case NATIVE_CONTEXT_TYPE:
1116       return CALL_APPLY(NativeContext);
1117     case FIXED_DOUBLE_ARRAY_TYPE:
1118       return CALL_APPLY(FixedDoubleArray);
1119     case FEEDBACK_METADATA_TYPE:
1120       return CALL_APPLY(FeedbackMetadata);
1121     case PROPERTY_ARRAY_TYPE:
1122       return CALL_APPLY(PropertyArray);
1123     case TRANSITION_ARRAY_TYPE:
1124       return CALL_APPLY(TransitionArray);
1125     case FEEDBACK_CELL_TYPE:
1126       return CALL_APPLY(FeedbackCell);
1127     case COVERAGE_INFO_TYPE:
1128       return CALL_APPLY(CoverageInfo);
1129 #if V8_ENABLE_WEBASSEMBLY
1130     case WASM_API_FUNCTION_REF_TYPE:
1131       return CALL_APPLY(WasmApiFunctionRef);
1132     case WASM_ARRAY_TYPE:
1133       return CALL_APPLY(WasmArray);
1134     case WASM_CAPI_FUNCTION_DATA_TYPE:
1135       return CALL_APPLY(WasmCapiFunctionData);
1136     case WASM_EXPORTED_FUNCTION_DATA_TYPE:
1137       return CALL_APPLY(WasmExportedFunctionData);
1138     case WASM_INTERNAL_FUNCTION_TYPE:
1139       return CALL_APPLY(WasmInternalFunction);
1140     case WASM_JS_FUNCTION_DATA_TYPE:
1141       return CALL_APPLY(WasmJSFunctionData);
1142     case WASM_ON_FULFILLED_DATA_TYPE:
1143       return CALL_APPLY(WasmOnFulfilledData);
1144     case WASM_STRUCT_TYPE:
1145       return CALL_APPLY(WasmStruct);
1146     case WASM_TYPE_INFO_TYPE:
1147       return CALL_APPLY(WasmTypeInfo);
1148 #endif  // V8_ENABLE_WEBASSEMBLY
1149     case JS_API_OBJECT_TYPE:
1150     case JS_ARGUMENTS_OBJECT_TYPE:
1151     case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE:
1152     case JS_ARRAY_ITERATOR_TYPE:
1153     case JS_ARRAY_TYPE:
1154     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
1155     case JS_ASYNC_FUNCTION_OBJECT_TYPE:
1156     case JS_ASYNC_GENERATOR_OBJECT_TYPE:
1157     case JS_BOUND_FUNCTION_TYPE:
1158     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1159     case JS_DATE_TYPE:
1160     case JS_ERROR_TYPE:
1161     case JS_FINALIZATION_REGISTRY_TYPE:
1162     case JS_GENERATOR_OBJECT_TYPE:
1163     case JS_GLOBAL_OBJECT_TYPE:
1164     case JS_GLOBAL_PROXY_TYPE:
1165     case JS_ITERATOR_PROTOTYPE_TYPE:
1166     case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
1167     case JS_MAP_KEY_ITERATOR_TYPE:
1168     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
1169     case JS_MAP_TYPE:
1170     case JS_MAP_VALUE_ITERATOR_TYPE:
1171     case JS_MESSAGE_OBJECT_TYPE:
1172     case JS_MODULE_NAMESPACE_TYPE:
1173     case JS_OBJECT_PROTOTYPE_TYPE:
1174     case JS_OBJECT_TYPE:
1175     case JS_PRIMITIVE_WRAPPER_TYPE:
1176     case JS_PROMISE_PROTOTYPE_TYPE:
1177     case JS_PROMISE_TYPE:
1178     case JS_REG_EXP_PROTOTYPE_TYPE:
1179     case JS_REG_EXP_STRING_ITERATOR_TYPE:
1180     case JS_REG_EXP_TYPE:
1181     case JS_SET_ITERATOR_PROTOTYPE_TYPE:
1182     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
1183     case JS_SET_PROTOTYPE_TYPE:
1184     case JS_SET_TYPE:
1185     case JS_SET_VALUE_ITERATOR_TYPE:
1186     case JS_SPECIAL_API_OBJECT_TYPE:
1187     case JS_SHADOW_REALM_TYPE:
1188     case JS_SHARED_STRUCT_TYPE:
1189     case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
1190     case JS_STRING_ITERATOR_TYPE:
1191     case JS_TEMPORAL_CALENDAR_TYPE:
1192     case JS_TEMPORAL_DURATION_TYPE:
1193     case JS_TEMPORAL_INSTANT_TYPE:
1194     case JS_TEMPORAL_PLAIN_DATE_TYPE:
1195     case JS_TEMPORAL_PLAIN_DATE_TIME_TYPE:
1196     case JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE:
1197     case JS_TEMPORAL_PLAIN_TIME_TYPE:
1198     case JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE:
1199     case JS_TEMPORAL_TIME_ZONE_TYPE:
1200     case JS_TEMPORAL_ZONED_DATE_TIME_TYPE:
1201     case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
1202     case JS_FUNCTION_TYPE:
1203     case JS_CLASS_CONSTRUCTOR_TYPE:
1204     case JS_PROMISE_CONSTRUCTOR_TYPE:
1205     case JS_REG_EXP_CONSTRUCTOR_TYPE:
1206     case JS_WRAPPED_FUNCTION_TYPE:
1207     case JS_ARRAY_CONSTRUCTOR_TYPE:
1208 #define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
1209   case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
1210       TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
1211 #undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
1212 #ifdef V8_INTL_SUPPORT
1213     case JS_V8_BREAK_ITERATOR_TYPE:
1214     case JS_COLLATOR_TYPE:
1215     case JS_DATE_TIME_FORMAT_TYPE:
1216     case JS_DISPLAY_NAMES_TYPE:
1217     case JS_LIST_FORMAT_TYPE:
1218     case JS_LOCALE_TYPE:
1219     case JS_NUMBER_FORMAT_TYPE:
1220     case JS_PLURAL_RULES_TYPE:
1221     case JS_RELATIVE_TIME_FORMAT_TYPE:
1222     case JS_SEGMENT_ITERATOR_TYPE:
1223     case JS_SEGMENTER_TYPE:
1224     case JS_SEGMENTS_TYPE:
1225 #endif  // V8_INTL_SUPPORT
1226 #if V8_ENABLE_WEBASSEMBLY
1227     case WASM_GLOBAL_OBJECT_TYPE:
1228     case WASM_MEMORY_OBJECT_TYPE:
1229     case WASM_MODULE_OBJECT_TYPE:
1230     case WASM_SUSPENDER_OBJECT_TYPE:
1231     case WASM_TABLE_OBJECT_TYPE:
1232     case WASM_TAG_OBJECT_TYPE:
1233     case WASM_VALUE_OBJECT_TYPE:
1234 #endif  // V8_ENABLE_WEBASSEMBLY
1235       return CALL_APPLY(JSObject);
1236 #if V8_ENABLE_WEBASSEMBLY
1237     case WASM_INSTANCE_OBJECT_TYPE:
1238       return CALL_APPLY(WasmInstanceObject);
1239 #endif  // V8_ENABLE_WEBASSEMBLY
1240     case JS_WEAK_MAP_TYPE:
1241     case JS_WEAK_SET_TYPE:
1242       return CALL_APPLY(JSWeakCollection);
1243     case JS_ARRAY_BUFFER_TYPE:
1244       return CALL_APPLY(JSArrayBuffer);
1245     case JS_DATA_VIEW_TYPE:
1246       return CALL_APPLY(JSDataView);
1247     case JS_TYPED_ARRAY_TYPE:
1248       return CALL_APPLY(JSTypedArray);
1249     case JS_EXTERNAL_OBJECT_TYPE:
1250       return CALL_APPLY(JSExternalObject);
1251     case WEAK_CELL_TYPE:
1252       return CALL_APPLY(WeakCell);
1253     case JS_WEAK_REF_TYPE:
1254       return CALL_APPLY(JSWeakRef);
1255     case JS_PROXY_TYPE:
1256       return CALL_APPLY(JSProxy);
1257     case FOREIGN_TYPE:
1258       return CALL_APPLY(Foreign);
1259     case MAP_TYPE:
1260       return CALL_APPLY(Map);
1261     case CODE_TYPE:
1262       return CALL_APPLY(Code);
1263     case CELL_TYPE:
1264       return CALL_APPLY(Cell);
1265     case PROPERTY_CELL_TYPE:
1266       return CALL_APPLY(PropertyCell);
1267     case SYMBOL_TYPE:
1268       return CALL_APPLY(Symbol);
1269     case BYTECODE_ARRAY_TYPE:
1270       return CALL_APPLY(BytecodeArray);
1271     case SMALL_ORDERED_HASH_SET_TYPE:
1272       return CALL_APPLY(SmallOrderedHashTable<SmallOrderedHashSet>);
1273     case SMALL_ORDERED_HASH_MAP_TYPE:
1274       return CALL_APPLY(SmallOrderedHashTable<SmallOrderedHashMap>);
1275     case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
1276       return CALL_APPLY(SmallOrderedHashTable<SmallOrderedNameDictionary>);
1277     case SWISS_NAME_DICTIONARY_TYPE:
1278       return CALL_APPLY(SwissNameDictionary);
1279     case CODE_DATA_CONTAINER_TYPE:
1280       return CALL_APPLY(CodeDataContainer);
1281     case PREPARSE_DATA_TYPE:
1282       return CALL_APPLY(PreparseData);
1283     case HEAP_NUMBER_TYPE:
1284       return CALL_APPLY(HeapNumber);
1285     case BYTE_ARRAY_TYPE:
1286       return CALL_APPLY(ByteArray);
1287     case BIGINT_TYPE:
1288       return CALL_APPLY(BigInt);
1289     case ALLOCATION_SITE_TYPE:
1290       return CALL_APPLY(AllocationSite);
1291     case ODDBALL_TYPE:
1292       return CALL_APPLY(Oddball);
1293 
1294 #define MAKE_STRUCT_CASE(TYPE, Name, name) \
1295   case TYPE:                               \
1296     return CALL_APPLY(Name);
1297       STRUCT_LIST(MAKE_STRUCT_CASE)
1298 #undef MAKE_STRUCT_CASE
1299     case CALL_HANDLER_INFO_TYPE:
1300       return CALL_APPLY(CallHandlerInfo);
1301     case LOAD_HANDLER_TYPE:
1302       return CALL_APPLY(LoadHandler);
1303     case STORE_HANDLER_TYPE:
1304       return CALL_APPLY(StoreHandler);
1305     case SOURCE_TEXT_MODULE_TYPE:
1306       return CALL_APPLY(SourceTextModule);
1307     case SYNTHETIC_MODULE_TYPE:
1308       return CALL_APPLY(SyntheticModule);
1309 // TODO(turbofan): Avoid duplicated cases when the body descriptors are
1310 // identical.
1311 #define MAKE_TORQUE_BODY_DESCRIPTOR_APPLY(TYPE, TypeName) \
1312   case TYPE:                                              \
1313     return CALL_APPLY(TypeName);
1314       TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST(
1315           MAKE_TORQUE_BODY_DESCRIPTOR_APPLY)
1316 #undef MAKE_TORQUE_BODY_DESCRIPTOR_APPLY
1317 
1318     case FILLER_TYPE:
1319       return Op::template apply<FreeSpaceFillerBodyDescriptor>(
1320           std::forward<Args>(args)...);
1321 
1322     case FREE_SPACE_TYPE:
1323       return CALL_APPLY(FreeSpace);
1324 
1325     default:
1326       PrintF("Unknown type: %d\n", type);
1327       UNREACHABLE();
1328   }
1329 #undef CALL_APPLY
1330 }
1331 
1332 template <typename ObjectVisitor>
IterateFast(PtrComprCageBase cage_base,ObjectVisitor * v)1333 void HeapObject::IterateFast(PtrComprCageBase cage_base, ObjectVisitor* v) {
1334   v->VisitMapPointer(*this);
1335   IterateBodyFast(cage_base, v);
1336 }
1337 
1338 template <typename ObjectVisitor>
IterateFast(Map map,int object_size,ObjectVisitor * v)1339 void HeapObject::IterateFast(Map map, int object_size, ObjectVisitor* v) {
1340   v->VisitMapPointer(*this);
1341   IterateBodyFast(map, object_size, v);
1342 }
1343 
1344 template <typename ObjectVisitor>
IterateBodyFast(PtrComprCageBase cage_base,ObjectVisitor * v)1345 void HeapObject::IterateBodyFast(PtrComprCageBase cage_base, ObjectVisitor* v) {
1346   Map m = map(cage_base);
1347   IterateBodyFast(m, SizeFromMap(m), v);
1348 }
1349 
1350 struct CallIterateBody {
1351   template <typename BodyDescriptor, typename ObjectVisitor>
applyCallIterateBody1352   static void apply(Map map, HeapObject obj, int object_size,
1353                     ObjectVisitor* v) {
1354     BodyDescriptor::IterateBody(map, obj, object_size, v);
1355   }
1356 };
1357 
1358 template <typename ObjectVisitor>
IterateBodyFast(Map map,int object_size,ObjectVisitor * v)1359 void HeapObject::IterateBodyFast(Map map, int object_size, ObjectVisitor* v) {
1360   BodyDescriptorApply<CallIterateBody>(map.instance_type(), map, *this,
1361                                        object_size, v);
1362 }
1363 
1364 class EphemeronHashTable::BodyDescriptor final : public BodyDescriptorBase {
1365  public:
IsValidSlot(Map map,HeapObject obj,int offset)1366   static bool IsValidSlot(Map map, HeapObject obj, int offset) {
1367     return (offset >= EphemeronHashTable::kHeaderSize);
1368   }
1369 
1370   template <typename ObjectVisitor>
IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)1371   static inline void IterateBody(Map map, HeapObject obj, int object_size,
1372                                  ObjectVisitor* v) {
1373     int entries_start = EphemeronHashTable::kHeaderSize +
1374                         EphemeronHashTable::kElementsStartIndex * kTaggedSize;
1375     IteratePointers(obj, EphemeronHashTable::kHeaderSize, entries_start, v);
1376     EphemeronHashTable table = EphemeronHashTable::unchecked_cast(obj);
1377     for (InternalIndex i : table.IterateEntries()) {
1378       const int key_index = EphemeronHashTable::EntryToIndex(i);
1379       const int value_index = EphemeronHashTable::EntryToValueIndex(i);
1380       IterateEphemeron(obj, i.as_int(), OffsetOfElementAt(key_index),
1381                        OffsetOfElementAt(value_index), v);
1382     }
1383   }
1384 
SizeOf(Map map,HeapObject object)1385   static inline int SizeOf(Map map, HeapObject object) {
1386     return object.SizeFromMap(map);
1387   }
1388 };
1389 
1390 #include "torque-generated/objects-body-descriptors-inl.inc"
1391 
1392 }  // namespace internal
1393 }  // namespace v8
1394 
1395 #endif  // V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_INL_H_
1396