objects-body-descriptors-inl.h 35.3 KB
Newer Older
1 2 3 4 5 6 7
// 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.

#ifndef V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
#define V8_OBJECTS_BODY_DESCRIPTORS_INL_H_

8
#include "src/assembler-inl.h"
9
#include "src/feedback-vector.h"
10
#include "src/objects-body-descriptors.h"
11
#include "src/objects/hash-table.h"
12
#include "src/objects/js-collection.h"
13
#include "src/objects/js-weak-refs.h"
14
#include "src/transitions.h"
15
#include "src/wasm/wasm-objects-inl.h"
16 17 18 19 20 21 22 23 24

namespace v8 {
namespace internal {

template <int start_offset>
int FlexibleBodyDescriptor<start_offset>::SizeOf(Map* map, HeapObject* object) {
  return object->SizeFromMap(map);
}

25 26 27
bool BodyDescriptorBase::IsValidSlotImpl(Map* map, HeapObject* obj,
                                         int offset) {
  if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) {
28 29 30 31 32
    return true;
  } else {
    DCHECK(FLAG_unbox_double_fields);
    DCHECK(IsAligned(offset, kPointerSize));

33
    LayoutDescriptorHelper helper(map);
34 35 36 37 38 39
    DCHECK(!helper.all_fields_tagged());
    return helper.IsTagged(offset);
  }
}

template <typename ObjectVisitor>
40 41 42 43
void BodyDescriptorBase::IterateBodyImpl(Map* map, HeapObject* obj,
                                         int start_offset, int end_offset,
                                         ObjectVisitor* v) {
  if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) {
44 45 46 47 48 49
    IteratePointers(obj, start_offset, end_offset, v);
  } else {
    DCHECK(FLAG_unbox_double_fields);
    DCHECK(IsAligned(start_offset, kPointerSize) &&
           IsAligned(end_offset, kPointerSize));

50
    LayoutDescriptorHelper helper(map);
51 52 53 54 55 56 57 58 59 60 61 62
    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>
63 64 65 66
DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(HeapObject* obj,
                                                          int start_offset,
                                                          int end_offset,
                                                          ObjectVisitor* v) {
67
  v->VisitPointers(obj, HeapObject::RawField(obj, start_offset),
68 69 70 71 72 73
                   HeapObject::RawField(obj, end_offset));
}

template <typename ObjectVisitor>
void BodyDescriptorBase::IteratePointer(HeapObject* obj, int offset,
                                        ObjectVisitor* v) {
74
  v->VisitPointer(obj, HeapObject::RawField(obj, offset));
75 76
}

77 78 79 80 81 82 83
template <typename ObjectVisitor>
DISABLE_CFI_PERF void BodyDescriptorBase::IterateMaybeWeakPointers(
    HeapObject* obj, int start_offset, int end_offset, ObjectVisitor* v) {
  v->VisitPointers(obj, HeapObject::RawMaybeWeakField(obj, start_offset),
                   HeapObject::RawMaybeWeakField(obj, end_offset));
}

84 85 86 87 88 89
template <typename ObjectVisitor>
void BodyDescriptorBase::IterateMaybeWeakPointer(HeapObject* obj, int offset,
                                                 ObjectVisitor* v) {
  v->VisitPointer(obj, HeapObject::RawMaybeWeakField(obj, offset));
}

90 91 92 93 94 95 96 97 98 99 100 101 102
template <typename ObjectVisitor>
DISABLE_CFI_PERF void BodyDescriptorBase::IterateCustomWeakPointers(
    HeapObject* obj, int start_offset, int end_offset, ObjectVisitor* v) {
  v->VisitCustomWeakPointers(obj, HeapObject::RawField(obj, start_offset),
                             HeapObject::RawField(obj, end_offset));
}

template <typename ObjectVisitor>
void BodyDescriptorBase::IterateCustomWeakPointer(HeapObject* obj, int offset,
                                                  ObjectVisitor* v) {
  v->VisitCustomWeakPointer(obj, HeapObject::RawField(obj, offset));
}

103 104
class JSObject::BodyDescriptor final : public BodyDescriptorBase {
 public:
105
  static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
106

107
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
108
    if (offset < kStartOffset) return false;
109
    return IsValidSlotImpl(map, obj, offset);
110 111 112
  }

  template <typename ObjectVisitor>
113
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
114
                                 ObjectVisitor* v) {
115
    IterateBodyImpl(map, obj, kStartOffset, object_size, v);
116 117 118 119 120 121
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return map->instance_size();
  }
};
122

123 124
class JSObject::FastBodyDescriptor final : public BodyDescriptorBase {
 public:
125
  static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
126

127
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
128 129 130 131
    return offset >= kStartOffset;
  }

  template <typename ObjectVisitor>
132
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
133 134 135 136 137 138 139 140 141
                                 ObjectVisitor* v) {
    IteratePointers(obj, kStartOffset, object_size, v);
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return map->instance_size();
  }
};

142
class JSFunction::BodyDescriptor final : public BodyDescriptorBase {
143
 public:
144
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
145
    if (offset < kSizeWithoutPrototype) return true;
146
    if (offset < kSizeWithPrototype && map->has_prototype_slot()) {
147 148
      return true;
    }
149
    return IsValidSlotImpl(map, obj, offset);
150 151 152
  }

  template <typename ObjectVisitor>
153
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
154
                                 ObjectVisitor* v) {
155 156
    int header_size = JSFunction::GetHeaderSize(map->has_prototype_slot());
    DCHECK_EQ(header_size, JSObject::GetHeaderSize(map));
157
    IteratePointers(obj, kPropertiesOrHashOffset, header_size, v);
158
    IterateBodyImpl(map, obj, header_size, object_size, v);
159 160 161
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
162
    return map->instance_size();
163 164 165
  }
};

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
class JSWeakCell::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return JSObject::BodyDescriptor::IsValidSlot(map, obj, offset);
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointers(obj, JSReceiver::kPropertiesOrHashOffset, kTargetOffset, v);
    IterateCustomWeakPointer(obj, kTargetOffset, v);
    IteratePointers(obj, kTargetOffset + kPointerSize, object_size, v);
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return map->instance_size();
  }
};

185
class AllocationSite::BodyDescriptor final : public BodyDescriptorBase {
186
 public:
187 188 189 190 191 192 193
  STATIC_ASSERT(AllocationSite::kCommonPointerFieldEndOffset ==
                AllocationSite::kPretenureDataOffset);
  STATIC_ASSERT(AllocationSite::kPretenureDataOffset + kInt32Size ==
                AllocationSite::kPretenureCreateCountOffset);
  STATIC_ASSERT(AllocationSite::kPretenureCreateCountOffset + kInt32Size ==
                AllocationSite::kWeakNextOffset);

194
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
195 196 197 198 199
    if (offset >= AllocationSite::kStartOffset &&
        offset < AllocationSite::kCommonPointerFieldEndOffset) {
      return true;
    }
    // check for weak_next offset
200
    if (map->instance_size() == AllocationSite::kSizeWithWeakNext &&
201 202 203 204
        offset == AllocationSite::kWeakNextOffset) {
      return true;
    }
    return false;
205 206 207 208 209
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
210 211 212
    // Iterate over all the common pointer fields
    IteratePointers(obj, AllocationSite::kStartOffset,
                    AllocationSite::kCommonPointerFieldEndOffset, v);
213 214 215 216 217 218
    // 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);
    }
219 220 221 222 223 224 225
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return map->instance_size();
  }
};

226 227 228
class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
 public:
  STATIC_ASSERT(kByteLengthOffset + kPointerSize == kBackingStoreOffset);
229
  STATIC_ASSERT(kBackingStoreOffset + kPointerSize == kBitFieldSlot);
230 231
  STATIC_ASSERT(kBitFieldSlot + kPointerSize == kSize);

232
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
233
    if (offset < kBitFieldSlot) return true;
234
    if (offset < kSize) return false;
235
    return IsValidSlotImpl(map, obj, offset);
236 237 238
  }

  template <typename ObjectVisitor>
239
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
240
                                 ObjectVisitor* v) {
241 242
    // JSArrayBuffer instances contain raw data that the GC does not know about.
    IteratePointers(obj, kPropertiesOrHashOffset, kByteLengthOffset, v);
243
    IterateBodyImpl(map, obj, kSize, object_size, v);
244 245 246
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
247
    return map->instance_size();
248 249 250
  }
};

251
class JSArrayBufferView::BodyDescriptor final : public BodyDescriptorBase {
252 253 254
 public:
  STATIC_ASSERT(kBufferOffset + kPointerSize == kByteOffsetOffset);
  STATIC_ASSERT(kByteOffsetOffset + kUIntptrSize == kByteLengthOffset);
255
  STATIC_ASSERT(kByteLengthOffset + kUIntptrSize == kHeaderSize);
256 257 258

  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    if (offset < kByteOffsetOffset) return true;
259
    if (offset < kHeaderSize) return false;
260 261 262 263 264 265
    return IsValidSlotImpl(map, obj, offset);
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
266
    // JSArrayBufferView contains raw data that the GC does not know about.
267
    IteratePointers(obj, kPropertiesOrHashOffset, kByteOffsetOffset, v);
268
    IterateBodyImpl(map, obj, kHeaderSize, object_size, v);
269 270 271 272 273 274 275
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return map->instance_size();
  }
};

276 277 278
template <typename Derived>
class SmallOrderedHashTable<Derived>::BodyDescriptor final
    : public BodyDescriptorBase {
279
 public:
280
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
281
    Derived* table = reinterpret_cast<Derived*>(obj);
282 283
    if (offset < kDataTableStartOffset) return false;
    if (offset >= table->GetBucketsStartOffset()) return false;
284
    return IsValidSlotImpl(map, obj, offset);
285 286 287
  }

  template <typename ObjectVisitor>
288
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
289
                                 ObjectVisitor* v) {
290
    Derived* table = reinterpret_cast<Derived*>(obj);
291

292
    int offset = kDataTableStartOffset;
293
    int entry = 0;
294
    for (int i = 0; i < table->Capacity(); i++) {
295 296 297 298
      for (int j = 0; j < Derived::kEntrySize; j++) {
        IteratePointer(obj, offset + (entry * kPointerSize), v);
        entry++;
      }
299 300 301 302
    }
  }

  static inline int SizeOf(Map* map, HeapObject* obj) {
303
    Derived* table = reinterpret_cast<Derived*>(obj);
304
    return table->SizeFor(table->Capacity());
305 306 307
  }
};

308 309
class ByteArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
310 311 312
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
313 314

  template <typename ObjectVisitor>
315
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
316 317 318
                                 ObjectVisitor* v) {}

  static inline int SizeOf(Map* map, HeapObject* obj) {
319
    return ByteArray::SizeFor(ByteArray::cast(obj)->synchronized_length());
320 321 322
  }
};

323 324
class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
325
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
326 327
    return offset >= kConstantPoolOffset &&
           offset <= kSourcePositionTableOffset;
328 329 330
  }

  template <typename ObjectVisitor>
331
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
332 333
                                 ObjectVisitor* v) {
    IteratePointer(obj, kConstantPoolOffset, v);
334
    IteratePointer(obj, kHandlerTableOffset, v);
335
    IteratePointer(obj, kSourcePositionTableOffset, v);
336 337
  }

338
  static inline int SizeOf(Map* map, HeapObject* obj) {
339 340
    return BytecodeArray::SizeFor(
        BytecodeArray::cast(obj)->synchronized_length());
341 342 343
  }
};

344 345
class BigInt::BodyDescriptor final : public BodyDescriptorBase {
 public:
346 347 348
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
349 350

  template <typename ObjectVisitor>
351
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
352 353 354 355 356 357 358
                                 ObjectVisitor* v) {}

  static inline int SizeOf(Map* map, HeapObject* obj) {
    return BigInt::SizeFor(BigInt::cast(obj)->length());
  }
};

359 360
class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
361 362 363
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
364 365

  template <typename ObjectVisitor>
366
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
367 368 369 370
                                 ObjectVisitor* v) {}

  static inline int SizeOf(Map* map, HeapObject* obj) {
    return FixedDoubleArray::SizeFor(
371
        FixedDoubleArray::cast(obj)->synchronized_length());
372 373 374
  }
};

375 376
class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
 public:
377
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
378 379 380 381
    return offset == kBasePointerOffset;
  }

  template <typename ObjectVisitor>
382
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
383 384 385 386 387
                                 ObjectVisitor* v) {
    IteratePointer(obj, kBasePointerOffset, v);
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
388
    return FixedTypedArrayBase::cast(object)->size();
389 390 391
  }
};

392
class WeakArrayBodyDescriptor final : public BodyDescriptorBase {
393
 public:
394
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
395
    return true;
396 397 398
  }

  template <typename ObjectVisitor>
399
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
400
                                 ObjectVisitor* v) {
401
    IterateMaybeWeakPointers(obj, HeapObject::kHeaderSize, object_size, v);
402 403 404 405 406 407 408
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return object->SizeFromMap(map);
  }
};

409 410
class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
 public:
411 412 413
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
414 415

  template <typename ObjectVisitor>
416
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
417 418 419 420 421 422 423 424
                                 ObjectVisitor* v) {}

  static inline int SizeOf(Map* map, HeapObject* obj) {
    return FeedbackMetadata::SizeFor(
        FeedbackMetadata::cast(obj)->synchronized_slot_count());
  }
};

425 426
class FeedbackVector::BodyDescriptor final : public BodyDescriptorBase {
 public:
427
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
428 429 430 431 432
    return offset == kSharedFunctionInfoOffset ||
           offset == kOptimizedCodeOffset || offset >= kFeedbackSlotsOffset;
  }

  template <typename ObjectVisitor>
433
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
434 435
                                 ObjectVisitor* v) {
    IteratePointer(obj, kSharedFunctionInfoOffset, v);
436
    IterateMaybeWeakPointer(obj, kOptimizedCodeOffset, v);
437
    IterateMaybeWeakPointers(obj, kFeedbackSlotsOffset, object_size, v);
438 439 440 441 442 443 444
  }

  static inline int SizeOf(Map* map, HeapObject* obj) {
    return FeedbackVector::SizeFor(FeedbackVector::cast(obj)->length());
  }
};

445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
class PreParsedScopeData::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return offset == kScopeDataOffset || offset >= kChildDataStartOffset;
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointer(obj, kScopeDataOffset, v);
    IteratePointers(obj, kChildDataStartOffset, object_size, v);
  }

  static inline int SizeOf(Map* map, HeapObject* obj) {
    return PreParsedScopeData::SizeFor(PreParsedScopeData::cast(obj)->length());
  }
};

463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return offset >= HeapObject::kHeaderSize;
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointers(obj, HeapObject::kHeaderSize, kObjectCreateMapOffset, v);
    IterateMaybeWeakPointer(obj, kObjectCreateMapOffset, v);
    IteratePointers(obj, kObjectCreateMapOffset + kPointerSize, object_size, v);
  }

  static inline int SizeOf(Map* map, HeapObject* obj) {
    return obj->SizeFromMap(map);
  }
};

482
class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
483
 public:
484
  STATIC_ASSERT(kTableOffset + kPointerSize == kSize);
485

486 487
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return IsValidSlotImpl(map, obj, offset);
488 489 490
  }

  template <typename ObjectVisitor>
491
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
492
                                 ObjectVisitor* v) {
493
    IterateBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v);
494 495
  }

496 497 498
  static inline int SizeOf(Map* map, HeapObject* object) {
    return map->instance_size();
  }
499 500 501 502
};

class Foreign::BodyDescriptor final : public BodyDescriptorBase {
 public:
503 504 505
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
506 507

  template <typename ObjectVisitor>
508
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
509
                                 ObjectVisitor* v) {
510 511 512
    v->VisitExternalReference(Foreign::cast(obj),
                              reinterpret_cast<Address*>(HeapObject::RawField(
                                  obj, kForeignAddressOffset)));
513 514 515 516 517 518 519
  }

  static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
};

class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
520 521 522
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
523 524

  template <typename ObjectVisitor>
525 526
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {}
527 528 529 530 531 532

  static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
};

class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
533 534 535
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
536 537

  template <typename ObjectVisitor>
538 539
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {}
540 541 542 543 544 545

  static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
};

class Code::BodyDescriptor final : public BodyDescriptorBase {
 public:
546
  STATIC_ASSERT(kRelocationInfoOffset + kPointerSize ==
547 548
                kDeoptimizationDataOffset);
  STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
549 550
                kSourcePositionTableOffset);
  STATIC_ASSERT(kSourcePositionTableOffset + kPointerSize ==
551
                kCodeDataContainerOffset);
552
  STATIC_ASSERT(kCodeDataContainerOffset + kPointerSize == kDataStart);
553

554
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
555 556 557 558 559
    // Slots in code can't be invalid because we never trim code objects.
    return true;
  }

  template <typename ObjectVisitor>
560
  static inline void IterateBody(Map* map, HeapObject* obj, ObjectVisitor* v) {
561 562 563 564 565 566 567 568
    int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
                    RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                    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);

569
    // GC does not visit data/code in the header and in the body directly.
570
    IteratePointers(obj, kRelocationInfoOffset, kDataStart, v);
571

572
    RelocIterator it(Code::cast(obj), mode_mask);
573
    v->VisitRelocInfo(&it);
574 575 576
  }

  template <typename ObjectVisitor>
577
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
578
                                 ObjectVisitor* v) {
579
    IterateBody(map, obj, v);
580 581 582 583 584 585 586
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return reinterpret_cast<Code*>(object)->CodeSize();
  }
};

587 588
class SeqOneByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
589 590 591
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
592 593

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

  static inline int SizeOf(Map* map, HeapObject* obj) {
    SeqOneByteString* string = SeqOneByteString::cast(obj);
599
    return string->SizeFor(string->synchronized_length());
600 601 602 603 604
  }
};

class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
605 606 607
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
608 609

  template <typename ObjectVisitor>
610
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
611 612 613 614
                                 ObjectVisitor* v) {}

  static inline int SizeOf(Map* map, HeapObject* obj) {
    SeqTwoByteString* string = SeqTwoByteString::cast(obj);
615
    return string->SizeFor(string->synchronized_length());
616 617
  }
};
618

619 620
class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
 public:
621
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
622
    if (offset < kMemoryStartOffset) return true;
623
    if (offset < kModuleObjectOffset) return false;
624
    return IsValidSlotImpl(map, obj, offset);
625 626 627
  }

  template <typename ObjectVisitor>
628
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
629 630
                                 ObjectVisitor* v) {
    IteratePointers(obj, kPropertiesOrHashOffset, kFirstUntaggedOffset, v);
631
    IterateBodyImpl(map, obj, kSize, object_size, v);
632 633 634 635 636 637 638
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return map->instance_size();
  }
};

639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
class Map::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return offset >= Map::kPointerFieldsBeginOffset &&
           offset < Map::kPointerFieldsEndOffset;
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointers(obj, Map::kPointerFieldsBeginOffset,
                    Map::kTransitionsOrPrototypeInfoOffset, v);
    IterateMaybeWeakPointer(obj, kTransitionsOrPrototypeInfoOffset, v);
    IteratePointers(obj, Map::kTransitionsOrPrototypeInfoOffset + kPointerSize,
                    Map::kPointerFieldsEndOffset, v);
  }

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

659 660 661 662 663 664 665 666 667 668 669 670 671 672
class DataHandler::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return offset >= HeapObject::kHeaderSize;
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 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);
673
    IterateMaybeWeakPointers(obj, kData1Offset, object_size, v);
674 675 676 677 678 679 680
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return object->SizeFromMap(map);
  }
};

681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
class Context::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return offset >= Context::kHeaderSize && offset < Context::kSize;
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointers(obj, Context::kHeaderSize,
                    Context::kHeaderSize + FIRST_WEAK_SLOT * kPointerSize, v);
    IterateCustomWeakPointers(
        obj, Context::kHeaderSize + FIRST_WEAK_SLOT * kPointerSize,
        Context::kSize, v);
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return Context::kSize;
  }
};

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

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointers(obj, CodeDataContainer::kHeaderSize,
                    CodeDataContainer::kPointerFieldsStrongEndOffset, v);
    IterateCustomWeakPointers(
        obj, CodeDataContainer::kPointerFieldsStrongEndOffset,
        CodeDataContainer::kPointerFieldsWeakEndOffset, v);
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
    return CodeDataContainer::kSize;
  }
};

724
template <typename Op, typename ReturnType, typename T1, typename T2,
725 726
          typename T3, typename T4>
ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
727 728 729 730 731
  if (type < FIRST_NONSTRING_TYPE) {
    switch (type & kStringRepresentationMask) {
      case kSeqStringTag:
        return ReturnType();
      case kConsStringTag:
732
        return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3, p4);
733
      case kThinStringTag:
734
        return Op::template apply<ThinString::BodyDescriptor>(p1, p2, p3, p4);
735
      case kSlicedStringTag:
736
        return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3, p4);
737 738 739
      case kExternalStringTag:
        if ((type & kStringEncodingMask) == kOneByteStringTag) {
          return Op::template apply<ExternalOneByteString::BodyDescriptor>(
740
              p1, p2, p3, p4);
741 742
        } else {
          return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
743
              p1, p2, p3, p4);
744 745 746 747 748 749 750
        }
    }
    UNREACHABLE();
  }

  switch (type) {
    case FIXED_ARRAY_TYPE:
751
    case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
752
    case HASH_TABLE_TYPE:
753 754 755 756 757 758 759
    case ORDERED_HASH_MAP_TYPE:
    case ORDERED_HASH_SET_TYPE:
    case NAME_DICTIONARY_TYPE:
    case GLOBAL_DICTIONARY_TYPE:
    case NUMBER_DICTIONARY_TYPE:
    case SIMPLE_NUMBER_DICTIONARY_TYPE:
    case STRING_TABLE_TYPE:
760
    case EPHEMERON_HASH_TABLE_TYPE:
761
    case SCOPE_INFO_TYPE:
762
    case SCRIPT_CONTEXT_TABLE_TYPE:
763
    case AWAIT_CONTEXT_TYPE:
764 765 766 767 768 769 770 771 772
    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 NATIVE_CONTEXT_TYPE:
    case SCRIPT_CONTEXT_TYPE:
    case WITH_CONTEXT_TYPE:
773
      return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3, p4);
774
    case WEAK_FIXED_ARRAY_TYPE:
775
      return Op::template apply<WeakFixedArray::BodyDescriptor>(p1, p2, p3, p4);
776 777
    case WEAK_ARRAY_LIST_TYPE:
      return Op::template apply<WeakArrayList::BodyDescriptor>(p1, p2, p3, p4);
778 779
    case FIXED_DOUBLE_ARRAY_TYPE:
      return ReturnType();
780
    case FEEDBACK_METADATA_TYPE:
781 782
      return Op::template apply<FeedbackMetadata::BodyDescriptor>(p1, p2, p3,
                                                                  p4);
783
    case PROPERTY_ARRAY_TYPE:
784
      return Op::template apply<PropertyArray::BodyDescriptor>(p1, p2, p3, p4);
785
    case DESCRIPTOR_ARRAY_TYPE:
786 787
      return Op::template apply<DescriptorArray::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
788
    case TRANSITION_ARRAY_TYPE:
789 790
      return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
791
    case FEEDBACK_CELL_TYPE:
792
      return Op::template apply<FeedbackCell::BodyDescriptor>(p1, p2, p3, p4);
793
    case FEEDBACK_VECTOR_TYPE:
794
      return Op::template apply<FeedbackVector::BodyDescriptor>(p1, p2, p3, p4);
795
    case JS_OBJECT_TYPE:
796 797
    case JS_ERROR_TYPE:
    case JS_ARGUMENTS_TYPE:
798
    case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
799
    case JS_PROMISE_TYPE:
800 801
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    case JS_GENERATOR_OBJECT_TYPE:
802
    case JS_ASYNC_FUNCTION_OBJECT_TYPE:
803
    case JS_ASYNC_GENERATOR_OBJECT_TYPE:
804 805 806
    case JS_VALUE_TYPE:
    case JS_DATE_TYPE:
    case JS_ARRAY_TYPE:
807
    case JS_ARRAY_ITERATOR_TYPE:
808
    case JS_MODULE_NAMESPACE_TYPE:
809 810
    case JS_SET_TYPE:
    case JS_MAP_TYPE:
811 812 813 814 815
    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:
816
    case JS_STRING_ITERATOR_TYPE:
817
    case JS_REGEXP_STRING_ITERATOR_TYPE:
818 819 820
    case JS_REGEXP_TYPE:
    case JS_GLOBAL_PROXY_TYPE:
    case JS_GLOBAL_OBJECT_TYPE:
821
    case JS_API_OBJECT_TYPE:
822
    case JS_SPECIAL_API_OBJECT_TYPE:
823
    case JS_MESSAGE_OBJECT_TYPE:
824
    case JS_BOUND_FUNCTION_TYPE:
825 826
    case JS_WEAK_FACTORY_CLEANUP_ITERATOR_TYPE:
    case JS_WEAK_FACTORY_TYPE:
827
#ifdef V8_INTL_SUPPORT
828
    case JS_INTL_V8_BREAK_ITERATOR_TYPE:
829
    case JS_INTL_COLLATOR_TYPE:
830
    case JS_INTL_DATE_TIME_FORMAT_TYPE:
831
    case JS_INTL_LIST_FORMAT_TYPE:
832
    case JS_INTL_LOCALE_TYPE:
833
    case JS_INTL_NUMBER_FORMAT_TYPE:
834
    case JS_INTL_PLURAL_RULES_TYPE:
835
    case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
836
    case JS_INTL_SEGMENT_ITERATOR_TYPE:
837
    case JS_INTL_SEGMENTER_TYPE:
838
#endif  // V8_INTL_SUPPORT
839
    case WASM_EXCEPTION_TYPE:
840
    case WASM_GLOBAL_TYPE:
841 842 843
    case WASM_MEMORY_TYPE:
    case WASM_MODULE_TYPE:
    case WASM_TABLE_TYPE:
844
      return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3, p4);
845
    case WASM_INSTANCE_TYPE:
846 847
      return Op::template apply<WasmInstanceObject::BodyDescriptor>(p1, p2, p3,
                                                                    p4);
848 849
    case JS_WEAK_MAP_TYPE:
    case JS_WEAK_SET_TYPE:
850 851
      return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3,
                                                                  p4);
852
    case JS_ARRAY_BUFFER_TYPE:
853
      return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3, p4);
854 855 856 857
    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);
858
    case JS_FUNCTION_TYPE:
859
      return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3, p4);
860 861
    case JS_WEAK_CELL_TYPE:
      return Op::template apply<JSWeakCell::BodyDescriptor>(p1, p2, p3, p4);
862
    case ODDBALL_TYPE:
863
      return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3, p4);
864
    case JS_PROXY_TYPE:
865
      return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3, p4);
866
    case FOREIGN_TYPE:
867
      return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3, p4);
868
    case MAP_TYPE:
869
      return Op::template apply<Map::BodyDescriptor>(p1, p2, p3, p4);
870
    case CODE_TYPE:
871
      return Op::template apply<Code::BodyDescriptor>(p1, p2, p3, p4);
872
    case CELL_TYPE:
873
      return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3, p4);
874
    case PROPERTY_CELL_TYPE:
875
      return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3, p4);
876
    case SYMBOL_TYPE:
877
      return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3, p4);
878
    case BYTECODE_ARRAY_TYPE:
879
      return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3, p4);
880
    case SMALL_ORDERED_HASH_SET_TYPE:
881 882
      return Op::template apply<
          SmallOrderedHashTable<SmallOrderedHashSet>::BodyDescriptor>(p1, p2,
883
                                                                      p3, p4);
884 885 886
    case SMALL_ORDERED_HASH_MAP_TYPE:
      return Op::template apply<
          SmallOrderedHashTable<SmallOrderedHashMap>::BodyDescriptor>(p1, p2,
887
                                                                      p3, p4);
888
    case CODE_DATA_CONTAINER_TYPE:
889 890
      return Op::template apply<CodeDataContainer::BodyDescriptor>(p1, p2, p3,
                                                                   p4);
891 892 893
    case PRE_PARSED_SCOPE_DATA_TYPE:
      return Op::template apply<PreParsedScopeData::BodyDescriptor>(p1, p2, p3,
                                                                    p4);
894 895 896
    case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE:
      return Op::template apply<
          UncompiledDataWithoutPreParsedScope::BodyDescriptor>(p1, p2, p3, p4);
897 898 899
    case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE:
      return Op::template apply<
          UncompiledDataWithPreParsedScope::BodyDescriptor>(p1, p2, p3, p4);
900 901 902 903 904
    case HEAP_NUMBER_TYPE:
    case MUTABLE_HEAP_NUMBER_TYPE:
    case FILLER_TYPE:
    case BYTE_ARRAY_TYPE:
    case FREE_SPACE_TYPE:
905
    case BIGINT_TYPE:
906 907
      return ReturnType();

908
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)                              \
909 910 911
  case FIXED_##TYPE##_ARRAY_TYPE:                                              \
    return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3, \
                                                                   p4);
912 913 914 915
      TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

    case SHARED_FUNCTION_INFO_TYPE: {
916 917
      return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3,
                                                                    p4);
918
    }
919 920
    case ALLOCATION_SITE_TYPE:
      return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3, p4);
921

922
#define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE:
923 924
      STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
925
      if (type == PROTOTYPE_INFO_TYPE) {
926 927
        return Op::template apply<PrototypeInfo::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
928
      } else {
929
        return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
930
      }
931
    case CALL_HANDLER_INFO_TYPE:
932
      return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
933 934
    case LOAD_HANDLER_TYPE:
    case STORE_HANDLER_TYPE:
935
      return Op::template apply<DataHandler::BodyDescriptor>(p1, p2, p3, p4);
936 937 938 939 940 941 942 943 944 945
    default:
      PrintF("Unknown type: %d\n", type);
      UNREACHABLE();
  }
}


template <typename ObjectVisitor>
void HeapObject::IterateFast(ObjectVisitor* v) {
  BodyDescriptorBase::IteratePointer(this, kMapOffset, v);
946
  IterateBodyFast(v);
947 948 949 950 951 952
}


template <typename ObjectVisitor>
void HeapObject::IterateBodyFast(ObjectVisitor* v) {
  Map* m = map();
953
  IterateBodyFast(m, SizeFromMap(m), v);
954 955 956 957 958
}


struct CallIterateBody {
  template <typename BodyDescriptor, typename ObjectVisitor>
959 960 961
  static void apply(Map* map, HeapObject* obj, int object_size,
                    ObjectVisitor* v) {
    BodyDescriptor::IterateBody(map, obj, object_size, v);
962 963 964 965
  }
};

template <typename ObjectVisitor>
966 967 968
void HeapObject::IterateBodyFast(Map* map, int object_size, ObjectVisitor* v) {
  BodyDescriptorApply<CallIterateBody, void>(map->instance_type(), map, this,
                                             object_size, v);
969 970 971 972 973
}
}  // namespace internal
}  // namespace v8

#endif  // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_