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