Home | History | Annotate | Download | only in src
      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/assembler-inl.h"
      9 #include "src/objects-body-descriptors.h"
     10 #include "src/transitions.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 template <int start_offset>
     16 int FlexibleBodyDescriptor<start_offset>::SizeOf(Map* map, HeapObject* object) {
     17   return object->SizeFromMap(map);
     18 }
     19 
     20 
     21 bool BodyDescriptorBase::IsValidSlotImpl(HeapObject* obj, int offset) {
     22   if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
     23     return true;
     24   } else {
     25     DCHECK(FLAG_unbox_double_fields);
     26     DCHECK(IsAligned(offset, kPointerSize));
     27 
     28     LayoutDescriptorHelper helper(obj->map());
     29     DCHECK(!helper.all_fields_tagged());
     30     return helper.IsTagged(offset);
     31   }
     32 }
     33 
     34 template <typename ObjectVisitor>
     35 void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
     36                                          int end_offset, ObjectVisitor* v) {
     37   if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
     38     IteratePointers(obj, start_offset, end_offset, v);
     39   } else {
     40     DCHECK(FLAG_unbox_double_fields);
     41     DCHECK(IsAligned(start_offset, kPointerSize) &&
     42            IsAligned(end_offset, kPointerSize));
     43 
     44     LayoutDescriptorHelper helper(obj->map());
     45     DCHECK(!helper.all_fields_tagged());
     46     for (int offset = start_offset; offset < end_offset;) {
     47       int end_of_region_offset;
     48       if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
     49         IteratePointers(obj, offset, end_of_region_offset, v);
     50       }
     51       offset = end_of_region_offset;
     52     }
     53   }
     54 }
     55 
     56 
     57 template <typename StaticVisitor>
     58 void BodyDescriptorBase::IterateBodyImpl(Heap* heap, HeapObject* obj,
     59                                          int start_offset, int end_offset) {
     60   if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
     61     IteratePointers<StaticVisitor>(heap, obj, start_offset, end_offset);
     62   } else {
     63     DCHECK(FLAG_unbox_double_fields);
     64     DCHECK(IsAligned(start_offset, kPointerSize) &&
     65            IsAligned(end_offset, kPointerSize));
     66 
     67     LayoutDescriptorHelper helper(obj->map());
     68     DCHECK(!helper.all_fields_tagged());
     69     for (int offset = start_offset; offset < end_offset;) {
     70       int end_of_region_offset;
     71       if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
     72         IteratePointers<StaticVisitor>(heap, obj, offset, end_of_region_offset);
     73       }
     74       offset = end_of_region_offset;
     75     }
     76   }
     77 }
     78 
     79 
     80 template <typename ObjectVisitor>
     81 DISABLE_CFI_PERF
     82 void BodyDescriptorBase::IteratePointers(HeapObject* obj, int start_offset,
     83                                          int end_offset, ObjectVisitor* v) {
     84   v->VisitPointers(HeapObject::RawField(obj, start_offset),
     85                    HeapObject::RawField(obj, end_offset));
     86 }
     87 
     88 
     89 template <typename StaticVisitor>
     90 DISABLE_CFI_PERF
     91 void BodyDescriptorBase::IteratePointers(Heap* heap, HeapObject* obj,
     92                                          int start_offset, int end_offset) {
     93   StaticVisitor::VisitPointers(heap, obj,
     94                                HeapObject::RawField(obj, start_offset),
     95                                HeapObject::RawField(obj, end_offset));
     96 }
     97 
     98 
     99 template <typename ObjectVisitor>
    100 void BodyDescriptorBase::IteratePointer(HeapObject* obj, int offset,
    101                                         ObjectVisitor* v) {
    102   v->VisitPointer(HeapObject::RawField(obj, offset));
    103 }
    104 
    105 
    106 template <typename StaticVisitor>
    107 void BodyDescriptorBase::IteratePointer(Heap* heap, HeapObject* obj,
    108                                         int offset) {
    109   StaticVisitor::VisitPointer(heap, obj, HeapObject::RawField(obj, offset));
    110 }
    111 
    112 
    113 // Iterates the function object according to the visiting policy.
    114 template <JSFunction::BodyVisitingPolicy body_visiting_policy>
    115 class JSFunction::BodyDescriptorImpl final : public BodyDescriptorBase {
    116  public:
    117   STATIC_ASSERT(kNonWeakFieldsEndOffset == kCodeEntryOffset);
    118   STATIC_ASSERT(kCodeEntryOffset + kPointerSize == kNextFunctionLinkOffset);
    119   STATIC_ASSERT(kNextFunctionLinkOffset + kPointerSize == kSize);
    120 
    121   static bool IsValidSlot(HeapObject* obj, int offset) {
    122     if (offset < kSize) return true;
    123     return IsValidSlotImpl(obj, offset);
    124   }
    125 
    126   template <typename ObjectVisitor>
    127   static inline void IterateBody(HeapObject* obj, int object_size,
    128                                  ObjectVisitor* v) {
    129     IteratePointers(obj, kPropertiesOffset, kNonWeakFieldsEndOffset, v);
    130 
    131     if (body_visiting_policy & kVisitCodeEntry) {
    132       v->VisitCodeEntry(obj->address() + kCodeEntryOffset);
    133     }
    134 
    135     if (body_visiting_policy & kVisitNextFunction) {
    136       IteratePointers(obj, kNextFunctionLinkOffset, kSize, v);
    137     }
    138     IterateBodyImpl(obj, kSize, object_size, v);
    139   }
    140 
    141   template <typename StaticVisitor>
    142   static inline void IterateBody(HeapObject* obj, int object_size) {
    143     Heap* heap = obj->GetHeap();
    144     IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
    145                                    kNonWeakFieldsEndOffset);
    146 
    147     if (body_visiting_policy & kVisitCodeEntry) {
    148       StaticVisitor::VisitCodeEntry(heap, obj,
    149                                     obj->address() + kCodeEntryOffset);
    150     }
    151 
    152     if (body_visiting_policy & kVisitNextFunction) {
    153       IteratePointers<StaticVisitor>(heap, obj, kNextFunctionLinkOffset, kSize);
    154     }
    155     IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
    156   }
    157 
    158   static inline int SizeOf(Map* map, HeapObject* object) {
    159     return map->instance_size();
    160   }
    161 };
    162 
    163 
    164 class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
    165  public:
    166   STATIC_ASSERT(kByteLengthOffset + kPointerSize == kBackingStoreOffset);
    167   STATIC_ASSERT(kBackingStoreOffset + kPointerSize == kBitFieldSlot);
    168   STATIC_ASSERT(kBitFieldSlot + kPointerSize == kSize);
    169 
    170   static bool IsValidSlot(HeapObject* obj, int offset) {
    171     if (offset < kBackingStoreOffset) return true;
    172     if (offset < kSize) return false;
    173     return IsValidSlotImpl(obj, offset);
    174   }
    175 
    176   template <typename ObjectVisitor>
    177   static inline void IterateBody(HeapObject* obj, int object_size,
    178                                  ObjectVisitor* v) {
    179     IteratePointers(obj, kPropertiesOffset, kBackingStoreOffset, v);
    180     IterateBodyImpl(obj, kSize, object_size, v);
    181   }
    182 
    183   template <typename StaticVisitor>
    184   static inline void IterateBody(HeapObject* obj, int object_size) {
    185     Heap* heap = obj->GetHeap();
    186     IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
    187                                    kBackingStoreOffset);
    188     IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
    189   }
    190 
    191   static inline int SizeOf(Map* map, HeapObject* object) {
    192     return map->instance_size();
    193   }
    194 };
    195 
    196 
    197 class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
    198  public:
    199   static bool IsValidSlot(HeapObject* obj, int offset) {
    200     return offset >= kConstantPoolOffset &&
    201            offset <= kSourcePositionTableOffset;
    202   }
    203 
    204   template <typename ObjectVisitor>
    205   static inline void IterateBody(HeapObject* obj, int object_size,
    206                                  ObjectVisitor* v) {
    207     IteratePointer(obj, kConstantPoolOffset, v);
    208     IteratePointer(obj, kHandlerTableOffset, v);
    209     IteratePointer(obj, kSourcePositionTableOffset, v);
    210   }
    211 
    212   template <typename StaticVisitor>
    213   static inline void IterateBody(HeapObject* obj, int object_size) {
    214     Heap* heap = obj->GetHeap();
    215     IteratePointer<StaticVisitor>(heap, obj, kConstantPoolOffset);
    216     IteratePointer<StaticVisitor>(heap, obj, kHandlerTableOffset);
    217     IteratePointer<StaticVisitor>(heap, obj, kSourcePositionTableOffset);
    218   }
    219 
    220   static inline int SizeOf(Map* map, HeapObject* obj) {
    221     return reinterpret_cast<BytecodeArray*>(obj)->BytecodeArraySize();
    222   }
    223 };
    224 
    225 
    226 class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
    227  public:
    228   static bool IsValidSlot(HeapObject* obj, int offset) {
    229     return offset == kBasePointerOffset;
    230   }
    231 
    232   template <typename ObjectVisitor>
    233   static inline void IterateBody(HeapObject* obj, int object_size,
    234                                  ObjectVisitor* v) {
    235     IteratePointer(obj, kBasePointerOffset, v);
    236   }
    237 
    238   template <typename StaticVisitor>
    239   static inline void IterateBody(HeapObject* obj, int object_size) {
    240     Heap* heap = obj->GetHeap();
    241     IteratePointer<StaticVisitor>(heap, obj, kBasePointerOffset);
    242   }
    243 
    244   static inline int SizeOf(Map* map, HeapObject* object) {
    245     return reinterpret_cast<FixedTypedArrayBase*>(object)->size();
    246   }
    247 };
    248 
    249 
    250 template <JSWeakCollection::BodyVisitingPolicy body_visiting_policy>
    251 class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
    252  public:
    253   STATIC_ASSERT(kTableOffset + kPointerSize == kNextOffset);
    254   STATIC_ASSERT(kNextOffset + kPointerSize == kSize);
    255 
    256   static bool IsValidSlot(HeapObject* obj, int offset) {
    257     return IsValidSlotImpl(obj, offset);
    258   }
    259 
    260   template <typename ObjectVisitor>
    261   static inline void IterateBody(HeapObject* obj, int object_size,
    262                                  ObjectVisitor* v) {
    263     if (body_visiting_policy == kVisitStrong) {
    264       IterateBodyImpl(obj, kPropertiesOffset, object_size, v);
    265     } else {
    266       IteratePointers(obj, kPropertiesOffset, kTableOffset, v);
    267       IterateBodyImpl(obj, kSize, object_size, v);
    268     }
    269   }
    270 
    271   template <typename StaticVisitor>
    272   static inline void IterateBody(HeapObject* obj, int object_size) {
    273     Heap* heap = obj->GetHeap();
    274     if (body_visiting_policy == kVisitStrong) {
    275       IterateBodyImpl<StaticVisitor>(heap, obj, kPropertiesOffset, object_size);
    276     } else {
    277       IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
    278                                      kTableOffset);
    279       IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
    280     }
    281   }
    282 
    283   static inline int SizeOf(Map* map, HeapObject* object) {
    284     return map->instance_size();
    285   }
    286 };
    287 
    288 
    289 class Foreign::BodyDescriptor final : public BodyDescriptorBase {
    290  public:
    291   static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
    292 
    293   template <typename ObjectVisitor>
    294   static inline void IterateBody(HeapObject* obj, int object_size,
    295                                  ObjectVisitor* v) {
    296     v->VisitExternalReference(reinterpret_cast<Address*>(
    297         HeapObject::RawField(obj, kForeignAddressOffset)));
    298   }
    299 
    300   template <typename StaticVisitor>
    301   static inline void IterateBody(HeapObject* obj, int object_size) {
    302     StaticVisitor::VisitExternalReference(reinterpret_cast<Address*>(
    303         HeapObject::RawField(obj, kForeignAddressOffset)));
    304   }
    305 
    306   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
    307 };
    308 
    309 
    310 class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
    311  public:
    312   static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
    313 
    314   template <typename ObjectVisitor>
    315   static inline void IterateBody(HeapObject* obj, int object_size,
    316                                  ObjectVisitor* v) {
    317     typedef v8::String::ExternalOneByteStringResource Resource;
    318     v->VisitExternalOneByteString(reinterpret_cast<Resource**>(
    319         HeapObject::RawField(obj, kResourceOffset)));
    320   }
    321 
    322   template <typename StaticVisitor>
    323   static inline void IterateBody(HeapObject* obj, int object_size) {
    324     typedef v8::String::ExternalOneByteStringResource Resource;
    325     StaticVisitor::VisitExternalOneByteString(reinterpret_cast<Resource**>(
    326         HeapObject::RawField(obj, kResourceOffset)));
    327   }
    328 
    329   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
    330 };
    331 
    332 
    333 class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
    334  public:
    335   static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
    336 
    337   template <typename ObjectVisitor>
    338   static inline void IterateBody(HeapObject* obj, int object_size,
    339                                  ObjectVisitor* v) {
    340     typedef v8::String::ExternalStringResource Resource;
    341     v->VisitExternalTwoByteString(reinterpret_cast<Resource**>(
    342         HeapObject::RawField(obj, kResourceOffset)));
    343   }
    344 
    345   template <typename StaticVisitor>
    346   static inline void IterateBody(HeapObject* obj, int object_size) {
    347     typedef v8::String::ExternalStringResource Resource;
    348     StaticVisitor::VisitExternalTwoByteString(reinterpret_cast<Resource**>(
    349         HeapObject::RawField(obj, kResourceOffset)));
    350   }
    351 
    352   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
    353 };
    354 
    355 
    356 class Code::BodyDescriptor final : public BodyDescriptorBase {
    357  public:
    358   STATIC_ASSERT(kRelocationInfoOffset + kPointerSize == kHandlerTableOffset);
    359   STATIC_ASSERT(kHandlerTableOffset + kPointerSize ==
    360                 kDeoptimizationDataOffset);
    361   STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
    362                 kSourcePositionTableOffset);
    363   STATIC_ASSERT(kSourcePositionTableOffset + kPointerSize ==
    364                 kTypeFeedbackInfoOffset);
    365   STATIC_ASSERT(kTypeFeedbackInfoOffset + kPointerSize ==
    366                 kNextCodeLinkOffset);
    367 
    368   static bool IsValidSlot(HeapObject* obj, int offset) {
    369     // Slots in code can't be invalid because we never trim code objects.
    370     return true;
    371   }
    372 
    373   template <typename ObjectVisitor>
    374   static inline void IterateBody(HeapObject* obj, ObjectVisitor* v) {
    375     int mode_mask = RelocInfo::kCodeTargetMask |
    376                     RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
    377                     RelocInfo::ModeMask(RelocInfo::CELL) |
    378                     RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
    379                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
    380                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
    381                     RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
    382                     RelocInfo::kDebugBreakSlotMask;
    383 
    384     IteratePointers(obj, kRelocationInfoOffset, kNextCodeLinkOffset, v);
    385     v->VisitNextCodeLink(HeapObject::RawField(obj, kNextCodeLinkOffset));
    386 
    387     RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
    388     Isolate* isolate = obj->GetIsolate();
    389     for (; !it.done(); it.next()) {
    390       it.rinfo()->Visit(isolate, v);
    391     }
    392   }
    393 
    394   template <typename ObjectVisitor>
    395   static inline void IterateBody(HeapObject* obj, int object_size,
    396                                  ObjectVisitor* v) {
    397     IterateBody(obj, v);
    398   }
    399 
    400   template <typename StaticVisitor>
    401   static inline void IterateBody(HeapObject* obj) {
    402     int mode_mask = RelocInfo::kCodeTargetMask |
    403                     RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
    404                     RelocInfo::ModeMask(RelocInfo::CELL) |
    405                     RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
    406                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
    407                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
    408                     RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
    409                     RelocInfo::kDebugBreakSlotMask;
    410 
    411     Heap* heap = obj->GetHeap();
    412     IteratePointers<StaticVisitor>(heap, obj, kRelocationInfoOffset,
    413                                    kNextCodeLinkOffset);
    414     StaticVisitor::VisitNextCodeLink(
    415         heap, HeapObject::RawField(obj, kNextCodeLinkOffset));
    416 
    417     RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
    418     for (; !it.done(); it.next()) {
    419       it.rinfo()->template Visit<StaticVisitor>(heap);
    420     }
    421   }
    422 
    423   template <typename StaticVisitor>
    424   static inline void IterateBody(HeapObject* obj, int object_size) {
    425     IterateBody<StaticVisitor>(obj);
    426   }
    427 
    428   static inline int SizeOf(Map* map, HeapObject* object) {
    429     return reinterpret_cast<Code*>(object)->CodeSize();
    430   }
    431 };
    432 
    433 
    434 template <typename Op, typename ReturnType, typename T1, typename T2,
    435           typename T3>
    436 ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
    437   if (type < FIRST_NONSTRING_TYPE) {
    438     switch (type & kStringRepresentationMask) {
    439       case kSeqStringTag:
    440         return ReturnType();
    441       case kConsStringTag:
    442         return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3);
    443       case kThinStringTag:
    444         return Op::template apply<ThinString::BodyDescriptor>(p1, p2, p3);
    445       case kSlicedStringTag:
    446         return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3);
    447       case kExternalStringTag:
    448         if ((type & kStringEncodingMask) == kOneByteStringTag) {
    449           return Op::template apply<ExternalOneByteString::BodyDescriptor>(
    450               p1, p2, p3);
    451         } else {
    452           return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
    453               p1, p2, p3);
    454         }
    455     }
    456     UNREACHABLE();
    457     return ReturnType();
    458   }
    459 
    460   switch (type) {
    461     case FIXED_ARRAY_TYPE:
    462       return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3);
    463     case FIXED_DOUBLE_ARRAY_TYPE:
    464       return ReturnType();
    465     case TRANSITION_ARRAY_TYPE:
    466       return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3);
    467     case JS_OBJECT_TYPE:
    468     case JS_ERROR_TYPE:
    469     case JS_ARGUMENTS_TYPE:
    470     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
    471     case JS_PROMISE_CAPABILITY_TYPE:
    472     case JS_PROMISE_TYPE:
    473     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    474     case JS_GENERATOR_OBJECT_TYPE:
    475     case JS_VALUE_TYPE:
    476     case JS_DATE_TYPE:
    477     case JS_ARRAY_TYPE:
    478     case JS_MODULE_NAMESPACE_TYPE:
    479     case JS_TYPED_ARRAY_TYPE:
    480     case JS_DATA_VIEW_TYPE:
    481     case JS_SET_TYPE:
    482     case JS_MAP_TYPE:
    483     case JS_SET_ITERATOR_TYPE:
    484     case JS_MAP_ITERATOR_TYPE:
    485     case JS_STRING_ITERATOR_TYPE:
    486 
    487     case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
    488     case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
    489     case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
    490     case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    491     case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    492     case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    493     case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    494     case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    495     case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    496     case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    497     case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    498     case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    499     case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    500     case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    501     case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    502     case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    503     case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    504     case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    505     case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    506     case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
    507     case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
    508     case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
    509     case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
    510     case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
    511     case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
    512     case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
    513     case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
    514     case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
    515     case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
    516     case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
    517     case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
    518     case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
    519     case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
    520     case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
    521     case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:
    522 
    523     case JS_REGEXP_TYPE:
    524     case JS_GLOBAL_PROXY_TYPE:
    525     case JS_GLOBAL_OBJECT_TYPE:
    526     case JS_API_OBJECT_TYPE:
    527     case JS_SPECIAL_API_OBJECT_TYPE:
    528     case JS_MESSAGE_OBJECT_TYPE:
    529     case JS_BOUND_FUNCTION_TYPE:
    530       return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3);
    531     case JS_WEAK_MAP_TYPE:
    532     case JS_WEAK_SET_TYPE:
    533       return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3);
    534     case JS_ARRAY_BUFFER_TYPE:
    535       return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3);
    536     case JS_FUNCTION_TYPE:
    537       return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3);
    538     case ODDBALL_TYPE:
    539       return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3);
    540     case JS_PROXY_TYPE:
    541       return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3);
    542     case FOREIGN_TYPE:
    543       return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3);
    544     case MAP_TYPE:
    545       return Op::template apply<Map::BodyDescriptor>(p1, p2, p3);
    546     case CODE_TYPE:
    547       return Op::template apply<Code::BodyDescriptor>(p1, p2, p3);
    548     case CELL_TYPE:
    549       return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3);
    550     case PROPERTY_CELL_TYPE:
    551       return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3);
    552     case WEAK_CELL_TYPE:
    553       return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3);
    554     case SYMBOL_TYPE:
    555       return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3);
    556     case BYTECODE_ARRAY_TYPE:
    557       return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3);
    558 
    559     case HEAP_NUMBER_TYPE:
    560     case MUTABLE_HEAP_NUMBER_TYPE:
    561     case FILLER_TYPE:
    562     case BYTE_ARRAY_TYPE:
    563     case FREE_SPACE_TYPE:
    564       return ReturnType();
    565 
    566 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
    567   case FIXED_##TYPE##_ARRAY_TYPE:                       \
    568     return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3);
    569       TYPED_ARRAYS(TYPED_ARRAY_CASE)
    570 #undef TYPED_ARRAY_CASE
    571 
    572     case SHARED_FUNCTION_INFO_TYPE: {
    573       return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3);
    574     }
    575 
    576 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
    577       STRUCT_LIST(MAKE_STRUCT_CASE)
    578 #undef MAKE_STRUCT_CASE
    579       if (type == ALLOCATION_SITE_TYPE) {
    580         return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3);
    581       } else {
    582         return Op::template apply<StructBodyDescriptor>(p1, p2, p3);
    583       }
    584     default:
    585       PrintF("Unknown type: %d\n", type);
    586       UNREACHABLE();
    587       return ReturnType();
    588   }
    589 }
    590 
    591 
    592 template <typename ObjectVisitor>
    593 void HeapObject::IterateFast(ObjectVisitor* v) {
    594   BodyDescriptorBase::IteratePointer(this, kMapOffset, v);
    595   IterateBodyFast(v);
    596 }
    597 
    598 
    599 template <typename ObjectVisitor>
    600 void HeapObject::IterateBodyFast(ObjectVisitor* v) {
    601   Map* m = map();
    602   IterateBodyFast(m->instance_type(), SizeFromMap(m), v);
    603 }
    604 
    605 
    606 struct CallIterateBody {
    607   template <typename BodyDescriptor, typename ObjectVisitor>
    608   static void apply(HeapObject* obj, int object_size, ObjectVisitor* v) {
    609     BodyDescriptor::IterateBody(obj, object_size, v);
    610   }
    611 };
    612 
    613 template <typename ObjectVisitor>
    614 void HeapObject::IterateBodyFast(InstanceType type, int object_size,
    615                                  ObjectVisitor* v) {
    616   BodyDescriptorApply<CallIterateBody, void>(type, this, object_size, v);
    617 }
    618 }  // namespace internal
    619 }  // namespace v8
    620 
    621 #endif  // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
    622