// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
#define V8_OBJECTS_BODY_DESCRIPTORS_INL_H_

#include "src/assembler-inl.h"
#include "src/objects-body-descriptors.h"
#include "src/objects/hash-table.h"
#include "src/transitions.h"

namespace v8 {
namespace internal {

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

bool BodyDescriptorBase::IsValidSlotImpl(HeapObject* obj, int offset) {
  if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
    return true;
  } else {
    DCHECK(FLAG_unbox_double_fields);
    DCHECK(IsAligned(offset, kPointerSize));

    LayoutDescriptorHelper helper(obj->map());
    DCHECK(!helper.all_fields_tagged());
    return helper.IsTagged(offset);
  }
}

template <typename ObjectVisitor>
void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
                                         int end_offset, ObjectVisitor* v) {
  if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
    IteratePointers(obj, start_offset, end_offset, v);
  } else {
    DCHECK(FLAG_unbox_double_fields);
    DCHECK(IsAligned(start_offset, kPointerSize) &&
           IsAligned(end_offset, kPointerSize));

    LayoutDescriptorHelper helper(obj->map());
    DCHECK(!helper.all_fields_tagged());
    for (int offset = start_offset; offset < end_offset;) {
      int end_of_region_offset;
      if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
        IteratePointers(obj, offset, end_of_region_offset, v);
      }
      offset = end_of_region_offset;
    }
  }
}

template <typename StaticVisitor>
void BodyDescriptorBase::IterateBodyImpl(Heap* heap, HeapObject* obj,
                                         int start_offset, int end_offset) {
  if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
    IteratePointers<StaticVisitor>(heap, obj, start_offset, end_offset);
  } else {
    DCHECK(FLAG_unbox_double_fields);
    DCHECK(IsAligned(start_offset, kPointerSize) &&
           IsAligned(end_offset, kPointerSize));

    LayoutDescriptorHelper helper(obj->map());
    DCHECK(!helper.all_fields_tagged());
    for (int offset = start_offset; offset < end_offset;) {
      int end_of_region_offset;
      if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
        IteratePointers<StaticVisitor>(heap, obj, offset, end_of_region_offset);
      }
      offset = end_of_region_offset;
    }
  }
}

template <typename ObjectVisitor>
DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(HeapObject* obj,
                                                          int start_offset,
                                                          int end_offset,
                                                          ObjectVisitor* v) {
  v->VisitPointers(obj, HeapObject::RawField(obj, start_offset),
                   HeapObject::RawField(obj, end_offset));
}

template <typename StaticVisitor>
DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(Heap* heap,
                                                          HeapObject* obj,
                                                          int start_offset,
                                                          int end_offset) {
  StaticVisitor::VisitPointers(heap, obj,
                               HeapObject::RawField(obj, start_offset),
                               HeapObject::RawField(obj, end_offset));
}

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

template <typename StaticVisitor>
void BodyDescriptorBase::IteratePointer(Heap* heap, HeapObject* obj,
                                        int offset) {
  StaticVisitor::VisitPointer(heap, obj, HeapObject::RawField(obj, offset));
}

class JSObject::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static const int kStartOffset = JSReceiver::kPropertiesOffset;

  static bool IsValidSlot(HeapObject* obj, int offset) {
    if (offset < kStartOffset) return false;
    return IsValidSlotImpl(obj, offset);
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IterateBodyImpl(obj, kStartOffset, object_size, v);
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    Heap* heap = obj->GetHeap();
    IterateBodyImpl<StaticVisitor>(heap, obj, kStartOffset, object_size);
  }

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

class JSObject::FastBodyDescriptor final : public BodyDescriptorBase {
 public:
  static const int kStartOffset = JSReceiver::kPropertiesOffset;

  static bool IsValidSlot(HeapObject* obj, int offset) {
    return offset >= kStartOffset;
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointers(obj, kStartOffset, object_size, v);
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    Heap* heap = obj->GetHeap();
    IteratePointers<StaticVisitor>(heap, obj, kStartOffset, object_size);
  }

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

// Iterates the function object according to the visiting policy.
template <JSFunction::BodyVisitingPolicy body_visiting_policy>
class JSFunction::BodyDescriptorImpl final : public BodyDescriptorBase {
 public:
  STATIC_ASSERT(kNonWeakFieldsEndOffset == kCodeEntryOffset);
  STATIC_ASSERT(kCodeEntryOffset + kPointerSize == kNextFunctionLinkOffset);
  STATIC_ASSERT(kNextFunctionLinkOffset + kPointerSize == kSize);

  static bool IsValidSlot(HeapObject* obj, int offset) {
    if (offset < kSize) return true;
    return IsValidSlotImpl(obj, offset);
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointers(obj, kPropertiesOffset, kNonWeakFieldsEndOffset, v);

    if (body_visiting_policy & kVisitCodeEntry) {
      v->VisitCodeEntry(JSFunction::cast(obj),
                        obj->address() + kCodeEntryOffset);
    }

    if (body_visiting_policy & kVisitNextFunction) {
      IteratePointers(obj, kNextFunctionLinkOffset, kSize, v);
    }
    IterateBodyImpl(obj, kSize, object_size, v);
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    Heap* heap = obj->GetHeap();
    IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
                                   kNonWeakFieldsEndOffset);

    if (body_visiting_policy & kVisitCodeEntry) {
      StaticVisitor::VisitCodeEntry(heap, obj,
                                    obj->address() + kCodeEntryOffset);
    }

    if (body_visiting_policy & kVisitNextFunction) {
      IteratePointers<StaticVisitor>(heap, obj, kNextFunctionLinkOffset, kSize);
    }
    IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
  }

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

class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
 public:
  STATIC_ASSERT(kByteLengthOffset + kPointerSize == kBackingStoreOffset);
  STATIC_ASSERT(kAllocationLengthOffset + kPointerSize == kBitFieldSlot);
  STATIC_ASSERT(kBitFieldSlot + kPointerSize == kSize);

  static bool IsValidSlot(HeapObject* obj, int offset) {
    if (offset < kAllocationLengthOffset) return true;
    if (offset < kSize) return false;
    return IsValidSlotImpl(obj, offset);
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    // Array buffers contain raw pointers that the GC does not know about. These
    // are stored at kBackStoreOffset and later, so we do not iterate over
    // those.
    IteratePointers(obj, kPropertiesOffset, kBackingStoreOffset, v);
    IterateBodyImpl(obj, kSize, object_size, v);
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    Heap* heap = obj->GetHeap();
    // Array buffers contain raw pointers that the GC does not know about. These
    // are stored at kBackStoreOffset and later, so we do not iterate over
    // those.
    IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
                                   kBackingStoreOffset);
    IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
  }

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

class SmallOrderedHashSet::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) {
    SmallOrderedHashSet* table = reinterpret_cast<SmallOrderedHashSet*>(obj);
    if (offset < table->GetDataTableStartOffset()) return false;
    return IsValidSlotImpl(obj, offset);
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    SmallOrderedHashSet* table = reinterpret_cast<SmallOrderedHashSet*>(obj);
    int start = table->GetDataTableStartOffset();
    for (int i = 0; i < table->Capacity(); i++) {
      IteratePointer(obj, start + (i * kPointerSize), v);
    }
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    Heap* heap = obj->GetHeap();
    SmallOrderedHashSet* table = reinterpret_cast<SmallOrderedHashSet*>(obj);
    int start = table->GetDataTableStartOffset();
    for (int i = 0; i < table->Capacity(); i++) {
      IteratePointer<StaticVisitor>(heap, obj, start + (i * kPointerSize));
    }
  }

  static inline int SizeOf(Map* map, HeapObject* obj) {
    SmallOrderedHashSet* table = reinterpret_cast<SmallOrderedHashSet*>(obj);
    return table->Size();
  }
};

class ByteArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {}

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {}

  static inline int SizeOf(Map* map, HeapObject* obj) {
    return reinterpret_cast<ByteArray*>(obj)->ByteArraySize();
  }
};

class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) {
    return offset >= kConstantPoolOffset &&
           offset <= kSourcePositionTableOffset;
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointer(obj, kConstantPoolOffset, v);
    IteratePointer(obj, kHandlerTableOffset, v);
    IteratePointer(obj, kSourcePositionTableOffset, v);
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    Heap* heap = obj->GetHeap();
    IteratePointer<StaticVisitor>(heap, obj, kConstantPoolOffset);
    IteratePointer<StaticVisitor>(heap, obj, kHandlerTableOffset);
    IteratePointer<StaticVisitor>(heap, obj, kSourcePositionTableOffset);
  }

  static inline int SizeOf(Map* map, HeapObject* obj) {
    return reinterpret_cast<BytecodeArray*>(obj)->BytecodeArraySize();
  }
};

class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {}

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {}

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

class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) {
    return offset == kBasePointerOffset;
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IteratePointer(obj, kBasePointerOffset, v);
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    Heap* heap = obj->GetHeap();
    IteratePointer<StaticVisitor>(heap, obj, kBasePointerOffset);
  }

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

template <JSWeakCollection::BodyVisitingPolicy body_visiting_policy>
class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
 public:
  STATIC_ASSERT(kTableOffset + kPointerSize == kNextOffset);
  STATIC_ASSERT(kNextOffset + kPointerSize == kSize);

  static bool IsValidSlot(HeapObject* obj, int offset) {
    return IsValidSlotImpl(obj, offset);
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    if (body_visiting_policy == kVisitStrong) {
      IterateBodyImpl(obj, kPropertiesOffset, object_size, v);
    } else {
      IteratePointers(obj, kPropertiesOffset, kTableOffset, v);
      IterateBodyImpl(obj, kSize, object_size, v);
    }
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    Heap* heap = obj->GetHeap();
    if (body_visiting_policy == kVisitStrong) {
      IterateBodyImpl<StaticVisitor>(heap, obj, kPropertiesOffset, object_size);
    } else {
      IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
                                     kTableOffset);
      IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
    }
  }

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

class Foreign::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    v->VisitExternalReference(Foreign::cast(obj),
                              reinterpret_cast<Address*>(HeapObject::RawField(
                                  obj, kForeignAddressOffset)));
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    StaticVisitor::VisitExternalReference(reinterpret_cast<Address*>(
        HeapObject::RawField(obj, kForeignAddressOffset)));
  }

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

class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
  }

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

class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
  }

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

class Code::BodyDescriptor final : public BodyDescriptorBase {
 public:
  STATIC_ASSERT(kRelocationInfoOffset + kPointerSize == kHandlerTableOffset);
  STATIC_ASSERT(kHandlerTableOffset + kPointerSize ==
                kDeoptimizationDataOffset);
  STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
                kSourcePositionTableOffset);
  STATIC_ASSERT(kSourcePositionTableOffset + kPointerSize ==
                kTypeFeedbackInfoOffset);
  STATIC_ASSERT(kTypeFeedbackInfoOffset + kPointerSize ==
                kNextCodeLinkOffset);

  static bool IsValidSlot(HeapObject* obj, int offset) {
    // Slots in code can't be invalid because we never trim code objects.
    return true;
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, ObjectVisitor* v) {
    int mode_mask = RelocInfo::kCodeTargetMask |
                    RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                    RelocInfo::ModeMask(RelocInfo::CELL) |
                    RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
                    RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
                    RelocInfo::kDebugBreakSlotMask;

    IteratePointers(obj, kRelocationInfoOffset, kNextCodeLinkOffset, v);
    v->VisitNextCodeLink(Code::cast(obj),
                         HeapObject::RawField(obj, kNextCodeLinkOffset));

    RelocIterator it(Code::cast(obj), mode_mask);
    Isolate* isolate = obj->GetIsolate();
    for (; !it.done(); it.next()) {
      it.rinfo()->Visit(isolate, v);
    }
  }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {
    IterateBody(obj, v);
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj) {
    int mode_mask = RelocInfo::kCodeTargetMask |
                    RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                    RelocInfo::ModeMask(RelocInfo::CELL) |
                    RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
                    RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
                    RelocInfo::kDebugBreakSlotMask;

    Heap* heap = obj->GetHeap();
    IteratePointers<StaticVisitor>(heap, obj, kRelocationInfoOffset,
                                   kNextCodeLinkOffset);
    StaticVisitor::VisitNextCodeLink(
        heap, HeapObject::RawField(obj, kNextCodeLinkOffset));

    RelocIterator it(Code::cast(obj), mode_mask);
    for (; !it.done(); it.next()) {
      it.rinfo()->template Visit<StaticVisitor>(heap);
    }
  }

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {
    IterateBody<StaticVisitor>(obj);
  }

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

class SeqOneByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {}

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {}

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

class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
 public:
  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }

  template <typename ObjectVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size,
                                 ObjectVisitor* v) {}

  template <typename StaticVisitor>
  static inline void IterateBody(HeapObject* obj, int object_size) {}

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

template <typename Op, typename ReturnType, typename T1, typename T2,
          typename T3>
ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
  if (type < FIRST_NONSTRING_TYPE) {
    switch (type & kStringRepresentationMask) {
      case kSeqStringTag:
        return ReturnType();
      case kConsStringTag:
        return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3);
      case kThinStringTag:
        return Op::template apply<ThinString::BodyDescriptor>(p1, p2, p3);
      case kSlicedStringTag:
        return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3);
      case kExternalStringTag:
        if ((type & kStringEncodingMask) == kOneByteStringTag) {
          return Op::template apply<ExternalOneByteString::BodyDescriptor>(
              p1, p2, p3);
        } else {
          return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
              p1, p2, p3);
        }
    }
    UNREACHABLE();
  }

  switch (type) {
    case FIXED_ARRAY_TYPE:
      return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3);
    case FIXED_DOUBLE_ARRAY_TYPE:
      return ReturnType();
    case TRANSITION_ARRAY_TYPE:
      return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3);
    case JS_OBJECT_TYPE:
    case JS_ERROR_TYPE:
    case JS_ARGUMENTS_TYPE:
    case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
    case JS_PROMISE_CAPABILITY_TYPE:
    case JS_PROMISE_TYPE:
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    case JS_GENERATOR_OBJECT_TYPE:
    case JS_ASYNC_GENERATOR_OBJECT_TYPE:
    case JS_VALUE_TYPE:
    case JS_DATE_TYPE:
    case JS_ARRAY_TYPE:
    case JS_MODULE_NAMESPACE_TYPE:
    case JS_TYPED_ARRAY_TYPE:
    case JS_DATA_VIEW_TYPE:
    case JS_SET_TYPE:
    case JS_MAP_TYPE:
    case JS_SET_ITERATOR_TYPE:
    case JS_MAP_ITERATOR_TYPE:
    case JS_STRING_ITERATOR_TYPE:

    case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
    case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
    case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
    case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:

    case JS_REGEXP_TYPE:
    case JS_GLOBAL_PROXY_TYPE:
    case JS_GLOBAL_OBJECT_TYPE:
    case JS_API_OBJECT_TYPE:
    case JS_SPECIAL_API_OBJECT_TYPE:
    case JS_MESSAGE_OBJECT_TYPE:
    case JS_BOUND_FUNCTION_TYPE:
      return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3);
    case JS_WEAK_MAP_TYPE:
    case JS_WEAK_SET_TYPE:
      return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3);
    case JS_ARRAY_BUFFER_TYPE:
      return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3);
    case JS_FUNCTION_TYPE:
      return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3);
    case ODDBALL_TYPE:
      return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3);
    case JS_PROXY_TYPE:
      return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3);
    case FOREIGN_TYPE:
      return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3);
    case MAP_TYPE:
      return Op::template apply<Map::BodyDescriptor>(p1, p2, p3);
    case CODE_TYPE:
      return Op::template apply<Code::BodyDescriptor>(p1, p2, p3);
    case CELL_TYPE:
      return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3);
    case PROPERTY_CELL_TYPE:
      return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3);
    case WEAK_CELL_TYPE:
      return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3);
    case SYMBOL_TYPE:
      return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3);
    case BYTECODE_ARRAY_TYPE:
      return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3);
    case SMALL_ORDERED_HASH_SET_TYPE:
      return Op::template apply<SmallOrderedHashSet::BodyDescriptor>(p1, p2,
                                                                     p3);
    case HEAP_NUMBER_TYPE:
    case MUTABLE_HEAP_NUMBER_TYPE:
    case FILLER_TYPE:
    case BYTE_ARRAY_TYPE:
    case FREE_SPACE_TYPE:
      return ReturnType();

#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
  case FIXED_##TYPE##_ARRAY_TYPE:                       \
    return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3);
      TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

    case SHARED_FUNCTION_INFO_TYPE: {
      return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3);
    }

#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
      STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
      if (type == ALLOCATION_SITE_TYPE) {
        return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3);
      } else {
        return Op::template apply<StructBodyDescriptor>(p1, p2, p3);
      }
    default:
      PrintF("Unknown type: %d\n", type);
      UNREACHABLE();
  }
}


template <typename ObjectVisitor>
void HeapObject::IterateFast(ObjectVisitor* v) {
  BodyDescriptorBase::IteratePointer(this, kMapOffset, v);
  IterateBodyFast(v);
}


template <typename ObjectVisitor>
void HeapObject::IterateBodyFast(ObjectVisitor* v) {
  Map* m = map();
  IterateBodyFast(m->instance_type(), SizeFromMap(m), v);
}


struct CallIterateBody {
  template <typename BodyDescriptor, typename ObjectVisitor>
  static void apply(HeapObject* obj, int object_size, ObjectVisitor* v) {
    BodyDescriptor::IterateBody(obj, object_size, v);
  }
};

template <typename ObjectVisitor>
void HeapObject::IterateBodyFast(InstanceType type, int object_size,
                                 ObjectVisitor* v) {
  BodyDescriptorApply<CallIterateBody, void>(type, this, object_size, v);
}
}  // namespace internal
}  // namespace v8

#endif  // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
