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