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   }
    198 
    199   template <typename ObjectVisitor>
    200   static inline void IterateBody(HeapObject* obj, int object_size,
    201                                  ObjectVisitor* v) {
    202     IteratePointer(obj, kConstantPoolOffset, v);
    203   }
    204 
    205   template <typename StaticVisitor>
    206   static inline void IterateBody(HeapObject* obj, int object_size) {
    207     Heap* heap = obj->GetHeap();
    208     IteratePointer<StaticVisitor>(heap, obj, kConstantPoolOffset);
    209   }
    210 
    211   static inline int SizeOf(Map* map, HeapObject* obj) {
    212     return reinterpret_cast<BytecodeArray*>(obj)->BytecodeArraySize();
    213   }
    214 };
    215 
    216 
    217 class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
    218  public:
    219   static bool IsValidSlot(HeapObject* obj, int offset) {
    220     return offset == kBasePointerOffset;
    221   }
    222 
    223   template <typename ObjectVisitor>
    224   static inline void IterateBody(HeapObject* obj, int object_size,
    225                                  ObjectVisitor* v) {
    226     IteratePointer(obj, kBasePointerOffset, v);
    227   }
    228 
    229   template <typename StaticVisitor>
    230   static inline void IterateBody(HeapObject* obj, int object_size) {
    231     Heap* heap = obj->GetHeap();
    232     IteratePointer<StaticVisitor>(heap, obj, kBasePointerOffset);
    233   }
    234 
    235   static inline int SizeOf(Map* map, HeapObject* object) {
    236     return reinterpret_cast<FixedTypedArrayBase*>(object)->size();
    237   }
    238 };
    239 
    240 
    241 template <JSWeakCollection::BodyVisitingPolicy body_visiting_policy>
    242 class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
    243  public:
    244   STATIC_ASSERT(kTableOffset + kPointerSize == kNextOffset);
    245   STATIC_ASSERT(kNextOffset + kPointerSize == kSize);
    246 
    247   static bool IsValidSlot(HeapObject* obj, int offset) {
    248     return IsValidSlotImpl(obj, offset);
    249   }
    250 
    251   template <typename ObjectVisitor>
    252   static inline void IterateBody(HeapObject* obj, int object_size,
    253                                  ObjectVisitor* v) {
    254     if (body_visiting_policy == kVisitStrong) {
    255       IterateBodyImpl(obj, kPropertiesOffset, object_size, v);
    256     } else {
    257       IteratePointers(obj, kPropertiesOffset, kTableOffset, v);
    258       IterateBodyImpl(obj, kSize, object_size, v);
    259     }
    260   }
    261 
    262   template <typename StaticVisitor>
    263   static inline void IterateBody(HeapObject* obj, int object_size) {
    264     Heap* heap = obj->GetHeap();
    265     if (body_visiting_policy == kVisitStrong) {
    266       IterateBodyImpl<StaticVisitor>(heap, obj, kPropertiesOffset, object_size);
    267     } else {
    268       IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
    269                                      kTableOffset);
    270       IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
    271     }
    272   }
    273 
    274   static inline int SizeOf(Map* map, HeapObject* object) {
    275     return map->instance_size();
    276   }
    277 };
    278 
    279 
    280 class Foreign::BodyDescriptor final : public BodyDescriptorBase {
    281  public:
    282   static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
    283 
    284   template <typename ObjectVisitor>
    285   static inline void IterateBody(HeapObject* obj, int object_size,
    286                                  ObjectVisitor* v) {
    287     v->VisitExternalReference(reinterpret_cast<Address*>(
    288         HeapObject::RawField(obj, kForeignAddressOffset)));
    289   }
    290 
    291   template <typename StaticVisitor>
    292   static inline void IterateBody(HeapObject* obj, int object_size) {
    293     StaticVisitor::VisitExternalReference(reinterpret_cast<Address*>(
    294         HeapObject::RawField(obj, kForeignAddressOffset)));
    295   }
    296 
    297   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
    298 };
    299 
    300 
    301 class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
    302  public:
    303   static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
    304 
    305   template <typename ObjectVisitor>
    306   static inline void IterateBody(HeapObject* obj, int object_size,
    307                                  ObjectVisitor* v) {
    308     typedef v8::String::ExternalOneByteStringResource Resource;
    309     v->VisitExternalOneByteString(reinterpret_cast<Resource**>(
    310         HeapObject::RawField(obj, kResourceOffset)));
    311   }
    312 
    313   template <typename StaticVisitor>
    314   static inline void IterateBody(HeapObject* obj, int object_size) {
    315     typedef v8::String::ExternalOneByteStringResource Resource;
    316     StaticVisitor::VisitExternalOneByteString(reinterpret_cast<Resource**>(
    317         HeapObject::RawField(obj, kResourceOffset)));
    318   }
    319 
    320   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
    321 };
    322 
    323 
    324 class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
    325  public:
    326   static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
    327 
    328   template <typename ObjectVisitor>
    329   static inline void IterateBody(HeapObject* obj, int object_size,
    330                                  ObjectVisitor* v) {
    331     typedef v8::String::ExternalStringResource Resource;
    332     v->VisitExternalTwoByteString(reinterpret_cast<Resource**>(
    333         HeapObject::RawField(obj, kResourceOffset)));
    334   }
    335 
    336   template <typename StaticVisitor>
    337   static inline void IterateBody(HeapObject* obj, int object_size) {
    338     typedef v8::String::ExternalStringResource Resource;
    339     StaticVisitor::VisitExternalTwoByteString(reinterpret_cast<Resource**>(
    340         HeapObject::RawField(obj, kResourceOffset)));
    341   }
    342 
    343   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
    344 };
    345 
    346 
    347 class Code::BodyDescriptor final : public BodyDescriptorBase {
    348  public:
    349   STATIC_ASSERT(kRelocationInfoOffset + kPointerSize == kHandlerTableOffset);
    350   STATIC_ASSERT(kHandlerTableOffset + kPointerSize ==
    351                 kDeoptimizationDataOffset);
    352   STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
    353                 kTypeFeedbackInfoOffset);
    354   STATIC_ASSERT(kTypeFeedbackInfoOffset + kPointerSize == kNextCodeLinkOffset);
    355 
    356   static bool IsValidSlot(HeapObject* obj, int offset) {
    357     // Slots in code can't be invalid because we never trim code objects.
    358     return true;
    359   }
    360 
    361   template <typename ObjectVisitor>
    362   static inline void IterateBody(HeapObject* obj, ObjectVisitor* v) {
    363     int mode_mask = RelocInfo::kCodeTargetMask |
    364                     RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
    365                     RelocInfo::ModeMask(RelocInfo::CELL) |
    366                     RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
    367                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
    368                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
    369                     RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
    370                     RelocInfo::kDebugBreakSlotMask;
    371 
    372     IteratePointers(obj, kRelocationInfoOffset, kNextCodeLinkOffset, v);
    373     v->VisitNextCodeLink(HeapObject::RawField(obj, kNextCodeLinkOffset));
    374 
    375     RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
    376     Isolate* isolate = obj->GetIsolate();
    377     for (; !it.done(); it.next()) {
    378       it.rinfo()->Visit(isolate, v);
    379     }
    380   }
    381 
    382   template <typename ObjectVisitor>
    383   static inline void IterateBody(HeapObject* obj, int object_size,
    384                                  ObjectVisitor* v) {
    385     IterateBody(obj, v);
    386   }
    387 
    388   template <typename StaticVisitor>
    389   static inline void IterateBody(HeapObject* obj) {
    390     int mode_mask = RelocInfo::kCodeTargetMask |
    391                     RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
    392                     RelocInfo::ModeMask(RelocInfo::CELL) |
    393                     RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
    394                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
    395                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
    396                     RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
    397                     RelocInfo::kDebugBreakSlotMask;
    398 
    399     Heap* heap = obj->GetHeap();
    400     IteratePointers<StaticVisitor>(heap, obj, kRelocationInfoOffset,
    401                                    kNextCodeLinkOffset);
    402     StaticVisitor::VisitNextCodeLink(
    403         heap, HeapObject::RawField(obj, kNextCodeLinkOffset));
    404 
    405     RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
    406     for (; !it.done(); it.next()) {
    407       it.rinfo()->template Visit<StaticVisitor>(heap);
    408     }
    409   }
    410 
    411   template <typename StaticVisitor>
    412   static inline void IterateBody(HeapObject* obj, int object_size) {
    413     IterateBody<StaticVisitor>(obj);
    414   }
    415 
    416   static inline int SizeOf(Map* map, HeapObject* object) {
    417     return reinterpret_cast<Code*>(object)->CodeSize();
    418   }
    419 };
    420 
    421 
    422 template <typename Op, typename ReturnType, typename T1, typename T2,
    423           typename T3>
    424 ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
    425   if (type < FIRST_NONSTRING_TYPE) {
    426     switch (type & kStringRepresentationMask) {
    427       case kSeqStringTag:
    428         return ReturnType();
    429       case kConsStringTag:
    430         return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3);
    431       case kSlicedStringTag:
    432         return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3);
    433       case kExternalStringTag:
    434         if ((type & kStringEncodingMask) == kOneByteStringTag) {
    435           return Op::template apply<ExternalOneByteString::BodyDescriptor>(
    436               p1, p2, p3);
    437         } else {
    438           return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
    439               p1, p2, p3);
    440         }
    441     }
    442     UNREACHABLE();
    443     return ReturnType();
    444   }
    445 
    446   switch (type) {
    447     case FIXED_ARRAY_TYPE:
    448       return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3);
    449     case FIXED_DOUBLE_ARRAY_TYPE:
    450       return ReturnType();
    451     case TRANSITION_ARRAY_TYPE:
    452       return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3);
    453     case JS_OBJECT_TYPE:
    454     case JS_PROMISE_TYPE:
    455     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    456     case JS_GENERATOR_OBJECT_TYPE:
    457     case JS_MODULE_TYPE:
    458     case JS_VALUE_TYPE:
    459     case JS_DATE_TYPE:
    460     case JS_ARRAY_TYPE:
    461     case JS_TYPED_ARRAY_TYPE:
    462     case JS_DATA_VIEW_TYPE:
    463     case JS_SET_TYPE:
    464     case JS_MAP_TYPE:
    465     case JS_SET_ITERATOR_TYPE:
    466     case JS_MAP_ITERATOR_TYPE:
    467     case JS_ITERATOR_RESULT_TYPE:
    468     case JS_REGEXP_TYPE:
    469     case JS_GLOBAL_PROXY_TYPE:
    470     case JS_GLOBAL_OBJECT_TYPE:
    471     case JS_MESSAGE_OBJECT_TYPE:
    472     case JS_BOUND_FUNCTION_TYPE:
    473       return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3);
    474     case JS_WEAK_MAP_TYPE:
    475     case JS_WEAK_SET_TYPE:
    476       return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3);
    477     case JS_ARRAY_BUFFER_TYPE:
    478       return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3);
    479     case JS_FUNCTION_TYPE:
    480       return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3);
    481     case ODDBALL_TYPE:
    482       return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3);
    483     case JS_PROXY_TYPE:
    484       return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3);
    485     case FOREIGN_TYPE:
    486       return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3);
    487     case MAP_TYPE:
    488       return Op::template apply<Map::BodyDescriptor>(p1, p2, p3);
    489     case CODE_TYPE:
    490       return Op::template apply<Code::BodyDescriptor>(p1, p2, p3);
    491     case CELL_TYPE:
    492       return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3);
    493     case PROPERTY_CELL_TYPE:
    494       return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3);
    495     case WEAK_CELL_TYPE:
    496       return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3);
    497     case SYMBOL_TYPE:
    498       return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3);
    499     case BYTECODE_ARRAY_TYPE:
    500       return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3);
    501 
    502     case HEAP_NUMBER_TYPE:
    503     case MUTABLE_HEAP_NUMBER_TYPE:
    504     case SIMD128_VALUE_TYPE:
    505     case FILLER_TYPE:
    506     case BYTE_ARRAY_TYPE:
    507     case FREE_SPACE_TYPE:
    508       return ReturnType();
    509 
    510 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
    511   case FIXED_##TYPE##_ARRAY_TYPE:                       \
    512     return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3);
    513       TYPED_ARRAYS(TYPED_ARRAY_CASE)
    514 #undef TYPED_ARRAY_CASE
    515 
    516     case SHARED_FUNCTION_INFO_TYPE: {
    517       return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3);
    518     }
    519 
    520 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
    521       STRUCT_LIST(MAKE_STRUCT_CASE)
    522 #undef MAKE_STRUCT_CASE
    523       if (type == ALLOCATION_SITE_TYPE) {
    524         return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3);
    525       } else {
    526         return Op::template apply<StructBodyDescriptor>(p1, p2, p3);
    527       }
    528     default:
    529       PrintF("Unknown type: %d\n", type);
    530       UNREACHABLE();
    531       return ReturnType();
    532   }
    533 }
    534 
    535 
    536 template <typename ObjectVisitor>
    537 void HeapObject::IterateFast(ObjectVisitor* v) {
    538   BodyDescriptorBase::IteratePointer(this, kMapOffset, v);
    539   IterateBodyFast(v);
    540 }
    541 
    542 
    543 template <typename ObjectVisitor>
    544 void HeapObject::IterateBodyFast(ObjectVisitor* v) {
    545   Map* m = map();
    546   IterateBodyFast(m->instance_type(), SizeFromMap(m), v);
    547 }
    548 
    549 
    550 struct CallIterateBody {
    551   template <typename BodyDescriptor, typename ObjectVisitor>
    552   static void apply(HeapObject* obj, int object_size, ObjectVisitor* v) {
    553     BodyDescriptor::IterateBody(obj, object_size, v);
    554   }
    555 };
    556 
    557 template <typename ObjectVisitor>
    558 void HeapObject::IterateBodyFast(InstanceType type, int object_size,
    559                                  ObjectVisitor* v) {
    560   BodyDescriptorApply<CallIterateBody, void>(type, this, object_size, v);
    561 }
    562 }  // namespace internal
    563 }  // namespace v8
    564 
    565 #endif  // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
    566