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