objects-body-descriptors-inl.h 43.1 KB
Newer Older
1 2 3 4
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_INL_H_
#define V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_INL_H_
7

8
#include "src/objects/objects-body-descriptors.h"
9 10 11

#include <algorithm>

12
#include "src/codegen/reloc-info.h"
13
#include "src/objects/cell.h"
14
#include "src/objects/data-handler.h"
15
#include "src/objects/feedback-vector.h"
16
#include "src/objects/foreign-inl.h"
17
#include "src/objects/hash-table.h"
18
#include "src/objects/js-collection.h"
19
#include "src/objects/js-weak-refs.h"
20
#include "src/objects/oddball.h"
21
#include "src/objects/ordered-hash-table.h"
22
#include "src/objects/source-text-module.h"
23
#include "src/objects/synthetic-module.h"
24
#include "src/objects/transitions.h"
25
#include "src/wasm/wasm-objects-inl.h"
26 27 28 29 30

namespace v8 {
namespace internal {

template <int start_offset>
31
int FlexibleBodyDescriptor<start_offset>::SizeOf(Map map, HeapObject object) {
32
  return object.SizeFromMap(map);
33 34
}

35 36
template <int start_offset>
int FlexibleWeakBodyDescriptor<start_offset>::SizeOf(Map map,
37
                                                     HeapObject object) {
38
  return object.SizeFromMap(map);
39 40
}

41
bool BodyDescriptorBase::IsValidJSObjectSlotImpl(Map map, HeapObject obj,
42
                                                 int offset) {
43 44 45
#ifdef V8_COMPRESS_POINTERS
  STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
  int embedder_fields_offset = JSObject::GetEmbedderFieldsStartOffset(map);
46
  int inobject_fields_offset = map.GetInObjectPropertyOffset(0);
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
  // |embedder_fields_offset| may be greater than |inobject_fields_offset| if
  // the object does not have embedder fields but the check handles this
  // case properly.
  if (embedder_fields_offset <= offset && offset < inobject_fields_offset) {
    // offset points to embedder fields area:
    // [embedder_fields_offset, inobject_fields_offset).
    STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize));
    return ((offset - embedder_fields_offset) & (kEmbedderDataSlotSize - 1)) ==
           EmbedderDataSlot::kTaggedPayloadOffset;
  }
#else
  // We store raw aligned pointers as Smis, so it's safe to treat the whole
  // embedder field area as tagged slots.
  STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
#endif
62
  if (!FLAG_unbox_double_fields || map.HasFastPointerLayout()) {
63 64 65
    return true;
  } else {
    DCHECK(FLAG_unbox_double_fields);
66
    DCHECK(IsAligned(offset, kSystemPointerSize));
67

68
    LayoutDescriptorHelper helper(map);
69 70 71 72 73 74
    DCHECK(!helper.all_fields_tagged());
    return helper.IsTagged(offset);
  }
}

template <typename ObjectVisitor>
75
void BodyDescriptorBase::IterateJSObjectBodyImpl(Map map, HeapObject obj,
76 77 78
                                                 int start_offset,
                                                 int end_offset,
                                                 ObjectVisitor* v) {
79 80 81
#ifdef V8_COMPRESS_POINTERS
  STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
  int header_size = JSObject::GetHeaderSize(map);
82
  int inobject_fields_offset = map.GetInObjectPropertyOffset(0);
83 84
  // We are always requested to process header and embedder fields.
  DCHECK_LE(inobject_fields_offset, end_offset);
85
  // Embedder fields are located between header and inobject properties.
86 87 88 89
  if (header_size < inobject_fields_offset) {
    // There are embedder fields.
    IteratePointers(obj, start_offset, header_size, v);
    // Iterate only tagged payload of the embedder slots and skip raw payload.
90 91
    DCHECK_EQ(header_size, JSObject::GetEmbedderFieldsStartOffset(map));
    for (int offset = header_size + EmbedderDataSlot::kTaggedPayloadOffset;
92 93 94 95 96 97 98 99 100 101 102
         offset < inobject_fields_offset; offset += kEmbedderDataSlotSize) {
      IteratePointer(obj, offset, v);
    }
    // Proceed processing inobject properties.
    start_offset = inobject_fields_offset;
  }
#else
  // We store raw aligned pointers as Smis, so it's safe to iterate the whole
  // embedder field area as tagged slots.
  STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
#endif
103
  if (!FLAG_unbox_double_fields || map.HasFastPointerLayout()) {
104 105 106
    IteratePointers(obj, start_offset, end_offset, v);
  } else {
    DCHECK(FLAG_unbox_double_fields);
107 108
    DCHECK(IsAligned(start_offset, kSystemPointerSize) &&
           IsAligned(end_offset, kSystemPointerSize));
109

110
    LayoutDescriptorHelper helper(map);
111 112 113 114 115 116 117 118 119 120 121 122
    DCHECK(!helper.all_fields_tagged());
    for (int offset = start_offset; offset < end_offset;) {
      int end_of_region_offset;
      if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
        IteratePointers(obj, offset, end_of_region_offset, v);
      }
      offset = end_of_region_offset;
    }
  }
}

template <typename ObjectVisitor>
123
DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(HeapObject obj,
124 125 126
                                                          int start_offset,
                                                          int end_offset,
                                                          ObjectVisitor* v) {
127
  v->VisitPointers(obj, obj.RawField(start_offset), obj.RawField(end_offset));
128 129 130
}

template <typename ObjectVisitor>
131
void BodyDescriptorBase::IteratePointer(HeapObject obj, int offset,
132
                                        ObjectVisitor* v) {
133
  v->VisitPointer(obj, obj.RawField(offset));
134 135
}

136 137
template <typename ObjectVisitor>
DISABLE_CFI_PERF void BodyDescriptorBase::IterateMaybeWeakPointers(
138
    HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) {
139 140
  v->VisitPointers(obj, obj.RawMaybeWeakField(start_offset),
                   obj.RawMaybeWeakField(end_offset));
141 142
}

143
template <typename ObjectVisitor>
144
void BodyDescriptorBase::IterateMaybeWeakPointer(HeapObject obj, int offset,
145
                                                 ObjectVisitor* v) {
146
  v->VisitPointer(obj, obj.RawMaybeWeakField(offset));
147 148
}

149 150
template <typename ObjectVisitor>
DISABLE_CFI_PERF void BodyDescriptorBase::IterateCustomWeakPointers(
151
    HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) {
152 153
  v->VisitCustomWeakPointers(obj, obj.RawField(start_offset),
                             obj.RawField(end_offset));
154 155
}

156 157 158 159 160 161
template <typename ObjectVisitor>
DISABLE_CFI_PERF void BodyDescriptorBase::IterateEphemeron(HeapObject obj,
                                                           int index,
                                                           int key_offset,
                                                           int value_offset,
                                                           ObjectVisitor* v) {
162 163
  v->VisitEphemeron(obj, index, obj.RawField(key_offset),
                    obj.RawField(value_offset));
164 165
}

166
template <typename ObjectVisitor>
167
void BodyDescriptorBase::IterateCustomWeakPointer(HeapObject obj, int offset,
168
                                                  ObjectVisitor* v) {
169
  v->VisitCustomWeakPointer(obj, obj.RawField(offset));
170 171
}

172 173
class JSObject::BodyDescriptor final : public BodyDescriptorBase {
 public:
174
  static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
175

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>
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
  }

187
  static inline int SizeOf(Map map, HeapObject object) {
188
    return map.instance_size();
189 190
  }
};
191

192 193
class JSObject::FastBodyDescriptor final : public BodyDescriptorBase {
 public:
194
  static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
195

196
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
197 198 199 200
    return offset >= kStartOffset;
  }

  template <typename ObjectVisitor>
201
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
202 203 204 205
                                 ObjectVisitor* v) {
    IteratePointers(obj, kStartOffset, object_size, v);
  }

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:
213
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
214
    return offset >= HeapObject::kHeaderSize;
215 216 217
  }

  template <typename ObjectVisitor>
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
    IteratePointers(obj, kTargetOffset + kTaggedSize, object_size, v);
223 224
  }

225
  static inline int SizeOf(Map map, HeapObject object) {
226
    return map.instance_size();
227 228 229
  }
};

230 231
class JSWeakRef::BodyDescriptor final : public BodyDescriptorBase {
 public:
232
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
233
    return IsValidJSObjectSlotImpl(map, obj, offset);
234 235 236
  }

  template <typename ObjectVisitor>
237
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
238 239 240
                                 ObjectVisitor* v) {
    IteratePointers(obj, JSReceiver::kPropertiesOrHashOffset, kTargetOffset, v);
    IterateCustomWeakPointer(obj, kTargetOffset, v);
241 242
    IterateJSObjectBodyImpl(map, obj, kTargetOffset + kTaggedSize, object_size,
                            v);
243 244
  }

245
  static inline int SizeOf(Map map, HeapObject object) {
246
    return map.instance_size();
247 248 249
  }
};

250 251
class SharedFunctionInfo::BodyDescriptor final : public BodyDescriptorBase {
 public:
252
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
253 254 255 256 257
    static_assert(kEndOfWeakFieldsOffset == kStartOfStrongFieldsOffset,
                  "Leverage that strong fields directly follow weak fields"
                  "to call FixedBodyDescriptor<...>::IsValidSlot below");
    return FixedBodyDescriptor<kStartOfWeakFieldsOffset,
                               kEndOfStrongFieldsOffset,
258 259 260 261
                               kAlignedSize>::IsValidSlot(map, obj, offset);
  }

  template <typename ObjectVisitor>
262
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
263 264
                                 ObjectVisitor* v) {
    IterateCustomWeakPointer(obj, kFunctionDataOffset, v);
265
    IteratePointers(obj, SharedFunctionInfo::kStartOfStrongFieldsOffset,
266
                    SharedFunctionInfo::kEndOfStrongFieldsOffset, v);
267 268
  }

269
  static inline int SizeOf(Map map, HeapObject object) {
270
    return map.instance_size();
271 272 273
  }
};

274
class AllocationSite::BodyDescriptor final : public BodyDescriptorBase {
275
 public:
276 277 278 279 280 281 282
  STATIC_ASSERT(AllocationSite::kCommonPointerFieldEndOffset ==
                AllocationSite::kPretenureDataOffset);
  STATIC_ASSERT(AllocationSite::kPretenureDataOffset + kInt32Size ==
                AllocationSite::kPretenureCreateCountOffset);
  STATIC_ASSERT(AllocationSite::kPretenureCreateCountOffset + kInt32Size ==
                AllocationSite::kWeakNextOffset);

283
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
284 285 286 287 288
    if (offset >= AllocationSite::kStartOffset &&
        offset < AllocationSite::kCommonPointerFieldEndOffset) {
      return true;
    }
    // check for weak_next offset
289
    if (map.instance_size() == AllocationSite::kSizeWithWeakNext &&
290 291 292 293
        offset == AllocationSite::kWeakNextOffset) {
      return true;
    }
    return false;
294 295 296
  }

  template <typename ObjectVisitor>
297
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
298
                                 ObjectVisitor* v) {
299 300 301
    // Iterate over all the common pointer fields
    IteratePointers(obj, AllocationSite::kStartOffset,
                    AllocationSite::kCommonPointerFieldEndOffset, v);
302 303 304 305 306 307
    // Skip PretenureDataOffset and PretenureCreateCount which are Int32 fields.
    // Visit weak_next only if it has weak_next field.
    if (object_size == AllocationSite::kSizeWithWeakNext) {
      IterateCustomWeakPointers(obj, AllocationSite::kWeakNextOffset,
                                AllocationSite::kSizeWithWeakNext, v);
    }
308 309
  }

310
  static inline int SizeOf(Map map, HeapObject object) {
311
    return map.instance_size();
312 313 314
  }
};

315 316
class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
 public:
317
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
318 319
    if (offset < kEndOfTaggedFieldsOffset) return true;
    if (offset < kHeaderSize) return false;
320
    return IsValidJSObjectSlotImpl(map, obj, offset);
321 322 323
  }

  template <typename ObjectVisitor>
324
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
325
                                 ObjectVisitor* v) {
326
    // JSArrayBuffer instances contain raw data that the GC does not know about.
327
    IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
328
    IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
329 330
  }

331
  static inline int SizeOf(Map map, HeapObject object) {
332
    return map.instance_size();
333 334 335
  }
};

336
class JSTypedArray::BodyDescriptor final : public BodyDescriptorBase {
337
 public:
338
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
339
    if (offset < kEndOfTaggedFieldsOffset) return true;
340 341
    // TODO(v8:4153): Remove this.
    if (offset == kBasePointerOffset) return true;
342
    if (offset < kHeaderSize) return false;
343
    return IsValidJSObjectSlotImpl(map, obj, offset);
344 345 346
  }

  template <typename ObjectVisitor>
347
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
348
                                 ObjectVisitor* v) {
349 350
    // JSTypedArray contains raw data that the GC does not know about.
    IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
351 352
    // TODO(v8:4153): Remove this.
    IteratePointer(obj, kBasePointerOffset, v);
353 354 355 356
    IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
  }

  static inline int SizeOf(Map map, HeapObject object) {
357
    return map.instance_size();
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
  }
};

class JSDataView::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
    if (offset < kEndOfTaggedFieldsOffset) return true;
    if (offset < kHeaderSize) return false;
    return IsValidJSObjectSlotImpl(map, obj, offset);
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
                                 ObjectVisitor* v) {
    // JSDataView contains raw data that the GC does not know about.
373
    IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
374
    IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
375 376
  }

377
  static inline int SizeOf(Map map, HeapObject object) {
378
    return map.instance_size();
379 380 381
  }
};

382
template <typename Derived>
383
class V8_EXPORT_PRIVATE SmallOrderedHashTable<Derived>::BodyDescriptor final
384
    : public BodyDescriptorBase {
385
 public:
386
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
387
    Derived table = Derived::cast(obj);
388 389
    // Only data table part contains tagged values.
    return (offset >= DataTableStartOffset()) &&
390
           (offset < table.GetBucketsStartOffset());
391 392 393
  }

  template <typename ObjectVisitor>
394
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
395
                                 ObjectVisitor* v) {
396
    Derived table = Derived::cast(obj);
397
    int start_offset = DataTableStartOffset();
398
    int end_offset = table.GetBucketsStartOffset();
399
    IteratePointers(obj, start_offset, end_offset, v);
400 401
  }

402
  static inline int SizeOf(Map map, HeapObject obj) {
403
    Derived table = Derived::cast(obj);
404
    return table.SizeFor(table.Capacity());
405 406 407
  }
};

408 409
class ByteArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
410
  static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
411 412

  template <typename ObjectVisitor>
413
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
414 415
                                 ObjectVisitor* v) {}

416
  static inline int SizeOf(Map map, HeapObject obj) {
417
    return ByteArray::SizeFor(ByteArray::cast(obj).synchronized_length());
418 419 420
  }
};

421 422
class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
423
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
424 425
    return offset >= kConstantPoolOffset &&
           offset <= kSourcePositionTableOffset;
426 427 428
  }

  template <typename ObjectVisitor>
429
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
430 431
                                 ObjectVisitor* v) {
    IteratePointer(obj, kConstantPoolOffset, v);
432
    IteratePointer(obj, kHandlerTableOffset, v);
433
    IteratePointer(obj, kSourcePositionTableOffset, v);
434 435
  }

436
  static inline int SizeOf(Map map, HeapObject obj) {
437
    return BytecodeArray::SizeFor(
438
        BytecodeArray::cast(obj).synchronized_length());
439 440 441
  }
};

442 443
class BigInt::BodyDescriptor final : public BodyDescriptorBase {
 public:
444
  static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
445 446

  template <typename ObjectVisitor>
447
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
448 449
                                 ObjectVisitor* v) {}

450
  static inline int SizeOf(Map map, HeapObject obj) {
451
    return BigInt::SizeFor(BigInt::cast(obj).synchronized_length());
452 453 454
  }
};

455 456
class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
457
  static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
458 459

  template <typename ObjectVisitor>
460
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
461 462
                                 ObjectVisitor* v) {}

463
  static inline int SizeOf(Map map, HeapObject obj) {
464
    return FixedDoubleArray::SizeFor(
465
        FixedDoubleArray::cast(obj).synchronized_length());
466 467 468
  }
};

469 470
class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
 public:
471
  static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
472 473

  template <typename ObjectVisitor>
474
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
475 476
                                 ObjectVisitor* v) {}

477
  static inline int SizeOf(Map map, HeapObject obj) {
478
    return FeedbackMetadata::SizeFor(
479
        FeedbackMetadata::cast(obj).synchronized_slot_count());
480 481 482
  }
};

483 484
class FeedbackVector::BodyDescriptor final : public BodyDescriptorBase {
 public:
485
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
486
    return offset == kSharedFunctionInfoOffset ||
Irina Yatsenko's avatar
Irina Yatsenko committed
487
           offset == kOptimizedCodeWeakOrSmiOffset ||
488 489
           offset == kClosureFeedbackCellArrayOffset ||
           offset >= kFeedbackSlotsOffset;
490 491 492
  }

  template <typename ObjectVisitor>
493
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
494 495
                                 ObjectVisitor* v) {
    IteratePointer(obj, kSharedFunctionInfoOffset, v);
Irina Yatsenko's avatar
Irina Yatsenko committed
496
    IterateMaybeWeakPointer(obj, kOptimizedCodeWeakOrSmiOffset, v);
497
    IteratePointer(obj, kClosureFeedbackCellArrayOffset, v);
498
    IterateMaybeWeakPointers(obj, kFeedbackSlotsOffset, object_size, v);
499 500
  }

501
  static inline int SizeOf(Map map, HeapObject obj) {
502
    return FeedbackVector::SizeFor(FeedbackVector::cast(obj).length());
503 504 505
  }
};

506
class PreparseData::BodyDescriptor final : public BodyDescriptorBase {
507
 public:
508
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
509
    return offset >= PreparseData::cast(obj).inner_start_offset();
510 511 512
  }

  template <typename ObjectVisitor>
513
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
514
                                 ObjectVisitor* v) {
515
    PreparseData data = PreparseData::cast(obj);
516 517
    int start_offset = data.inner_start_offset();
    int end_offset = start_offset + data.children_length() * kTaggedSize;
518
    IteratePointers(obj, start_offset, end_offset, v);
519 520
  }

521
  static inline int SizeOf(Map map, HeapObject obj) {
522
    PreparseData data = PreparseData::cast(obj);
523
    return PreparseData::SizeFor(data.data_length(), data.children_length());
524 525 526
  }
};

527 528
class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase {
 public:
529
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
530 531 532 533
    return offset >= HeapObject::kHeaderSize;
  }

  template <typename ObjectVisitor>
534
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
535 536 537
                                 ObjectVisitor* v) {
    IteratePointers(obj, HeapObject::kHeaderSize, kObjectCreateMapOffset, v);
    IterateMaybeWeakPointer(obj, kObjectCreateMapOffset, v);
538
    IteratePointers(obj, kObjectCreateMapOffset + kTaggedSize, object_size, v);
539 540
  }

541
  static inline int SizeOf(Map map, HeapObject obj) {
542
    return obj.SizeFromMap(map);
543 544 545
  }
};

546
class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
547
 public:
548
  STATIC_ASSERT(kTableOffset + kTaggedSize == kSizeOfAllWeakCollections);
549

550
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
551
    return IsValidJSObjectSlotImpl(map, obj, offset);
552 553 554
  }

  template <typename ObjectVisitor>
555
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
556
                                 ObjectVisitor* v) {
557
    IterateJSObjectBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v);
558 559
  }

560
  static inline int SizeOf(Map map, HeapObject object) {
561
    return map.instance_size();
562
  }
563 564 565 566
};

class Foreign::BodyDescriptor final : public BodyDescriptorBase {
 public:
567
  static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
568 569

  template <typename ObjectVisitor>
570
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
571
                                 ObjectVisitor* v) {
572
    v->VisitExternalReference(
573 574
        Foreign::cast(obj), reinterpret_cast<Address*>(
                                obj.RawField(kForeignAddressOffset).address()));
575 576
  }

577
  static inline int SizeOf(Map map, HeapObject object) { return kSize; }
578 579 580 581
};

class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
582
  static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
583 584

  template <typename ObjectVisitor>
585
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
586
                                 ObjectVisitor* v) {}
587

588
  static inline int SizeOf(Map map, HeapObject object) { return kSize; }
589 590 591 592
};

class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
593
  static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
594 595

  template <typename ObjectVisitor>
596
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
597
                                 ObjectVisitor* v) {}
598

599
  static inline int SizeOf(Map map, HeapObject object) { return kSize; }
600 601 602 603
};

class Code::BodyDescriptor final : public BodyDescriptorBase {
 public:
604
  STATIC_ASSERT(kRelocationInfoOffset + kTaggedSize ==
605
                kDeoptimizationDataOffset);
606
  STATIC_ASSERT(kDeoptimizationDataOffset + kTaggedSize ==
607
                kSourcePositionTableOffset);
608
  STATIC_ASSERT(kSourcePositionTableOffset + kTaggedSize ==
609
                kCodeDataContainerOffset);
610
  STATIC_ASSERT(kCodeDataContainerOffset + kTaggedSize == kDataStart);
611

612
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
613 614 615 616
    // Slots in code can't be invalid because we never trim code objects.
    return true;
  }

617 618 619
  static constexpr int kRelocModeMask =
      RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
      RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
620 621
      RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
      RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) |
622 623 624 625 626 627
      RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
      RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
      RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
      RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) |
      RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);

628
  template <typename ObjectVisitor>
629
  static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) {
630
    // GC does not visit data/code in the header and in the body directly.
631
    IteratePointers(obj, kRelocationInfoOffset, kDataStart, v);
632

633
    RelocIterator it(Code::cast(obj), kRelocModeMask);
634
    v->VisitRelocInfo(&it);
635 636 637
  }

  template <typename ObjectVisitor>
638
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
639
                                 ObjectVisitor* v) {
640
    IterateBody(map, obj, v);
641 642
  }

643
  static inline int SizeOf(Map map, HeapObject object) {
644
    return Code::unchecked_cast(object).CodeSize();
645 646 647
  }
};

648 649
class SeqOneByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
650
  static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
651 652

  template <typename ObjectVisitor>
653
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
654 655
                                 ObjectVisitor* v) {}

656
  static inline int SizeOf(Map map, HeapObject obj) {
657
    SeqOneByteString string = SeqOneByteString::cast(obj);
658
    return string.SizeFor(string.synchronized_length());
659 660 661 662 663
  }
};

class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
664
  static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
665 666

  template <typename ObjectVisitor>
667
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
668 669
                                 ObjectVisitor* v) {}

670
  static inline int SizeOf(Map map, HeapObject obj) {
671
    SeqTwoByteString string = SeqTwoByteString::cast(obj);
672
    return string.SizeFor(string.synchronized_length());
673 674
  }
};
675

676 677
class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
 public:
678
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
679 680 681 682 683 684 685 686 687
    SLOW_DCHECK(std::is_sorted(std::begin(kTaggedFieldOffsets),
                               std::end(kTaggedFieldOffsets)));
    STATIC_ASSERT(sizeof(*kTaggedFieldOffsets) == sizeof(uint16_t));
    if (offset < int{8 * sizeof(*kTaggedFieldOffsets)} &&
        std::binary_search(std::begin(kTaggedFieldOffsets),
                           std::end(kTaggedFieldOffsets),
                           static_cast<uint16_t>(offset))) {
      return true;
    }
688
    return IsValidJSObjectSlotImpl(map, obj, offset);
689 690 691
  }

  template <typename ObjectVisitor>
692
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
693
                                 ObjectVisitor* v) {
694
    IteratePointers(obj, kPropertiesOrHashOffset, JSObject::kHeaderSize, v);
695 696 697
    for (uint16_t offset : kTaggedFieldOffsets) {
      IteratePointer(obj, offset, v);
    }
698
    IterateJSObjectBodyImpl(map, obj, kSize, object_size, v);
699 700
  }

701
  static inline int SizeOf(Map map, HeapObject object) {
702
    return map.instance_size();
703 704 705
  }
};

706 707
class Map::BodyDescriptor final : public BodyDescriptorBase {
 public:
708
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
709 710 711 712 713 714
    static_assert(
        Map::kEndOfStrongFieldsOffset == Map::kStartOfWeakFieldsOffset,
        "Leverage that weak fields directly follow strong fields for the "
        "check below");
    return offset >= Map::kStartOfStrongFieldsOffset &&
           offset < Map::kEndOfWeakFieldsOffset;
715 716 717
  }

  template <typename ObjectVisitor>
718
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
719
                                 ObjectVisitor* v) {
720 721
    IteratePointers(obj, Map::kStartOfStrongFieldsOffset,
                    Map::kEndOfStrongFieldsOffset, v);
722 723 724
    IterateMaybeWeakPointer(obj, kTransitionsOrPrototypeInfoOffset, v);
  }

725
  static inline int SizeOf(Map map, HeapObject obj) { return Map::kSize; }
726 727
};

728 729
class DataHandler::BodyDescriptor final : public BodyDescriptorBase {
 public:
730
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
731 732 733 734
    return offset >= HeapObject::kHeaderSize;
  }

  template <typename ObjectVisitor>
735
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
736 737 738 739 740 741
                                 ObjectVisitor* v) {
    static_assert(kSmiHandlerOffset < kData1Offset,
                  "Field order must be in sync with this iteration code");
    static_assert(kData1Offset < kSizeWithData1,
                  "Field order must be in sync with this iteration code");
    IteratePointers(obj, kSmiHandlerOffset, kData1Offset, v);
742
    IterateMaybeWeakPointers(obj, kData1Offset, object_size, v);
743 744
  }

745
  static inline int SizeOf(Map map, HeapObject object) {
746
    return object.SizeFromMap(map);
747 748 749
  }
};

750
class NativeContext::BodyDescriptor final : public BodyDescriptorBase {
751
 public:
752
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
753
    return offset < NativeContext::kEndOfTaggedFieldsOffset;
754 755 756
  }

  template <typename ObjectVisitor>
757
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
758
                                 ObjectVisitor* v) {
759 760 761 762
    IteratePointers(obj, NativeContext::kStartOfStrongFieldsOffset,
                    NativeContext::kEndOfStrongFieldsOffset, v);
    IterateCustomWeakPointers(obj, NativeContext::kStartOfWeakFieldsOffset,
                              NativeContext::kEndOfWeakFieldsOffset, v);
763 764
  }

765
  static inline int SizeOf(Map map, HeapObject object) {
766
    return NativeContext::kSize;
767 768 769 770 771
  }
};

class CodeDataContainer::BodyDescriptor final : public BodyDescriptorBase {
 public:
772
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
773 774 775 776 777
    return offset >= CodeDataContainer::kHeaderSize &&
           offset < CodeDataContainer::kSize;
  }

  template <typename ObjectVisitor>
778
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
779 780 781 782 783 784 785 786
                                 ObjectVisitor* v) {
    IteratePointers(obj, CodeDataContainer::kHeaderSize,
                    CodeDataContainer::kPointerFieldsStrongEndOffset, v);
    IterateCustomWeakPointers(
        obj, CodeDataContainer::kPointerFieldsStrongEndOffset,
        CodeDataContainer::kPointerFieldsWeakEndOffset, v);
  }

787
  static inline int SizeOf(Map map, HeapObject object) {
788 789 790 791
    return CodeDataContainer::kSize;
  }
};

792 793
class EmbedderDataArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
794
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
795
#ifdef V8_COMPRESS_POINTERS
796
    STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
797 798 799 800 801 802 803
    STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize));
    return (offset < EmbedderDataArray::kHeaderSize) ||
           (((offset - EmbedderDataArray::kHeaderSize) &
             (kEmbedderDataSlotSize - 1)) ==
            EmbedderDataSlot::kTaggedPayloadOffset);
#else
    STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
804 805 806
    // We store raw aligned pointers as Smis, so it's safe to iterate the whole
    // array.
    return true;
807
#endif
808 809 810
  }

  template <typename ObjectVisitor>
811
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
812
                                 ObjectVisitor* v) {
813
#ifdef V8_COMPRESS_POINTERS
814
    STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
815 816 817 818 819 820 821
    // Iterate only tagged payload of the embedder slots and skip raw payload.
    for (int offset = EmbedderDataArray::OffsetOfElementAt(0) +
                      EmbedderDataSlot::kTaggedPayloadOffset;
         offset < object_size; offset += kEmbedderDataSlotSize) {
      IteratePointer(obj, offset, v);
    }
#else
822 823
    // We store raw aligned pointers as Smis, so it's safe to iterate the whole
    // array.
824
    STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
825
    IteratePointers(obj, EmbedderDataArray::kHeaderSize, object_size, v);
826
#endif
827 828
  }

829
  static inline int SizeOf(Map map, HeapObject object) {
830
    return object.SizeFromMap(map);
831 832 833
  }
};

834
template <typename Op, typename ReturnType, typename T1, typename T2,
835 836
          typename T3, typename T4>
ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
837 838 839 840 841
  if (type < FIRST_NONSTRING_TYPE) {
    switch (type & kStringRepresentationMask) {
      case kSeqStringTag:
        return ReturnType();
      case kConsStringTag:
842
        return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3, p4);
843
      case kThinStringTag:
844
        return Op::template apply<ThinString::BodyDescriptor>(p1, p2, p3, p4);
845
      case kSlicedStringTag:
846
        return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3, p4);
847 848 849
      case kExternalStringTag:
        if ((type & kStringEncodingMask) == kOneByteStringTag) {
          return Op::template apply<ExternalOneByteString::BodyDescriptor>(
850
              p1, p2, p3, p4);
851 852
        } else {
          return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
853
              p1, p2, p3, p4);
854 855 856 857 858 859
        }
    }
    UNREACHABLE();
  }

  switch (type) {
860 861 862
    case EMBEDDER_DATA_ARRAY_TYPE:
      return Op::template apply<EmbedderDataArray::BodyDescriptor>(p1, p2, p3,
                                                                   p4);
863
    case FIXED_ARRAY_TYPE:
864
    case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
865
    case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
866
    case HASH_TABLE_TYPE:
867 868
    case ORDERED_HASH_MAP_TYPE:
    case ORDERED_HASH_SET_TYPE:
869
    case ORDERED_NAME_DICTIONARY_TYPE:
870 871 872 873 874
    case NAME_DICTIONARY_TYPE:
    case GLOBAL_DICTIONARY_TYPE:
    case NUMBER_DICTIONARY_TYPE:
    case SIMPLE_NUMBER_DICTIONARY_TYPE:
    case STRING_TABLE_TYPE:
875
    case SCOPE_INFO_TYPE:
876
    case SCRIPT_CONTEXT_TABLE_TYPE:
877
      return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3, p4);
878 879 880
    case EPHEMERON_HASH_TABLE_TYPE:
      return Op::template apply<EphemeronHashTable::BodyDescriptor>(p1, p2, p3,
                                                                    p4);
881
    case AWAIT_CONTEXT_TYPE:
882 883 884 885 886 887 888 889
    case BLOCK_CONTEXT_TYPE:
    case CATCH_CONTEXT_TYPE:
    case DEBUG_EVALUATE_CONTEXT_TYPE:
    case EVAL_CONTEXT_TYPE:
    case FUNCTION_CONTEXT_TYPE:
    case MODULE_CONTEXT_TYPE:
    case SCRIPT_CONTEXT_TYPE:
    case WITH_CONTEXT_TYPE:
890 891 892
      return Op::template apply<Context::BodyDescriptor>(p1, p2, p3, p4);
    case NATIVE_CONTEXT_TYPE:
      return Op::template apply<NativeContext::BodyDescriptor>(p1, p2, p3, p4);
893
    case WEAK_FIXED_ARRAY_TYPE:
894
      return Op::template apply<WeakFixedArray::BodyDescriptor>(p1, p2, p3, p4);
895 896
    case WEAK_ARRAY_LIST_TYPE:
      return Op::template apply<WeakArrayList::BodyDescriptor>(p1, p2, p3, p4);
897 898
    case FIXED_DOUBLE_ARRAY_TYPE:
      return ReturnType();
899
    case FEEDBACK_METADATA_TYPE:
900 901
      return Op::template apply<FeedbackMetadata::BodyDescriptor>(p1, p2, p3,
                                                                  p4);
902
    case PROPERTY_ARRAY_TYPE:
903
      return Op::template apply<PropertyArray::BodyDescriptor>(p1, p2, p3, p4);
904
    case DESCRIPTOR_ARRAY_TYPE:
905 906
      return Op::template apply<DescriptorArray::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
907
    case TRANSITION_ARRAY_TYPE:
908 909
      return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
910
    case FEEDBACK_CELL_TYPE:
911
      return Op::template apply<FeedbackCell::BodyDescriptor>(p1, p2, p3, p4);
912
    case FEEDBACK_VECTOR_TYPE:
913
      return Op::template apply<FeedbackVector::BodyDescriptor>(p1, p2, p3, p4);
914
    case JS_OBJECT_TYPE:
915 916
    case JS_ERROR_TYPE:
    case JS_ARGUMENTS_TYPE:
917
    case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
918
    case JS_PROMISE_TYPE:
919 920
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    case JS_GENERATOR_OBJECT_TYPE:
921
    case JS_ASYNC_FUNCTION_OBJECT_TYPE:
922
    case JS_ASYNC_GENERATOR_OBJECT_TYPE:
923
    case JS_PRIMITIVE_WRAPPER_TYPE:
924 925
    case JS_DATE_TYPE:
    case JS_ARRAY_TYPE:
926
    case JS_ARRAY_ITERATOR_TYPE:
927
    case JS_MODULE_NAMESPACE_TYPE:
928 929
    case JS_SET_TYPE:
    case JS_MAP_TYPE:
930 931 932 933 934
    case JS_SET_KEY_VALUE_ITERATOR_TYPE:
    case JS_SET_VALUE_ITERATOR_TYPE:
    case JS_MAP_KEY_ITERATOR_TYPE:
    case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
    case JS_MAP_VALUE_ITERATOR_TYPE:
935
    case JS_STRING_ITERATOR_TYPE:
936
    case JS_REGEXP_STRING_ITERATOR_TYPE:
937 938 939
    case JS_REGEXP_TYPE:
    case JS_GLOBAL_PROXY_TYPE:
    case JS_GLOBAL_OBJECT_TYPE:
940
    case JS_API_OBJECT_TYPE:
941
    case JS_SPECIAL_API_OBJECT_TYPE:
942
    case JS_MESSAGE_OBJECT_TYPE:
943
    case JS_BOUND_FUNCTION_TYPE:
944 945
    case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
    case JS_FINALIZATION_GROUP_TYPE:
946
#ifdef V8_INTL_SUPPORT
947
    case JS_INTL_V8_BREAK_ITERATOR_TYPE:
948
    case JS_INTL_COLLATOR_TYPE:
949
    case JS_INTL_DATE_TIME_FORMAT_TYPE:
950
    case JS_INTL_LIST_FORMAT_TYPE:
951
    case JS_INTL_LOCALE_TYPE:
952
    case JS_INTL_NUMBER_FORMAT_TYPE:
953
    case JS_INTL_PLURAL_RULES_TYPE:
954
    case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
955
    case JS_INTL_SEGMENT_ITERATOR_TYPE:
956
    case JS_INTL_SEGMENTER_TYPE:
957
#endif  // V8_INTL_SUPPORT
958
    case WASM_EXCEPTION_TYPE:
959
    case WASM_GLOBAL_TYPE:
960 961 962
    case WASM_MEMORY_TYPE:
    case WASM_MODULE_TYPE:
    case WASM_TABLE_TYPE:
963
      return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3, p4);
964
    case WASM_INSTANCE_TYPE:
965 966
      return Op::template apply<WasmInstanceObject::BodyDescriptor>(p1, p2, p3,
                                                                    p4);
967 968
    case JS_WEAK_MAP_TYPE:
    case JS_WEAK_SET_TYPE:
969 970
      return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3,
                                                                  p4);
971
    case JS_ARRAY_BUFFER_TYPE:
972
      return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3, p4);
973 974 975 976
    case JS_DATA_VIEW_TYPE:
      return Op::template apply<JSDataView::BodyDescriptor>(p1, p2, p3, p4);
    case JS_TYPED_ARRAY_TYPE:
      return Op::template apply<JSTypedArray::BodyDescriptor>(p1, p2, p3, p4);
977
    case JS_FUNCTION_TYPE:
978
      return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3, p4);
979 980
    case WEAK_CELL_TYPE:
      return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3, p4);
981 982
    case JS_WEAK_REF_TYPE:
      return Op::template apply<JSWeakRef::BodyDescriptor>(p1, p2, p3, p4);
983
    case ODDBALL_TYPE:
984
      return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3, p4);
985
    case JS_PROXY_TYPE:
986
      return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3, p4);
987
    case FOREIGN_TYPE:
988
      return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3, p4);
989
    case MAP_TYPE:
990
      return Op::template apply<Map::BodyDescriptor>(p1, p2, p3, p4);
991
    case CODE_TYPE:
992
      return Op::template apply<Code::BodyDescriptor>(p1, p2, p3, p4);
993
    case CELL_TYPE:
994
      return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3, p4);
995
    case PROPERTY_CELL_TYPE:
996
      return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3, p4);
997
    case SYMBOL_TYPE:
998
      return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3, p4);
999
    case BYTECODE_ARRAY_TYPE:
1000
      return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3, p4);
1001
    case SMALL_ORDERED_HASH_SET_TYPE:
1002 1003
      return Op::template apply<
          SmallOrderedHashTable<SmallOrderedHashSet>::BodyDescriptor>(p1, p2,
1004
                                                                      p3, p4);
1005 1006 1007
    case SMALL_ORDERED_HASH_MAP_TYPE:
      return Op::template apply<
          SmallOrderedHashTable<SmallOrderedHashMap>::BodyDescriptor>(p1, p2,
1008
                                                                      p3, p4);
1009 1010 1011 1012
    case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
      return Op::template apply<
          SmallOrderedHashTable<SmallOrderedNameDictionary>::BodyDescriptor>(
          p1, p2, p3, p4);
1013
    case CODE_DATA_CONTAINER_TYPE:
1014 1015
      return Op::template apply<CodeDataContainer::BodyDescriptor>(p1, p2, p3,
                                                                   p4);
1016
    case PREPARSE_DATA_TYPE:
1017
      return Op::template apply<PreparseData::BodyDescriptor>(p1, p2, p3, p4);
1018
    case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE:
1019
      return Op::template apply<
1020
          UncompiledDataWithoutPreparseData::BodyDescriptor>(p1, p2, p3, p4);
1021
    case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE:
1022 1023
      return Op::template apply<UncompiledDataWithPreparseData::BodyDescriptor>(
          p1, p2, p3, p4);
1024 1025 1026 1027 1028
    case HEAP_NUMBER_TYPE:
    case MUTABLE_HEAP_NUMBER_TYPE:
    case FILLER_TYPE:
    case BYTE_ARRAY_TYPE:
    case FREE_SPACE_TYPE:
1029
    case BIGINT_TYPE:
1030 1031 1032
      return ReturnType();

    case SHARED_FUNCTION_INFO_TYPE: {
1033 1034
      return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3,
                                                                    p4);
1035
    }
1036 1037
    case ALLOCATION_SITE_TYPE:
      return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3, p4);
1038

1039
#define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE:
1040 1041
      STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
1042
      if (type == PROTOTYPE_INFO_TYPE) {
1043 1044
        return Op::template apply<PrototypeInfo::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
1045 1046 1047
      } else if (type == WASM_CAPI_FUNCTION_DATA_TYPE) {
        return Op::template apply<WasmCapiFunctionData::BodyDescriptor>(p1, p2,
                                                                        p3, p4);
1048 1049 1050
      } else if (type == WASM_INDIRECT_FUNCTION_TABLE_TYPE) {
        return Op::template apply<WasmIndirectFunctionTable::BodyDescriptor>(
            p1, p2, p3, p4);
1051
      } else {
1052
        return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
1053
      }
1054
    case CALL_HANDLER_INFO_TYPE:
1055
      return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
1056 1057
    case LOAD_HANDLER_TYPE:
    case STORE_HANDLER_TYPE:
1058
      return Op::template apply<DataHandler::BodyDescriptor>(p1, p2, p3, p4);
1059 1060 1061
    case SOURCE_TEXT_MODULE_TYPE:
      return Op::template apply<SourceTextModule::BodyDescriptor>(p1, p2, p3,
                                                                  p4);
1062 1063 1064
    case SYNTHETIC_MODULE_TYPE:
      return Op::template apply<SyntheticModule::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
1065 1066 1067 1068 1069 1070 1071 1072
    default:
      PrintF("Unknown type: %d\n", type);
      UNREACHABLE();
  }
}

template <typename ObjectVisitor>
void HeapObject::IterateFast(ObjectVisitor* v) {
1073
  BodyDescriptorBase::IteratePointer(*this, kMapOffset, v);
1074
  IterateBodyFast(v);
1075 1076 1077 1078
}

template <typename ObjectVisitor>
void HeapObject::IterateBodyFast(ObjectVisitor* v) {
1079
  Map m = map();
1080
  IterateBodyFast(m, SizeFromMap(m), v);
1081 1082 1083 1084
}

struct CallIterateBody {
  template <typename BodyDescriptor, typename ObjectVisitor>
1085
  static void apply(Map map, HeapObject obj, int object_size,
1086 1087
                    ObjectVisitor* v) {
    BodyDescriptor::IterateBody(map, obj, object_size, v);
1088 1089 1090 1091
  }
};

template <typename ObjectVisitor>
1092
void HeapObject::IterateBodyFast(Map map, int object_size, ObjectVisitor* v) {
1093
  BodyDescriptorApply<CallIterateBody, void>(map.instance_type(), map, *this,
1094
                                             object_size, v);
1095
}
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119

class EphemeronHashTable::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(Map map, HeapObject obj, int offset) {
    return (offset >= EphemeronHashTable::kHeaderSize);
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map map, HeapObject obj, int object_size,
                                 ObjectVisitor* v) {
    int entries_start = EphemeronHashTable::kHeaderSize +
                        EphemeronHashTable::kElementsStartIndex * kTaggedSize;
    IteratePointers(obj, EphemeronHashTable::kHeaderSize, entries_start, v);
    EphemeronHashTable table = EphemeronHashTable::unchecked_cast(obj);
    int entries = table.Capacity();
    for (int i = 0; i < entries; ++i) {
      const int key_index = EphemeronHashTable::EntryToIndex(i);
      const int value_index = EphemeronHashTable::EntryToValueIndex(i);
      IterateEphemeron(obj, i, OffsetOfElementAt(key_index),
                       OffsetOfElementAt(value_index), v);
    }
  }

  static inline int SizeOf(Map map, HeapObject object) {
1120
    return object.SizeFromMap(map);
1121 1122 1123
  }
};

1124 1125 1126
}  // namespace internal
}  // namespace v8

1127
#endif  // V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_INL_H_