objects-body-descriptors-inl.h 31.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/transitions.h"
14
#include "src/wasm/wasm-objects-inl.h"
15 16 17 18 19 20 21 22 23

namespace v8 {
namespace internal {

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

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

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

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

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

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

76 77 78 79 80 81 82
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));
}

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

89 90
class JSObject::BodyDescriptor final : public BodyDescriptorBase {
 public:
91
  static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
92

93
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
94
    if (offset < kStartOffset) return false;
95
    return IsValidSlotImpl(map, obj, offset);
96 97 98
  }

  template <typename ObjectVisitor>
99
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
100
                                 ObjectVisitor* v) {
101
    IterateBodyImpl(map, obj, kStartOffset, object_size, v);
102 103 104 105 106 107
  }

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

109 110
class JSObject::FastBodyDescriptor final : public BodyDescriptorBase {
 public:
111
  static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
112

113
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
114 115 116 117
    return offset >= kStartOffset;
  }

  template <typename ObjectVisitor>
118
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
119 120 121 122 123 124 125 126 127
                                 ObjectVisitor* v) {
    IteratePointers(obj, kStartOffset, object_size, v);
  }

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

128
class JSFunction::BodyDescriptor final : public BodyDescriptorBase {
129
 public:
130
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
131
    if (offset < kSizeWithoutPrototype) return true;
132
    if (offset < kSizeWithPrototype && map->has_prototype_slot()) {
133 134
      return true;
    }
135
    return IsValidSlotImpl(map, obj, offset);
136 137 138
  }

  template <typename ObjectVisitor>
139
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
140
                                 ObjectVisitor* v) {
141 142
    int header_size = JSFunction::GetHeaderSize(map->has_prototype_slot());
    DCHECK_EQ(header_size, JSObject::GetHeaderSize(map));
143
    IteratePointers(obj, kPropertiesOrHashOffset, header_size, v);
144
    IterateBodyImpl(map, obj, header_size, object_size, v);
145 146 147
  }

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

152 153 154
template <bool includeWeakNext>
class AllocationSite::BodyDescriptorImpl final : public BodyDescriptorBase {
 public:
155 156 157 158 159 160 161
  STATIC_ASSERT(AllocationSite::kCommonPointerFieldEndOffset ==
                AllocationSite::kPretenureDataOffset);
  STATIC_ASSERT(AllocationSite::kPretenureDataOffset + kInt32Size ==
                AllocationSite::kPretenureCreateCountOffset);
  STATIC_ASSERT(AllocationSite::kPretenureCreateCountOffset + kInt32Size ==
                AllocationSite::kWeakNextOffset);

162
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
163 164 165 166 167 168 169 170 171 172 173
    if (offset >= AllocationSite::kStartOffset &&
        offset < AllocationSite::kCommonPointerFieldEndOffset) {
      return true;
    }
    // check for weak_next offset
    if (includeWeakNext &&
        map->instance_size() == AllocationSite::kSizeWithWeakNext &&
        offset == AllocationSite::kWeakNextOffset) {
      return true;
    }
    return false;
174 175 176 177 178
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
179 180 181 182 183 184 185 186 187
    // Iterate over all the common pointer fields
    IteratePointers(obj, AllocationSite::kStartOffset,
                    AllocationSite::kCommonPointerFieldEndOffset, v);
    // Skip PretenureDataOffset and PretenureCreateCount which are Int32 fields
    // Visit weak_next only for full body descriptor and if it has weak_next
    // field
    if (includeWeakNext && object_size == AllocationSite::kSizeWithWeakNext)
      IteratePointers(obj, AllocationSite::kWeakNextOffset,
                      AllocationSite::kSizeWithWeakNext, v);
188 189 190 191 192 193 194
  }

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

195 196 197
class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
 public:
  STATIC_ASSERT(kByteLengthOffset + kPointerSize == kBackingStoreOffset);
198
  STATIC_ASSERT(kBackingStoreOffset + kPointerSize == kBitFieldSlot);
199 200
  STATIC_ASSERT(kBitFieldSlot + kPointerSize == kSize);

201
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
202
    if (offset < kBitFieldSlot) return true;
203
    if (offset < kSize) return false;
204
    return IsValidSlotImpl(map, obj, offset);
205 206 207
  }

  template <typename ObjectVisitor>
208
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
209
                                 ObjectVisitor* v) {
210 211 212
    // Array buffers contain raw pointers that the GC does not know about. These
    // are stored at kBackStoreOffset and later, so we do not iterate over
    // those.
213
    IteratePointers(obj, kPropertiesOrHashOffset, kBackingStoreOffset, v);
214
    IterateBodyImpl(map, obj, kSize, object_size, v);
215 216 217
  }

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

222 223 224
template <typename Derived>
class SmallOrderedHashTable<Derived>::BodyDescriptor final
    : public BodyDescriptorBase {
225
 public:
226
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
227
    Derived* table = reinterpret_cast<Derived*>(obj);
228 229
    if (offset < kDataTableStartOffset) return false;
    if (offset >= table->GetBucketsStartOffset()) return false;
230
    return IsValidSlotImpl(map, obj, offset);
231 232 233
  }

  template <typename ObjectVisitor>
234
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
235
                                 ObjectVisitor* v) {
236
    Derived* table = reinterpret_cast<Derived*>(obj);
237

238
    int offset = kDataTableStartOffset;
239
    int entry = 0;
240
    for (int i = 0; i < table->Capacity(); i++) {
241 242 243 244
      for (int j = 0; j < Derived::kEntrySize; j++) {
        IteratePointer(obj, offset + (entry * kPointerSize), v);
        entry++;
      }
245 246 247 248
    }
  }

  static inline int SizeOf(Map* map, HeapObject* obj) {
249
    Derived* table = reinterpret_cast<Derived*>(obj);
250
    return table->SizeFor(table->Capacity());
251 252 253
  }
};

254 255
class ByteArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
256 257 258
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
259 260

  template <typename ObjectVisitor>
261
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
262 263 264
                                 ObjectVisitor* v) {}

  static inline int SizeOf(Map* map, HeapObject* obj) {
265
    return ByteArray::SizeFor(ByteArray::cast(obj)->synchronized_length());
266 267 268
  }
};

269 270
class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
271
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
272 273
    return offset >= kConstantPoolOffset &&
           offset <= kSourcePositionTableOffset;
274 275 276
  }

  template <typename ObjectVisitor>
277
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
278 279
                                 ObjectVisitor* v) {
    IteratePointer(obj, kConstantPoolOffset, v);
280
    IteratePointer(obj, kHandlerTableOffset, v);
281
    IteratePointer(obj, kSourcePositionTableOffset, v);
282 283
  }

284
  static inline int SizeOf(Map* map, HeapObject* obj) {
285 286
    return BytecodeArray::SizeFor(
        BytecodeArray::cast(obj)->synchronized_length());
287 288 289
  }
};

290 291
class BigInt::BodyDescriptor final : public BodyDescriptorBase {
 public:
292 293 294
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
295 296

  template <typename ObjectVisitor>
297
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
298 299 300 301 302 303 304
                                 ObjectVisitor* v) {}

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

305 306
class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
307 308 309
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
310 311

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

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

321 322
class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
 public:
323
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
324 325 326 327
    return offset == kBasePointerOffset;
  }

  template <typename ObjectVisitor>
328
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
329 330 331 332 333
                                 ObjectVisitor* v) {
    IteratePointer(obj, kBasePointerOffset, v);
  }

  static inline int SizeOf(Map* map, HeapObject* object) {
334
    return FixedTypedArrayBase::cast(object)->size();
335 336 337
  }
};

338
class WeakArrayBodyDescriptor final : public BodyDescriptorBase {
339
 public:
340
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
341
    return true;
342 343 344
  }

  template <typename ObjectVisitor>
345
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
346
                                 ObjectVisitor* v) {
347
    IterateMaybeWeakPointers(obj, HeapObject::kHeaderSize, object_size, v);
348 349 350 351 352 353 354
  }

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

355 356
class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
 public:
357 358 359
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
360 361

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

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

371 372
class FeedbackVector::BodyDescriptor final : public BodyDescriptorBase {
 public:
373
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
374 375 376 377 378
    return offset == kSharedFunctionInfoOffset ||
           offset == kOptimizedCodeOffset || offset >= kFeedbackSlotsOffset;
  }

  template <typename ObjectVisitor>
379
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
380 381
                                 ObjectVisitor* v) {
    IteratePointer(obj, kSharedFunctionInfoOffset, v);
382
    IterateMaybeWeakPointer(obj, kOptimizedCodeOffset, v);
383
    IterateMaybeWeakPointers(obj, kFeedbackSlotsOffset, object_size, v);
384 385 386 387 388 389 390
  }

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

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
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());
  }
};

409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
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);
  }
};

428
class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
429
 public:
430
  STATIC_ASSERT(kTableOffset + kPointerSize == kSize);
431

432 433
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return IsValidSlotImpl(map, obj, offset);
434 435 436
  }

  template <typename ObjectVisitor>
437
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
438
                                 ObjectVisitor* v) {
439
    IterateBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v);
440 441
  }

442 443 444
  static inline int SizeOf(Map* map, HeapObject* object) {
    return map->instance_size();
  }
445 446 447 448
};

class Foreign::BodyDescriptor final : public BodyDescriptorBase {
 public:
449 450 451
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
452 453

  template <typename ObjectVisitor>
454
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
455
                                 ObjectVisitor* v) {
456 457 458
    v->VisitExternalReference(Foreign::cast(obj),
                              reinterpret_cast<Address*>(HeapObject::RawField(
                                  obj, kForeignAddressOffset)));
459 460 461 462 463 464 465
  }

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

class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
466 467 468
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
469 470

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

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

class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
479 480 481
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
482 483

  template <typename ObjectVisitor>
484 485
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {}
486 487 488 489 490 491

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

class Code::BodyDescriptor final : public BodyDescriptorBase {
 public:
492
  STATIC_ASSERT(kRelocationInfoOffset + kPointerSize ==
493 494
                kDeoptimizationDataOffset);
  STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
495 496
                kSourcePositionTableOffset);
  STATIC_ASSERT(kSourcePositionTableOffset + kPointerSize ==
497
                kCodeDataContainerOffset);
498
  STATIC_ASSERT(kCodeDataContainerOffset + kPointerSize == kDataStart);
499

500
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
501 502 503 504 505
    // Slots in code can't be invalid because we never trim code objects.
    return true;
  }

  template <typename ObjectVisitor>
506
  static inline void IterateBody(Map* map, HeapObject* obj, ObjectVisitor* v) {
507 508 509 510 511 512 513 514
    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);

515
    // GC does not visit data/code in the header and in the body directly.
516
    IteratePointers(obj, kRelocationInfoOffset, kDataStart, v);
517

518
    RelocIterator it(Code::cast(obj), mode_mask);
519
    v->VisitRelocInfo(&it);
520 521 522
  }

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

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

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

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

  static inline int SizeOf(Map* map, HeapObject* obj) {
    SeqOneByteString* string = SeqOneByteString::cast(obj);
545
    return string->SizeFor(string->synchronized_length());
546 547 548 549 550
  }
};

class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
551 552 553
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
    return false;
  }
554 555

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

  static inline int SizeOf(Map* map, HeapObject* obj) {
    SeqTwoByteString* string = SeqTwoByteString::cast(obj);
561
    return string->SizeFor(string->synchronized_length());
562 563
  }
};
564

565 566
class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
 public:
567
  static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
568
    if (offset < kMemoryStartOffset) return true;
569
    if (offset < kModuleObjectOffset) return false;
570
    return IsValidSlotImpl(map, obj, offset);
571 572 573
  }

  template <typename ObjectVisitor>
574
  static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
575 576
                                 ObjectVisitor* v) {
    IteratePointers(obj, kPropertiesOrHashOffset, kFirstUntaggedOffset, v);
577
    IterateBodyImpl(map, obj, kSize, object_size, v);
578 579 580 581 582 583 584
  }

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

585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
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; }
};

605 606 607 608 609 610 611 612 613 614 615 616 617 618
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);
619
    IterateMaybeWeakPointers(obj, kData1Offset, object_size, v);
620 621 622 623 624 625 626
  }

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

627
template <typename Op, typename ReturnType, typename T1, typename T2,
628 629
          typename T3, typename T4>
ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
630 631 632 633 634
  if (type < FIRST_NONSTRING_TYPE) {
    switch (type & kStringRepresentationMask) {
      case kSeqStringTag:
        return ReturnType();
      case kConsStringTag:
635
        return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3, p4);
636
      case kThinStringTag:
637
        return Op::template apply<ThinString::BodyDescriptor>(p1, p2, p3, p4);
638
      case kSlicedStringTag:
639
        return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3, p4);
640 641 642
      case kExternalStringTag:
        if ((type & kStringEncodingMask) == kOneByteStringTag) {
          return Op::template apply<ExternalOneByteString::BodyDescriptor>(
643
              p1, p2, p3, p4);
644 645
        } else {
          return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
646
              p1, p2, p3, p4);
647 648 649 650 651 652 653
        }
    }
    UNREACHABLE();
  }

  switch (type) {
    case FIXED_ARRAY_TYPE:
654
    case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
655
    case HASH_TABLE_TYPE:
656 657 658 659 660 661 662
    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:
663
    case EPHEMERON_HASH_TABLE_TYPE:
664
    case SCOPE_INFO_TYPE:
665
    case SCRIPT_CONTEXT_TABLE_TYPE:
666 667 668 669 670 671 672 673 674
    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:
675
      return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3, p4);
676
    case WEAK_FIXED_ARRAY_TYPE:
677
      return Op::template apply<WeakFixedArray::BodyDescriptor>(p1, p2, p3, p4);
678 679
    case WEAK_ARRAY_LIST_TYPE:
      return Op::template apply<WeakArrayList::BodyDescriptor>(p1, p2, p3, p4);
680 681
    case FIXED_DOUBLE_ARRAY_TYPE:
      return ReturnType();
682
    case FEEDBACK_METADATA_TYPE:
683 684
      return Op::template apply<FeedbackMetadata::BodyDescriptor>(p1, p2, p3,
                                                                  p4);
685
    case PROPERTY_ARRAY_TYPE:
686
      return Op::template apply<PropertyArray::BodyDescriptor>(p1, p2, p3, p4);
687
    case DESCRIPTOR_ARRAY_TYPE:
688 689
      return Op::template apply<DescriptorArray::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
690
    case TRANSITION_ARRAY_TYPE:
691 692
      return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
693
    case FEEDBACK_CELL_TYPE:
694
      return Op::template apply<FeedbackCell::BodyDescriptor>(p1, p2, p3, p4);
695
    case FEEDBACK_VECTOR_TYPE:
696
      return Op::template apply<FeedbackVector::BodyDescriptor>(p1, p2, p3, p4);
697
    case JS_OBJECT_TYPE:
698 699
    case JS_ERROR_TYPE:
    case JS_ARGUMENTS_TYPE:
700
    case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
701
    case JS_PROMISE_TYPE:
702 703
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    case JS_GENERATOR_OBJECT_TYPE:
704
    case JS_ASYNC_GENERATOR_OBJECT_TYPE:
705 706 707
    case JS_VALUE_TYPE:
    case JS_DATE_TYPE:
    case JS_ARRAY_TYPE:
708
    case JS_ARRAY_ITERATOR_TYPE:
709
    case JS_MODULE_NAMESPACE_TYPE:
710 711 712 713
    case JS_TYPED_ARRAY_TYPE:
    case JS_DATA_VIEW_TYPE:
    case JS_SET_TYPE:
    case JS_MAP_TYPE:
714 715 716 717 718
    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:
719
    case JS_STRING_ITERATOR_TYPE:
720
    case JS_REGEXP_STRING_ITERATOR_TYPE:
721 722 723
    case JS_REGEXP_TYPE:
    case JS_GLOBAL_PROXY_TYPE:
    case JS_GLOBAL_OBJECT_TYPE:
724
    case JS_API_OBJECT_TYPE:
725
    case JS_SPECIAL_API_OBJECT_TYPE:
726
    case JS_MESSAGE_OBJECT_TYPE:
727
    case JS_BOUND_FUNCTION_TYPE:
728
#ifdef V8_INTL_SUPPORT
729
    case JS_INTL_V8_BREAK_ITERATOR_TYPE:
730
    case JS_INTL_COLLATOR_TYPE:
731
    case JS_INTL_DATE_TIME_FORMAT_TYPE:
732
    case JS_INTL_LIST_FORMAT_TYPE:
733
    case JS_INTL_LOCALE_TYPE:
734
    case JS_INTL_NUMBER_FORMAT_TYPE:
735
    case JS_INTL_PLURAL_RULES_TYPE:
736
    case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
737
#endif  // V8_INTL_SUPPORT
738
    case WASM_GLOBAL_TYPE:
739 740 741
    case WASM_MEMORY_TYPE:
    case WASM_MODULE_TYPE:
    case WASM_TABLE_TYPE:
742
      return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3, p4);
743
    case WASM_INSTANCE_TYPE:
744 745
      return Op::template apply<WasmInstanceObject::BodyDescriptor>(p1, p2, p3,
                                                                    p4);
746 747
    case JS_WEAK_MAP_TYPE:
    case JS_WEAK_SET_TYPE:
748 749
      return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3,
                                                                  p4);
750
    case JS_ARRAY_BUFFER_TYPE:
751
      return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3, p4);
752
    case JS_FUNCTION_TYPE:
753
      return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3, p4);
754
    case ODDBALL_TYPE:
755
      return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3, p4);
756
    case JS_PROXY_TYPE:
757
      return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3, p4);
758
    case FOREIGN_TYPE:
759
      return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3, p4);
760
    case MAP_TYPE:
761
      return Op::template apply<Map::BodyDescriptor>(p1, p2, p3, p4);
762
    case CODE_TYPE:
763
      return Op::template apply<Code::BodyDescriptor>(p1, p2, p3, p4);
764
    case CELL_TYPE:
765
      return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3, p4);
766
    case PROPERTY_CELL_TYPE:
767
      return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3, p4);
768
    case SYMBOL_TYPE:
769
      return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3, p4);
770
    case BYTECODE_ARRAY_TYPE:
771
      return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3, p4);
772
    case SMALL_ORDERED_HASH_SET_TYPE:
773 774
      return Op::template apply<
          SmallOrderedHashTable<SmallOrderedHashSet>::BodyDescriptor>(p1, p2,
775
                                                                      p3, p4);
776 777 778
    case SMALL_ORDERED_HASH_MAP_TYPE:
      return Op::template apply<
          SmallOrderedHashTable<SmallOrderedHashMap>::BodyDescriptor>(p1, p2,
779
                                                                      p3, p4);
780
    case CODE_DATA_CONTAINER_TYPE:
781 782
      return Op::template apply<CodeDataContainer::BodyDescriptor>(p1, p2, p3,
                                                                   p4);
783 784 785
    case PRE_PARSED_SCOPE_DATA_TYPE:
      return Op::template apply<PreParsedScopeData::BodyDescriptor>(p1, p2, p3,
                                                                    p4);
786 787 788
    case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE:
      return Op::template apply<
          UncompiledDataWithoutPreParsedScope::BodyDescriptor>(p1, p2, p3, p4);
789 790 791
    case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE:
      return Op::template apply<
          UncompiledDataWithPreParsedScope::BodyDescriptor>(p1, p2, p3, p4);
792 793 794 795 796
    case HEAP_NUMBER_TYPE:
    case MUTABLE_HEAP_NUMBER_TYPE:
    case FILLER_TYPE:
    case BYTE_ARRAY_TYPE:
    case FREE_SPACE_TYPE:
797
    case BIGINT_TYPE:
798 799
      return ReturnType();

800
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)                              \
801 802 803
  case FIXED_##TYPE##_ARRAY_TYPE:                                              \
    return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3, \
                                                                   p4);
804 805 806 807
      TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

    case SHARED_FUNCTION_INFO_TYPE: {
808 809
      return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3,
                                                                    p4);
810
    }
811 812
    case ALLOCATION_SITE_TYPE:
      return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3, p4);
813 814 815 816

#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
      STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
817
      if (type == PROTOTYPE_INFO_TYPE) {
818 819
        return Op::template apply<PrototypeInfo::BodyDescriptor>(p1, p2, p3,
                                                                 p4);
820
      } else {
821
        return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
822
      }
823
    case CALL_HANDLER_INFO_TYPE:
824
      return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
825 826
    case LOAD_HANDLER_TYPE:
    case STORE_HANDLER_TYPE:
827
      return Op::template apply<DataHandler::BodyDescriptor>(p1, p2, p3, p4);
828 829 830 831 832 833 834 835 836 837
    default:
      PrintF("Unknown type: %d\n", type);
      UNREACHABLE();
  }
}


template <typename ObjectVisitor>
void HeapObject::IterateFast(ObjectVisitor* v) {
  BodyDescriptorBase::IteratePointer(this, kMapOffset, v);
838
  IterateBodyFast(v);
839 840 841 842 843 844
}


template <typename ObjectVisitor>
void HeapObject::IterateBodyFast(ObjectVisitor* v) {
  Map* m = map();
845
  IterateBodyFast(m, SizeFromMap(m), v);
846 847 848 849 850
}


struct CallIterateBody {
  template <typename BodyDescriptor, typename ObjectVisitor>
851 852 853
  static void apply(Map* map, HeapObject* obj, int object_size,
                    ObjectVisitor* v) {
    BodyDescriptor::IterateBody(map, obj, object_size, v);
854 855 856 857
  }
};

template <typename ObjectVisitor>
858 859 860
void HeapObject::IterateBodyFast(Map* map, int object_size, ObjectVisitor* v) {
  BodyDescriptorApply<CallIterateBody, void>(map->instance_type(), map, this,
                                             object_size, v);
861 862 863 864 865
}
}  // namespace internal
}  // namespace v8

#endif  // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_