LCOV - code coverage report
Current view: top level - src - objects-body-descriptors-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 159 262 60.7 %
Date: 2019-04-17 Functions: 129 235 54.9 %

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

Generated by: LCOV version 1.10