// Copyright 2012 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.

#include "src/codegen/assembler-inl.h"
#include "src/date/date.h"
#include "src/diagnostics/disasm.h"
#include "src/diagnostics/disassembler.h"
#include "src/heap/combined-heap.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/read-only-heap.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/init/bootstrapper.h"
#include "src/logging/counters.h"
#include "src/objects/allocation-site-inl.h"
#include "src/objects/arguments-inl.h"
#include "src/objects/bigint.h"
#include "src/objects/cell-inl.h"
#include "src/objects/data-handler-inl.h"
#include "src/objects/debug-objects-inl.h"
#include "src/objects/elements.h"
#include "src/objects/embedder-data-array-inl.h"
#include "src/objects/embedder-data-slot-inl.h"
#include "src/objects/feedback-cell-inl.h"
#include "src/objects/field-type.h"
#include "src/objects/foreign-inl.h"
#include "src/objects/free-space-inl.h"
#include "src/objects/function-kind.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/layout-descriptor.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/roots/roots.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-break-iterator-inl.h"
#include "src/objects/js-collator-inl.h"
#endif  // V8_INTL_SUPPORT
#include "src/objects/js-collection-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-date-time-format-inl.h"
#include "src/objects/js-display-names-inl.h"
#endif  // V8_INTL_SUPPORT
#include "src/objects/js-generator-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-list-format-inl.h"
#include "src/objects/js-locale-inl.h"
#include "src/objects/js-number-format-inl.h"
#include "src/objects/js-plural-rules-inl.h"
#endif  // V8_INTL_SUPPORT
#include "src/objects/js-regexp-inl.h"
#include "src/objects/js-regexp-string-iterator-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-relative-time-format-inl.h"
#include "src/objects/js-segment-iterator-inl.h"
#include "src/objects/js-segmenter-inl.h"
#include "src/objects/js-segments-inl.h"
#endif  // V8_INTL_SUPPORT
#include "src/objects/js-weak-refs-inl.h"
#include "src/objects/literal-objects-inl.h"
#include "src/objects/maybe-object.h"
#include "src/objects/microtask-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/oddball-inl.h"
#include "src/objects/promise-inl.h"
#include "src/objects/property-descriptor-object-inl.h"
#include "src/objects/stack-frame-info-inl.h"
#include "src/objects/struct-inl.h"
#include "src/objects/template-objects-inl.h"
#include "src/objects/transitions-inl.h"
#include "src/regexp/regexp.h"
#include "src/utils/ostreams.h"
#include "src/wasm/wasm-objects-inl.h"
#include "torque-generated/class-verifiers-tq.h"
#include "torque-generated/exported-class-definitions-tq-inl.h"
#include "torque-generated/internal-class-definitions-tq-inl.h"

namespace v8 {
namespace internal {

// Heap Verification Overview
// --------------------------
// - Each InstanceType has a separate XXXVerify method which checks an object's
//   integrity in isolation.
// - --verify-heap will iterate over all gc spaces and call ObjectVerify() on
//   every encountered tagged pointer.
// - Verification should be pushed down to the specific instance type if its
//   integrity is independent of an outer object.
// - In cases where the InstanceType is too genernic (e.g. FixedArray) the
//   XXXVerify of the outer method has to do recursive verification.
// - If the corresponding objects have inheritence the parent's Verify method
//   is called as well.
// - For any field containing pointes VerifyPointer(...) should be called.
//
// Caveats
// -------
// - Assume that any of the verify methods is incomplete!
// - Some integrity checks are only partially done due to objects being in
//   partially initialized states when a gc happens, for instance when outer
//   objects are allocted before inner ones.
//

#ifdef VERIFY_HEAP

#define USE_TORQUE_VERIFIER(Class)                                \
  void Class::Class##Verify(Isolate* isolate) {                   \
    TorqueGeneratedClassVerifiers::Class##Verify(*this, isolate); \
  }

void Object::ObjectVerify(Isolate* isolate) {
  RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kObjectVerify);
  if (IsSmi()) {
    Smi::cast(*this).SmiVerify(isolate);
  } else {
    HeapObject::cast(*this).HeapObjectVerify(isolate);
  }
  CHECK(!IsConstructor() || IsCallable());
}

void Object::VerifyPointer(Isolate* isolate, Object p) {
  if (p.IsHeapObject()) {
    HeapObject::VerifyHeapPointer(isolate, p);
  } else {
    CHECK(p.IsSmi());
  }
}

void MaybeObject::VerifyMaybeObjectPointer(Isolate* isolate, MaybeObject p) {
  HeapObject heap_object;
  if (p->GetHeapObject(&heap_object)) {
    HeapObject::VerifyHeapPointer(isolate, heap_object);
  } else {
    CHECK(p->IsSmi() || p->IsCleared());
  }
}

void Smi::SmiVerify(Isolate* isolate) {
  CHECK(IsSmi());
  CHECK(!IsCallable());
  CHECK(!IsConstructor());
}

void TaggedIndex::TaggedIndexVerify(Isolate* isolate) {
  CHECK(IsTaggedIndex());
}

void HeapObject::HeapObjectVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::HeapObjectVerify(*this, isolate);

  switch (map().instance_type()) {
#define STRING_TYPE_CASE(TYPE, size, name, CamelName) case TYPE:
    STRING_TYPE_LIST(STRING_TYPE_CASE)
#undef STRING_TYPE_CASE
    if (IsConsString()) {
      ConsString::cast(*this).ConsStringVerify(isolate);
    } else if (IsSlicedString()) {
      SlicedString::cast(*this).SlicedStringVerify(isolate);
    } else if (IsThinString()) {
      ThinString::cast(*this).ThinStringVerify(isolate);
    } else if (IsSeqString()) {
      SeqString::cast(*this).SeqStringVerify(isolate);
    } else if (IsExternalString()) {
      ExternalString::cast(*this).ExternalStringVerify(isolate);
    } else {
      String::cast(*this).StringVerify(isolate);
    }
    break;
    case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
      ObjectBoilerplateDescription::cast(*this)
          .ObjectBoilerplateDescriptionVerify(isolate);
      break;
    // FixedArray types
    case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
    case HASH_TABLE_TYPE:
    case ORDERED_HASH_MAP_TYPE:
    case ORDERED_HASH_SET_TYPE:
    case ORDERED_NAME_DICTIONARY_TYPE:
    case NAME_DICTIONARY_TYPE:
    case GLOBAL_DICTIONARY_TYPE:
    case NUMBER_DICTIONARY_TYPE:
    case SIMPLE_NUMBER_DICTIONARY_TYPE:
    case EPHEMERON_HASH_TABLE_TYPE:
    case FIXED_ARRAY_TYPE:
    case SCOPE_INFO_TYPE:
    case SCRIPT_CONTEXT_TABLE_TYPE:
      FixedArray::cast(*this).FixedArrayVerify(isolate);
      break;
    case AWAIT_CONTEXT_TYPE:
    case BLOCK_CONTEXT_TYPE:
    case CATCH_CONTEXT_TYPE:
    case DEBUG_EVALUATE_CONTEXT_TYPE:
    case EVAL_CONTEXT_TYPE:
    case FUNCTION_CONTEXT_TYPE:
    case MODULE_CONTEXT_TYPE:
    case SCRIPT_CONTEXT_TYPE:
    case WITH_CONTEXT_TYPE:
      Context::cast(*this).ContextVerify(isolate);
      break;
    case NATIVE_CONTEXT_TYPE:
      NativeContext::cast(*this).NativeContextVerify(isolate);
      break;
    case WEAK_FIXED_ARRAY_TYPE:
      WeakFixedArray::cast(*this).WeakFixedArrayVerify(isolate);
      break;
    case FEEDBACK_METADATA_TYPE:
      FeedbackMetadata::cast(*this).FeedbackMetadataVerify(isolate);
      break;
    case TRANSITION_ARRAY_TYPE:
      TransitionArray::cast(*this).TransitionArrayVerify(isolate);
      break;

    case CODE_TYPE:
      Code::cast(*this).CodeVerify(isolate);
      break;
    case JS_OBJECT_TYPE:
    case JS_ERROR_TYPE:
    case JS_API_OBJECT_TYPE:
    case JS_SPECIAL_API_OBJECT_TYPE:
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
      JSObject::cast(*this).JSObjectVerify(isolate);
      break;
    case WASM_INSTANCE_OBJECT_TYPE:
      WasmInstanceObject::cast(*this).WasmInstanceObjectVerify(isolate);
      break;
    case JS_GENERATOR_OBJECT_TYPE:
      JSGeneratorObject::cast(*this).JSGeneratorObjectVerify(isolate);
      break;
    case JS_SET_KEY_VALUE_ITERATOR_TYPE:
    case JS_SET_VALUE_ITERATOR_TYPE:
      JSSetIterator::cast(*this).JSSetIteratorVerify(isolate);
      break;
    case JS_MAP_KEY_ITERATOR_TYPE:
    case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
    case JS_MAP_VALUE_ITERATOR_TYPE:
      JSMapIterator::cast(*this).JSMapIteratorVerify(isolate);
      break;
    case FILLER_TYPE:
      break;
    case CODE_DATA_CONTAINER_TYPE:
      CodeDataContainer::cast(*this).CodeDataContainerVerify(isolate);
      break;

#define MAKE_TORQUE_CASE(Name, TYPE)         \
  case TYPE:                                 \
    Name::cast(*this).Name##Verify(isolate); \
    break;
      // Every class that has its fields defined in a .tq file and corresponds
      // to exactly one InstanceType value is included in the following list.
      TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
      TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
#undef MAKE_TORQUE_CASE

    case FOREIGN_TYPE:
      break;  // No interesting fields.

    case ALLOCATION_SITE_TYPE:
      AllocationSite::cast(*this).AllocationSiteVerify(isolate);
      break;

    case LOAD_HANDLER_TYPE:
      LoadHandler::cast(*this).LoadHandlerVerify(isolate);
      break;

    case STORE_HANDLER_TYPE:
      StoreHandler::cast(*this).StoreHandlerVerify(isolate);
      break;
  }
}

// static
void HeapObject::VerifyHeapPointer(Isolate* isolate, Object p) {
  CHECK(p.IsHeapObject());
  CHECK(IsValidHeapObject(isolate->heap(), HeapObject::cast(p)));
}

void Symbol::SymbolVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::SymbolVerify(*this, isolate);
  CHECK(HasHashCode());
  CHECK_GT(Hash(), 0);
  CHECK(description().IsUndefined(isolate) || description().IsString());
  CHECK_IMPLIES(IsPrivateName(), IsPrivate());
  CHECK_IMPLIES(IsPrivateBrand(), IsPrivateName());
}

void BytecodeArray::BytecodeArrayVerify(Isolate* isolate) {
  // TODO(oth): Walk bytecodes and immediate values to validate sanity.
  // - All bytecodes are known and well formed.
  // - Jumps must go to new instructions starts.
  // - No Illegal bytecodes.
  // - No consecutive sequences of prefix Wide / ExtraWide.
  CHECK(IsBytecodeArray(isolate));
  CHECK(constant_pool(isolate).IsFixedArray(isolate));
  VerifyHeapPointer(isolate, constant_pool(isolate));
  CHECK(synchronized_source_position_table(isolate).IsUndefined(isolate) ||
        synchronized_source_position_table(isolate).IsException(isolate) ||
        synchronized_source_position_table(isolate).IsByteArray(isolate));
  CHECK(handler_table(isolate).IsByteArray(isolate));
  for (int i = 0; i < constant_pool(isolate).length(); ++i) {
    // No ThinStrings in the constant pool.
    CHECK(!constant_pool(isolate).get(isolate, i).IsThinString(isolate));
  }
}

USE_TORQUE_VERIFIER(JSReceiver)

bool JSObject::ElementsAreSafeToExamine(const Isolate* isolate) const {
  // If a GC was caused while constructing this object, the elements
  // pointer may point to a one pointer filler map.
  return elements(isolate) !=
         GetReadOnlyRoots(isolate).one_pointer_filler_map();
}

namespace {

void VerifyJSObjectElements(Isolate* isolate, JSObject object) {
  // Only TypedArrays can have these specialized elements.
  if (object.IsJSTypedArray()) {
    // TODO(bmeurer,v8:4153): Fix CreateTypedArray to either not instantiate
    // the object or propertly initialize it on errors during construction.
    /* CHECK(object->HasTypedArrayElements()); */
    return;
  }
  CHECK(!object.elements().IsByteArray());

  if (object.HasDoubleElements()) {
    if (object.elements().length() > 0) {
      CHECK(object.elements().IsFixedDoubleArray());
    }
    return;
  }

  if (object.HasSloppyArgumentsElements()) {
    CHECK(object.elements().IsSloppyArgumentsElements());
    return;
  }

  FixedArray elements = FixedArray::cast(object.elements());
  if (object.HasSmiElements()) {
    // We might have a partially initialized backing store, in which case we
    // allow the hole + smi values.
    for (int i = 0; i < elements.length(); i++) {
      Object value = elements.get(i);
      CHECK(value.IsSmi() || value.IsTheHole(isolate));
    }
  } else if (object.HasObjectElements()) {
    for (int i = 0; i < elements.length(); i++) {
      Object element = elements.get(i);
      CHECK(!HasWeakHeapObjectTag(element));
    }
  }
}
}  // namespace

void JSObject::JSObjectVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSObjectVerify(*this, isolate);
  VerifyHeapPointer(isolate, elements());

  CHECK_IMPLIES(HasSloppyArgumentsElements(), IsJSArgumentsObject());
  if (HasFastProperties()) {
    int actual_unused_property_fields = map().GetInObjectProperties() +
                                        property_array().length() -
                                        map().NextFreePropertyIndex();
    if (map().UnusedPropertyFields() != actual_unused_property_fields) {
      // There are two reasons why this can happen:
      // - in the middle of StoreTransitionStub when the new extended backing
      //   store is already set into the object and the allocation of the
      //   HeapNumber triggers GC while the map isn't updated yet.
      // - deletion of the last property can leave additional backing store
      //   capacity behind.
      CHECK_GT(actual_unused_property_fields, map().UnusedPropertyFields());
      int delta = actual_unused_property_fields - map().UnusedPropertyFields();
      CHECK_EQ(0, delta % JSObject::kFieldsAdded);
    }
    DescriptorArray descriptors = map().instance_descriptors();
    bool is_transitionable_fast_elements_kind =
        IsTransitionableFastElementsKind(map().elements_kind());

    for (InternalIndex i : map().IterateOwnDescriptors()) {
      PropertyDetails details = descriptors.GetDetails(i);
      if (details.location() == kField) {
        DCHECK_EQ(kData, details.kind());
        Representation r = details.representation();
        FieldIndex index = FieldIndex::ForDescriptor(map(), i);
        if (IsUnboxedDoubleField(index)) {
          DCHECK(r.IsDouble());
          continue;
        }
        if (COMPRESS_POINTERS_BOOL && index.is_inobject()) {
          VerifyObjectField(isolate, index.offset());
        }
        Object value = RawFastPropertyAt(index);
        if (r.IsDouble()) DCHECK(value.IsHeapNumber());
        if (value.IsUninitialized(isolate)) continue;
        if (r.IsSmi()) DCHECK(value.IsSmi());
        if (r.IsHeapObject()) DCHECK(value.IsHeapObject());
        FieldType field_type = descriptors.GetFieldType(i);
        bool type_is_none = field_type.IsNone();
        bool type_is_any = field_type.IsAny();
        if (r.IsNone()) {
          CHECK(type_is_none);
        } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) {
          CHECK(!field_type.NowStable() || field_type.NowContains(value));
        }
        CHECK_IMPLIES(is_transitionable_fast_elements_kind,
                      Map::IsMostGeneralFieldType(r, field_type));
      }
    }

    if (map().EnumLength() != kInvalidEnumCacheSentinel) {
      EnumCache enum_cache = descriptors.enum_cache();
      FixedArray keys = enum_cache.keys();
      FixedArray indices = enum_cache.indices();
      CHECK_LE(map().EnumLength(), keys.length());
      CHECK_IMPLIES(indices != ReadOnlyRoots(isolate).empty_fixed_array(),
                    keys.length() == indices.length());
    }
  }

  // If a GC was caused while constructing this object, the elements
  // pointer may point to a one pointer filler map.
  if (ElementsAreSafeToExamine(isolate)) {
    CHECK_EQ((map().has_fast_smi_or_object_elements() ||
              map().has_any_nonextensible_elements() ||
              (elements() == GetReadOnlyRoots().empty_fixed_array()) ||
              HasFastStringWrapperElements()),
             (elements().map() == GetReadOnlyRoots().fixed_array_map() ||
              elements().map() == GetReadOnlyRoots().fixed_cow_array_map()));
    CHECK_EQ(map().has_fast_object_elements(), HasObjectElements());
    VerifyJSObjectElements(isolate, *this);
  }
}

void Map::MapVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::MapVerify(*this, isolate);
  Heap* heap = isolate->heap();
  CHECK(!ObjectInYoungGeneration(*this));
  CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
  CHECK(instance_size() == kVariableSizeSentinel ||
        (kTaggedSize <= instance_size() &&
         static_cast<size_t>(instance_size()) < heap->Capacity()));
  if (IsContextMap()) {
    CHECK(native_context().IsNativeContext());
  } else {
    if (GetBackPointer().IsUndefined(isolate)) {
      // Root maps must not have descriptors in the descriptor array that do not
      // belong to the map.
      CHECK_EQ(NumberOfOwnDescriptors(),
               instance_descriptors().number_of_descriptors());
    } else {
      // If there is a parent map it must be non-stable.
      Map parent = Map::cast(GetBackPointer());
      CHECK(!parent.is_stable());
      DescriptorArray descriptors = instance_descriptors();
      if (descriptors == parent.instance_descriptors()) {
        if (NumberOfOwnDescriptors() == parent.NumberOfOwnDescriptors() + 1) {
          // Descriptors sharing through property transitions takes over
          // ownership from the parent map.
          CHECK(!parent.owns_descriptors());
        } else {
          CHECK_EQ(NumberOfOwnDescriptors(), parent.NumberOfOwnDescriptors());
          // Descriptors sharing through special transitions properly takes over
          // ownership from the parent map unless it uses the canonical empty
          // descriptor array.
          if (descriptors != ReadOnlyRoots(isolate).empty_descriptor_array()) {
            CHECK_IMPLIES(owns_descriptors(), !parent.owns_descriptors());
            CHECK_IMPLIES(parent.owns_descriptors(), !owns_descriptors());
          }
        }
      }
    }
  }
  SLOW_DCHECK(instance_descriptors().IsSortedNoDuplicates());
  DisallowHeapAllocation no_gc;
  SLOW_DCHECK(
      TransitionsAccessor(isolate, *this, &no_gc).IsSortedNoDuplicates());
  SLOW_DCHECK(TransitionsAccessor(isolate, *this, &no_gc)
                  .IsConsistentWithBackPointers());
  SLOW_DCHECK(!FLAG_unbox_double_fields ||
              layout_descriptor().IsConsistentWithMap(*this));
  // Only JSFunction maps have has_prototype_slot() bit set and constructible
  // JSFunction objects must have prototype slot.
  CHECK_IMPLIES(has_prototype_slot(), instance_type() == JS_FUNCTION_TYPE);
  if (!may_have_interesting_symbols()) {
    CHECK(!has_named_interceptor());
    CHECK(!is_dictionary_map());
    CHECK(!is_access_check_needed());
    DescriptorArray const descriptors = instance_descriptors();
    for (InternalIndex i : IterateOwnDescriptors()) {
      CHECK(!descriptors.GetKey(i).IsInterestingSymbol());
    }
  }
  CHECK_IMPLIES(has_named_interceptor(), may_have_interesting_symbols());
  CHECK_IMPLIES(is_dictionary_map(), may_have_interesting_symbols());
  CHECK_IMPLIES(is_access_check_needed(), may_have_interesting_symbols());
  CHECK_IMPLIES(IsJSObjectMap() && !CanHaveFastTransitionableElementsKind(),
                IsDictionaryElementsKind(elements_kind()) ||
                    IsTerminalElementsKind(elements_kind()) ||
                    IsAnyHoleyNonextensibleElementsKind(elements_kind()));
  CHECK_IMPLIES(is_deprecated(), !is_stable());
  if (is_prototype_map()) {
    DCHECK(prototype_info() == Smi::zero() ||
           prototype_info().IsPrototypeInfo());
  }
}

void Map::DictionaryMapVerify(Isolate* isolate) {
  MapVerify(isolate);
  CHECK(is_dictionary_map());
  CHECK_EQ(kInvalidEnumCacheSentinel, EnumLength());
  CHECK_EQ(ReadOnlyRoots(isolate).empty_descriptor_array(),
           instance_descriptors());
  CHECK_EQ(0, UnusedPropertyFields());
  CHECK_EQ(Map::GetVisitorId(*this), visitor_id());
}

void EmbedderDataArray::EmbedderDataArrayVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::EmbedderDataArrayVerify(*this, isolate);
  EmbedderDataSlot start(*this, 0);
  EmbedderDataSlot end(*this, length());
  for (EmbedderDataSlot slot = start; slot < end; ++slot) {
    Object e = slot.load_tagged();
    Object::VerifyPointer(isolate, e);
  }
}

void WeakFixedArray::WeakFixedArrayVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::WeakFixedArrayVerify(*this, isolate);
  for (int i = 0; i < length(); i++) {
    MaybeObject::VerifyMaybeObjectPointer(isolate, Get(i));
  }
}

void PropertyArray::PropertyArrayVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::PropertyArrayVerify(*this, isolate);
  if (length() == 0) {
    CHECK_EQ(*this, ReadOnlyRoots(isolate).empty_property_array());
    return;
  }
  // There are no empty PropertyArrays.
  CHECK_LT(0, length());
  for (int i = 0; i < length(); i++) {
    Object e = get(i);
    Object::VerifyPointer(isolate, e);
  }
}

void FixedDoubleArray::FixedDoubleArrayVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::FixedDoubleArrayVerify(*this, isolate);
  for (int i = 0; i < length(); i++) {
    if (!is_the_hole(i)) {
      uint64_t value = get_representation(i);
      uint64_t unexpected =
          bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN()) &
          uint64_t{0x7FF8000000000000};
      // Create implementation specific sNaN by inverting relevant bit.
      unexpected ^= uint64_t{0x0008000000000000};
      CHECK((value & uint64_t{0x7FF8000000000000}) != unexpected ||
            (value & uint64_t{0x0007FFFFFFFFFFFF}) == uint64_t{0});
    }
  }
}

void Context::ContextVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::ContextVerify(*this, isolate);
  for (int i = 0; i < length(); i++) {
    VerifyObjectField(isolate, OffsetOfElementAt(i));
  }
}

void NativeContext::NativeContextVerify(Isolate* isolate) {
  ContextVerify(isolate);
  CHECK_EQ(length(), NativeContext::NATIVE_CONTEXT_SLOTS);
  CHECK_EQ(kVariableSizeSentinel, map().instance_size());
}

void FeedbackMetadata::FeedbackMetadataVerify(Isolate* isolate) {
  if (slot_count() == 0 && closure_feedback_cell_count() == 0) {
    CHECK_EQ(ReadOnlyRoots(isolate).empty_feedback_metadata(), *this);
  } else {
    FeedbackMetadataIterator iter(*this);
    while (iter.HasNext()) {
      iter.Next();
      FeedbackSlotKind kind = iter.kind();
      CHECK_NE(FeedbackSlotKind::kInvalid, kind);
      CHECK_GT(FeedbackSlotKind::kKindsNumber, kind);
    }
  }
}

void DescriptorArray::DescriptorArrayVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::DescriptorArrayVerify(*this, isolate);
  if (number_of_all_descriptors() == 0) {
    CHECK_EQ(ReadOnlyRoots(isolate).empty_descriptor_array(), *this);
    CHECK_EQ(0, number_of_all_descriptors());
    CHECK_EQ(0, number_of_descriptors());
    CHECK_EQ(ReadOnlyRoots(isolate).empty_enum_cache(), enum_cache());
  } else {
    CHECK_LT(0, number_of_all_descriptors());
    CHECK_LE(number_of_descriptors(), number_of_all_descriptors());

    // Check that properties with private symbols names are non-enumerable, and
    // that fields are in order.
    int expected_field_index = 0;
    for (InternalIndex descriptor :
         InternalIndex::Range(number_of_descriptors())) {
      Object key = *(GetDescriptorSlot(descriptor.as_int()) + kEntryKeyIndex);
      // number_of_descriptors() may be out of sync with the actual descriptors
      // written during descriptor array construction.
      if (key.IsUndefined(isolate)) continue;
      PropertyDetails details = GetDetails(descriptor);
      if (Name::cast(key).IsPrivate()) {
        CHECK_NE(details.attributes() & DONT_ENUM, 0);
      }
      MaybeObject value = GetValue(descriptor);
      HeapObject heap_object;
      if (details.location() == kField) {
        CHECK_EQ(details.field_index(), expected_field_index);
        CHECK(
            value == MaybeObject::FromObject(FieldType::None()) ||
            value == MaybeObject::FromObject(FieldType::Any()) ||
            value->IsCleared() ||
            (value->GetHeapObjectIfWeak(&heap_object) && heap_object.IsMap()));
        expected_field_index += details.field_width_in_words();
      } else {
        CHECK(!value->IsWeakOrCleared());
        CHECK(!value->cast<Object>().IsMap());
      }
    }
  }
}

void TransitionArray::TransitionArrayVerify(Isolate* isolate) {
  WeakFixedArrayVerify(isolate);
  CHECK_LE(LengthFor(number_of_transitions()), length());
}

namespace {
void SloppyArgumentsElementsVerify(Isolate* isolate,
                                   SloppyArgumentsElements elements,
                                   JSObject holder) {
  elements.SloppyArgumentsElementsVerify(isolate);
  ElementsKind kind = holder.GetElementsKind();
  bool is_fast = kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
  Context context_object = elements.context();
  FixedArray arg_elements = elements.arguments();
  if (arg_elements.length() == 0) {
    CHECK(arg_elements == ReadOnlyRoots(isolate).empty_fixed_array());
    return;
  }
  ElementsAccessor* accessor;
  if (is_fast) {
    accessor = ElementsAccessor::ForKind(HOLEY_ELEMENTS);
  } else {
    accessor = ElementsAccessor::ForKind(DICTIONARY_ELEMENTS);
  }
  int nofMappedParameters = 0;
  int maxMappedIndex = 0;
  for (int i = 0; i < nofMappedParameters; i++) {
    // Verify that each context-mapped argument is either the hole or a valid
    // Smi within context length range.
    Object mapped = elements.mapped_entries(i);
    if (mapped.IsTheHole(isolate)) {
      // Slow sloppy arguments can be holey.
      if (!is_fast) continue;
      // Fast sloppy arguments elements are never holey. Either the element is
      // context-mapped or present in the arguments elements.
      CHECK(accessor->HasElement(holder, i, arg_elements));
      continue;
    }
    int mappedIndex = Smi::ToInt(mapped);
    nofMappedParameters++;
    CHECK_LE(maxMappedIndex, mappedIndex);
    maxMappedIndex = mappedIndex;
    Object value = context_object.get(mappedIndex);
    CHECK(value.IsObject());
    // None of the context-mapped entries should exist in the arguments
    // elements.
    CHECK(!accessor->HasElement(holder, i, arg_elements));
  }
  CHECK_LE(nofMappedParameters, context_object.length());
  CHECK_LE(nofMappedParameters, arg_elements.length());
  CHECK_LE(maxMappedIndex, context_object.length());
  CHECK_LE(maxMappedIndex, arg_elements.length());
}
}  // namespace

void JSArgumentsObject::JSArgumentsObjectVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSArgumentsObjectVerify(*this, isolate);
  if (IsSloppyArgumentsElementsKind(GetElementsKind())) {
    SloppyArgumentsElementsVerify(
        isolate, SloppyArgumentsElements::cast(elements()), *this);
  }
  if (isolate->IsInAnyContext(map(), Context::SLOPPY_ARGUMENTS_MAP_INDEX) ||
      isolate->IsInAnyContext(map(),
                              Context::SLOW_ALIASED_ARGUMENTS_MAP_INDEX) ||
      isolate->IsInAnyContext(map(),
                              Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX)) {
    VerifyObjectField(isolate, JSSloppyArgumentsObject::kLengthOffset);
    VerifyObjectField(isolate, JSSloppyArgumentsObject::kCalleeOffset);
  } else if (isolate->IsInAnyContext(map(),
                                     Context::STRICT_ARGUMENTS_MAP_INDEX)) {
    VerifyObjectField(isolate, JSStrictArgumentsObject::kLengthOffset);
  }
}

void JSAsyncFunctionObject::JSAsyncFunctionObjectVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSAsyncFunctionObjectVerify(*this, isolate);
}

void JSAsyncGeneratorObject::JSAsyncGeneratorObjectVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSAsyncGeneratorObjectVerify(*this, isolate);
}

void JSDate::JSDateVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSDateVerify(*this, isolate);

  if (month().IsSmi()) {
    int month = Smi::ToInt(this->month());
    CHECK(0 <= month && month <= 11);
  }
  if (day().IsSmi()) {
    int day = Smi::ToInt(this->day());
    CHECK(1 <= day && day <= 31);
  }
  if (hour().IsSmi()) {
    int hour = Smi::ToInt(this->hour());
    CHECK(0 <= hour && hour <= 23);
  }
  if (min().IsSmi()) {
    int min = Smi::ToInt(this->min());
    CHECK(0 <= min && min <= 59);
  }
  if (sec().IsSmi()) {
    int sec = Smi::ToInt(this->sec());
    CHECK(0 <= sec && sec <= 59);
  }
  if (weekday().IsSmi()) {
    int weekday = Smi::ToInt(this->weekday());
    CHECK(0 <= weekday && weekday <= 6);
  }
  if (cache_stamp().IsSmi()) {
    CHECK(Smi::ToInt(cache_stamp()) <=
          Smi::ToInt(isolate->date_cache()->stamp()));
  }
}

USE_TORQUE_VERIFIER(JSMessageObject)

void String::StringVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::StringVerify(*this, isolate);
  CHECK(length() >= 0 && length() <= Smi::kMaxValue);
  CHECK_IMPLIES(length() == 0, *this == ReadOnlyRoots(isolate).empty_string());
  if (IsInternalizedString()) {
    CHECK(!ObjectInYoungGeneration(*this));
  }
}

void ConsString::ConsStringVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::ConsStringVerify(*this, isolate);
  CHECK_GE(this->length(), ConsString::kMinLength);
  CHECK(this->length() == this->first().length() + this->second().length());
  if (this->IsFlat()) {
    // A flat cons can only be created by String::SlowFlatten.
    // Afterwards, the first part may be externalized or internalized.
    CHECK(this->first().IsSeqString() || this->first().IsExternalString() ||
          this->first().IsThinString());
  }
}

void ThinString::ThinStringVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::ThinStringVerify(*this, isolate);
  CHECK(this->actual().IsInternalizedString());
  CHECK(this->actual().IsSeqString() || this->actual().IsExternalString());
}

void SlicedString::SlicedStringVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::SlicedStringVerify(*this, isolate);
  CHECK(!this->parent().IsConsString());
  CHECK(!this->parent().IsSlicedString());
  CHECK_GE(this->length(), SlicedString::kMinLength);
}

USE_TORQUE_VERIFIER(ExternalString)

void JSBoundFunction::JSBoundFunctionVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSBoundFunctionVerify(*this, isolate);
  CHECK(IsCallable());
  CHECK_EQ(IsConstructor(), bound_target_function().IsConstructor());
}

void JSFunction::JSFunctionVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSFunctionVerify(*this, isolate);
  CHECK(code().IsCode());
  CHECK(map().is_callable());
  Handle<JSFunction> function(*this, isolate);
  LookupIterator it(isolate, function, isolate->factory()->prototype_string(),
                    LookupIterator::OWN_SKIP_INTERCEPTOR);
  if (has_prototype_slot()) {
    VerifyObjectField(isolate, kPrototypeOrInitialMapOffset);
  }

  if (has_prototype_property()) {
    CHECK(it.IsFound());
    CHECK_EQ(LookupIterator::ACCESSOR, it.state());
    CHECK(it.GetAccessors()->IsAccessorInfo());
  } else {
    CHECK(!it.IsFound() || it.state() != LookupIterator::ACCESSOR ||
          !it.GetAccessors()->IsAccessorInfo());
  }
}

void SharedFunctionInfo::SharedFunctionInfoVerify(Isolate* isolate) {
  // TODO(leszeks): Add a TorqueGeneratedClassVerifier for LocalIsolate.
  TorqueGeneratedClassVerifiers::SharedFunctionInfoVerify(*this, isolate);
  this->SharedFunctionInfoVerify(ReadOnlyRoots(isolate));
}

void SharedFunctionInfo::SharedFunctionInfoVerify(LocalIsolate* isolate) {
  this->SharedFunctionInfoVerify(ReadOnlyRoots(isolate));
}

void SharedFunctionInfo::SharedFunctionInfoVerify(ReadOnlyRoots roots) {
  Object value = name_or_scope_info();
  if (value.IsScopeInfo()) {
    CHECK_LT(0, ScopeInfo::cast(value).length());
    CHECK_NE(value, roots.empty_scope_info());
  }

  CHECK(HasWasmExportedFunctionData() || IsApiFunction() ||
        HasBytecodeArray() || HasAsmWasmData() || HasBuiltinId() ||
        HasUncompiledDataWithPreparseData() ||
        HasUncompiledDataWithoutPreparseData() || HasWasmJSFunctionData() ||
        HasWasmCapiFunctionData());

  CHECK(script_or_debug_info().IsUndefined(roots) ||
        script_or_debug_info().IsScript() || HasDebugInfo());

  if (!is_compiled()) {
    CHECK(!HasFeedbackMetadata());
    CHECK(outer_scope_info().IsScopeInfo() ||
          outer_scope_info().IsTheHole(roots));
  } else if (HasBytecodeArray() && HasFeedbackMetadata()) {
    CHECK(feedback_metadata().IsFeedbackMetadata());
  }

  int expected_map_index = Context::FunctionMapIndex(
      language_mode(), kind(), HasSharedName(), needs_home_object());
  CHECK_EQ(expected_map_index, function_map_index());

  if (scope_info().length() > 0) {
    ScopeInfo info = scope_info();
    CHECK(kind() == info.function_kind());
    CHECK_EQ(internal::IsModule(kind()), info.scope_type() == MODULE_SCOPE);
  }

  if (IsApiFunction()) {
    CHECK(construct_as_builtin());
  } else if (!HasBuiltinId()) {
    CHECK(!construct_as_builtin());
  } else {
    int id = builtin_id();
    if (id != Builtins::kCompileLazy && id != Builtins::kEmptyFunction) {
      CHECK(construct_as_builtin());
    } else {
      CHECK(!construct_as_builtin());
    }
  }

  // At this point we only support skipping arguments adaptor frames
  // for strict mode functions (see https://crbug.com/v8/8895).
  CHECK_IMPLIES(is_safe_to_skip_arguments_adaptor(),
                language_mode() == LanguageMode::kStrict);
}

void JSGlobalProxy::JSGlobalProxyVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSGlobalProxyVerify(*this, isolate);
  CHECK(map().is_access_check_needed());
  // Make sure that this object has no properties, elements.
  CHECK_EQ(0, FixedArray::cast(elements()).length());
}

void JSGlobalObject::JSGlobalObjectVerify(Isolate* isolate) {
  CHECK(IsJSGlobalObject());
  // Do not check the dummy global object for the builtins.
  if (global_dictionary().NumberOfElements() == 0 && elements().length() == 0) {
    return;
  }
  JSObjectVerify(isolate);
}

void Oddball::OddballVerify(Isolate* isolate) {
  TorqueGeneratedOddball::OddballVerify(isolate);
  Heap* heap = isolate->heap();
  Object number = to_number();
  if (number.IsHeapObject()) {
    CHECK(number == ReadOnlyRoots(heap).nan_value() ||
          number == ReadOnlyRoots(heap).hole_nan_value());
  } else {
    CHECK(number.IsSmi());
    int value = Smi::ToInt(number);
    // Hidden oddballs have negative smis.
    const int kLeastHiddenOddballNumber = -7;
    CHECK_LE(value, 1);
    CHECK_GE(value, kLeastHiddenOddballNumber);
  }

  ReadOnlyRoots roots(heap);
  if (map() == roots.undefined_map()) {
    CHECK(*this == roots.undefined_value());
  } else if (map() == roots.the_hole_map()) {
    CHECK(*this == roots.the_hole_value());
  } else if (map() == roots.null_map()) {
    CHECK(*this == roots.null_value());
  } else if (map() == roots.boolean_map()) {
    CHECK(*this == roots.true_value() || *this == roots.false_value());
  } else if (map() == roots.uninitialized_map()) {
    CHECK(*this == roots.uninitialized_value());
  } else if (map() == roots.arguments_marker_map()) {
    CHECK(*this == roots.arguments_marker());
  } else if (map() == roots.termination_exception_map()) {
    CHECK(*this == roots.termination_exception());
  } else if (map() == roots.exception_map()) {
    CHECK(*this == roots.exception());
  } else if (map() == roots.optimized_out_map()) {
    CHECK(*this == roots.optimized_out());
  } else if (map() == roots.stale_register_map()) {
    CHECK(*this == roots.stale_register());
  } else if (map() == roots.self_reference_marker_map()) {
    // Multiple instances of this oddball may exist at once.
    CHECK_EQ(kind(), Oddball::kSelfReferenceMarker);
  } else if (map() == roots.basic_block_counters_marker_map()) {
    CHECK(*this == roots.basic_block_counters_marker());
  } else {
    UNREACHABLE();
  }
}

USE_TORQUE_VERIFIER(PropertyCell)

void CodeDataContainer::CodeDataContainerVerify(Isolate* isolate) {
  CHECK(IsCodeDataContainer());
  VerifyObjectField(isolate, kNextCodeLinkOffset);
  CHECK(next_code_link().IsCode() || next_code_link().IsUndefined(isolate));
}

void Code::CodeVerify(Isolate* isolate) {
  CHECK_IMPLIES(
      has_safepoint_table(),
      IsAligned(safepoint_table_offset(), static_cast<unsigned>(kIntSize)));
  CHECK_LE(safepoint_table_offset(), handler_table_offset());
  CHECK_LE(handler_table_offset(), constant_pool_offset());
  CHECK_LE(constant_pool_offset(), code_comments_offset());
  CHECK_LE(code_comments_offset(), InstructionSize());
  CHECK_IMPLIES(!ReadOnlyHeap::Contains(*this),
                IsAligned(raw_instruction_start(), kCodeAlignment));
  // TODO(delphick): Refactor Factory::CodeBuilder::BuildInternal, so that the
  // following CHECK works builtin trampolines. It currently fails because
  // CodeVerify is called halfway through constructing the trampoline and so not
  // everything is set up.
  // CHECK_EQ(ReadOnlyHeap::Contains(*this), !IsExecutable());
  relocation_info().ObjectVerify(isolate);
  CHECK(Code::SizeFor(body_size()) <= kMaxRegularHeapObjectSize ||
        isolate->heap()->InSpace(*this, CODE_LO_SPACE));
  Address last_gc_pc = kNullAddress;

  for (RelocIterator it(*this); !it.done(); it.next()) {
    it.rinfo()->Verify(isolate);
    // Ensure that GC will not iterate twice over the same pointer.
    if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
      CHECK(it.rinfo()->pc() != last_gc_pc);
      last_gc_pc = it.rinfo()->pc();
    }
  }
}

void JSArray::JSArrayVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSArrayVerify(*this, isolate);
  // If a GC was caused while constructing this array, the elements
  // pointer may point to a one pointer filler map.
  if (!ElementsAreSafeToExamine(isolate)) return;
  if (elements().IsUndefined(isolate)) return;
  CHECK(elements().IsFixedArray() || elements().IsFixedDoubleArray());
  if (elements().length() == 0) {
    CHECK_EQ(elements(), ReadOnlyRoots(isolate).empty_fixed_array());
  }
  // Verify that the length and the elements backing store are in sync.
  if (length().IsSmi() &&
      (HasFastElements() || HasAnyNonextensibleElements())) {
    if (elements().length() > 0) {
      CHECK_IMPLIES(HasDoubleElements(), elements().IsFixedDoubleArray());
      CHECK_IMPLIES(HasSmiOrObjectElements() || HasAnyNonextensibleElements(),
                    elements().IsFixedArray());
    }
    int size = Smi::ToInt(length());
    // Holey / Packed backing stores might have slack or might have not been
    // properly initialized yet.
    CHECK(size <= elements().length() ||
          elements() == ReadOnlyRoots(isolate).empty_fixed_array());
  } else {
    CHECK(HasDictionaryElements());
    uint32_t array_length;
    CHECK(length().ToArrayLength(&array_length));
    if (array_length == 0xFFFFFFFF) {
      CHECK(length().ToArrayLength(&array_length));
    }
    if (array_length != 0) {
      NumberDictionary dict = NumberDictionary::cast(elements());
      // The dictionary can never have more elements than the array length + 1.
      // If the backing store grows the verification might be triggered with
      // the old length in place.
      uint32_t nof_elements = static_cast<uint32_t>(dict.NumberOfElements());
      if (nof_elements != 0) nof_elements--;
      CHECK_LE(nof_elements, array_length);
    }
  }
}

void JSSet::JSSetVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSSetVerify(*this, isolate);
  CHECK(table().IsOrderedHashSet() || table().IsUndefined(isolate));
  // TODO(arv): Verify OrderedHashTable too.
}

void JSMap::JSMapVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSMapVerify(*this, isolate);
  CHECK(table().IsOrderedHashMap() || table().IsUndefined(isolate));
  // TODO(arv): Verify OrderedHashTable too.
}

void JSSetIterator::JSSetIteratorVerify(Isolate* isolate) {
  CHECK(IsJSSetIterator());
  JSCollectionIteratorVerify(isolate);
  CHECK(table().IsOrderedHashSet());
  CHECK(index().IsSmi());
}

void JSMapIterator::JSMapIteratorVerify(Isolate* isolate) {
  CHECK(IsJSMapIterator());
  JSCollectionIteratorVerify(isolate);
  CHECK(table().IsOrderedHashMap());
  CHECK(index().IsSmi());
}

void WeakCell::WeakCellVerify(Isolate* isolate) {
  CHECK(IsWeakCell());

  CHECK(target().IsJSReceiver() || target().IsUndefined(isolate));

  CHECK(prev().IsWeakCell() || prev().IsUndefined(isolate));
  if (prev().IsWeakCell()) {
    CHECK_EQ(WeakCell::cast(prev()).next(), *this);
  }

  CHECK(next().IsWeakCell() || next().IsUndefined(isolate));
  if (next().IsWeakCell()) {
    CHECK_EQ(WeakCell::cast(next()).prev(), *this);
  }

  CHECK_IMPLIES(unregister_token().IsUndefined(isolate),
                key_list_prev().IsUndefined(isolate));
  CHECK_IMPLIES(unregister_token().IsUndefined(isolate),
                key_list_next().IsUndefined(isolate));

  CHECK(key_list_prev().IsWeakCell() || key_list_prev().IsUndefined(isolate));

  CHECK(key_list_next().IsWeakCell() || key_list_next().IsUndefined(isolate));

  CHECK(finalization_registry().IsUndefined(isolate) ||
        finalization_registry().IsJSFinalizationRegistry());
}

void JSWeakRef::JSWeakRefVerify(Isolate* isolate) {
  CHECK(IsJSWeakRef());
  JSObjectVerify(isolate);
  CHECK(target().IsUndefined(isolate) || target().IsJSReceiver());
}

void JSFinalizationRegistry::JSFinalizationRegistryVerify(Isolate* isolate) {
  CHECK(IsJSFinalizationRegistry());
  JSObjectVerify(isolate);
  VerifyHeapPointer(isolate, cleanup());
  CHECK(active_cells().IsUndefined(isolate) || active_cells().IsWeakCell());
  if (active_cells().IsWeakCell()) {
    CHECK(WeakCell::cast(active_cells()).prev().IsUndefined(isolate));
  }
  CHECK(cleared_cells().IsUndefined(isolate) || cleared_cells().IsWeakCell());
  if (cleared_cells().IsWeakCell()) {
    CHECK(WeakCell::cast(cleared_cells()).prev().IsUndefined(isolate));
  }
  CHECK(next_dirty().IsUndefined(isolate) ||
        next_dirty().IsJSFinalizationRegistry());
}

void JSWeakMap::JSWeakMapVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSWeakMapVerify(*this, isolate);
  CHECK(table().IsEphemeronHashTable() || table().IsUndefined(isolate));
}

void JSArrayIterator::JSArrayIteratorVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSArrayIteratorVerify(*this, isolate);

  CHECK_GE(next_index().Number(), 0);
  CHECK_LE(next_index().Number(), kMaxSafeInteger);

  if (iterated_object().IsJSTypedArray()) {
    // JSTypedArray::length is limited to Smi range.
    CHECK(next_index().IsSmi());
    CHECK_LE(next_index().Number(), Smi::kMaxValue);
  } else if (iterated_object().IsJSArray()) {
    // JSArray::length is limited to Uint32 range.
    CHECK_LE(next_index().Number(), kMaxUInt32);
  }
}

void JSStringIterator::JSStringIteratorVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSStringIteratorVerify(*this, isolate);
  CHECK_GE(index(), 0);
  CHECK_LE(index(), String::kMaxLength);
}

void JSWeakSet::JSWeakSetVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSWeakSetVerify(*this, isolate);
  CHECK(table().IsEphemeronHashTable() || table().IsUndefined(isolate));
}

void CallableTask::CallableTaskVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::CallableTaskVerify(*this, isolate);
  CHECK(callable().IsCallable());
}

void JSPromise::JSPromiseVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSPromiseVerify(*this, isolate);
  if (status() == Promise::kPending) {
    CHECK(reactions().IsSmi() || reactions().IsPromiseReaction());
  }
}

template <typename Derived>
void SmallOrderedHashTable<Derived>::SmallOrderedHashTableVerify(
    Isolate* isolate) {
  CHECK(IsSmallOrderedHashTable());

  int capacity = Capacity();
  CHECK_GE(capacity, kMinCapacity);
  CHECK_LE(capacity, kMaxCapacity);

  for (int entry = 0; entry < NumberOfBuckets(); entry++) {
    int bucket = GetFirstEntry(entry);
    if (bucket == kNotFound) continue;
    CHECK_GE(bucket, 0);
    CHECK_LE(bucket, capacity);
  }

  for (int entry = 0; entry < NumberOfElements(); entry++) {
    int chain = GetNextEntry(entry);
    if (chain == kNotFound) continue;
    CHECK_GE(chain, 0);
    CHECK_LE(chain, capacity);
  }

  for (int entry = 0; entry < NumberOfElements(); entry++) {
    for (int offset = 0; offset < Derived::kEntrySize; offset++) {
      Object val = GetDataEntry(entry, offset);
      VerifyPointer(isolate, val);
    }
  }

  for (int entry = NumberOfElements() + NumberOfDeletedElements();
       entry < Capacity(); entry++) {
    for (int offset = 0; offset < Derived::kEntrySize; offset++) {
      Object val = GetDataEntry(entry, offset);
      CHECK(val.IsTheHole(isolate));
    }
  }
}
void SmallOrderedHashMap::SmallOrderedHashMapVerify(Isolate* isolate) {
  SmallOrderedHashTable<SmallOrderedHashMap>::SmallOrderedHashTableVerify(
      isolate);
  for (int entry = NumberOfElements(); entry < NumberOfDeletedElements();
       entry++) {
    for (int offset = 0; offset < kEntrySize; offset++) {
      Object val = GetDataEntry(entry, offset);
      CHECK(val.IsTheHole(isolate));
    }
  }
}

void SmallOrderedHashSet::SmallOrderedHashSetVerify(Isolate* isolate) {
  SmallOrderedHashTable<SmallOrderedHashSet>::SmallOrderedHashTableVerify(
      isolate);
  for (int entry = NumberOfElements(); entry < NumberOfDeletedElements();
       entry++) {
    for (int offset = 0; offset < kEntrySize; offset++) {
      Object val = GetDataEntry(entry, offset);
      CHECK(val.IsTheHole(isolate));
    }
  }
}

void SmallOrderedNameDictionary::SmallOrderedNameDictionaryVerify(
    Isolate* isolate) {
  SmallOrderedHashTable<
      SmallOrderedNameDictionary>::SmallOrderedHashTableVerify(isolate);
  for (int entry = NumberOfElements(); entry < NumberOfDeletedElements();
       entry++) {
    for (int offset = 0; offset < kEntrySize; offset++) {
      Object val = GetDataEntry(entry, offset);
      CHECK(val.IsTheHole(isolate) ||
            (PropertyDetails::Empty().AsSmi() == Smi::cast(val)));
    }
  }
}

void JSRegExp::JSRegExpVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSRegExpVerify(*this, isolate);
  switch (TypeTag()) {
    case JSRegExp::ATOM: {
      FixedArray arr = FixedArray::cast(data());
      CHECK(arr.get(JSRegExp::kAtomPatternIndex).IsString());
      break;
    }
    case JSRegExp::EXPERIMENTAL: {
      FixedArray arr = FixedArray::cast(data());
      Smi uninitialized = Smi::FromInt(JSRegExp::kUninitializedValue);

      Object latin1_code = arr.get(JSRegExp::kIrregexpLatin1CodeIndex);
      Object uc16_code = arr.get(JSRegExp::kIrregexpUC16CodeIndex);
      Object latin1_bytecode = arr.get(JSRegExp::kIrregexpLatin1BytecodeIndex);
      Object uc16_bytecode = arr.get(JSRegExp::kIrregexpUC16BytecodeIndex);

      bool is_compiled = latin1_code.IsCode();
      if (is_compiled) {
        CHECK_EQ(Code::cast(latin1_code).builtin_index(),
                 Builtins::kRegExpExperimentalTrampoline);
        CHECK_EQ(uc16_code, latin1_code);

        CHECK(latin1_bytecode.IsByteArray());
        CHECK_EQ(uc16_bytecode, latin1_bytecode);
      } else {
        CHECK_EQ(latin1_code, uninitialized);
        CHECK_EQ(uc16_code, uninitialized);

        CHECK_EQ(latin1_bytecode, uninitialized);
        CHECK_EQ(uc16_bytecode, uninitialized);
      }

      CHECK_EQ(arr.get(JSRegExp::kIrregexpMaxRegisterCountIndex),
               uninitialized);
      CHECK(arr.get(JSRegExp::kIrregexpCaptureCountIndex).IsSmi());
      CHECK_GE(Smi::ToInt(arr.get(JSRegExp::kIrregexpCaptureCountIndex)), 0);
      CHECK_EQ(arr.get(JSRegExp::kIrregexpTicksUntilTierUpIndex),
               uninitialized);
      CHECK_EQ(arr.get(JSRegExp::kIrregexpBacktrackLimit), uninitialized);
      break;
    }
    case JSRegExp::IRREGEXP: {
      bool can_be_interpreted = RegExp::CanGenerateBytecode();

      FixedArray arr = FixedArray::cast(data());
      Object one_byte_data = arr.get(JSRegExp::kIrregexpLatin1CodeIndex);
      // Smi : Not compiled yet (-1).
      // Code: Compiled irregexp code or trampoline to the interpreter.
      CHECK((one_byte_data.IsSmi() &&
             Smi::ToInt(one_byte_data) == JSRegExp::kUninitializedValue) ||
            one_byte_data.IsCode());
      Object uc16_data = arr.get(JSRegExp::kIrregexpUC16CodeIndex);
      CHECK((uc16_data.IsSmi() &&
             Smi::ToInt(uc16_data) == JSRegExp::kUninitializedValue) ||
            uc16_data.IsCode());

      Object one_byte_bytecode =
          arr.get(JSRegExp::kIrregexpLatin1BytecodeIndex);
      // Smi : Not compiled yet (-1).
      // ByteArray: Bytecode to interpret regexp.
      CHECK((one_byte_bytecode.IsSmi() &&
             Smi::ToInt(one_byte_bytecode) == JSRegExp::kUninitializedValue) ||
            (can_be_interpreted && one_byte_bytecode.IsByteArray()));
      Object uc16_bytecode = arr.get(JSRegExp::kIrregexpUC16BytecodeIndex);
      CHECK((uc16_bytecode.IsSmi() &&
             Smi::ToInt(uc16_bytecode) == JSRegExp::kUninitializedValue) ||
            (can_be_interpreted && uc16_bytecode.IsByteArray()));

      CHECK_IMPLIES(one_byte_data.IsSmi(), one_byte_bytecode.IsSmi());
      CHECK_IMPLIES(uc16_data.IsSmi(), uc16_bytecode.IsSmi());

      CHECK(arr.get(JSRegExp::kIrregexpCaptureCountIndex).IsSmi());
      CHECK_GE(Smi::ToInt(arr.get(JSRegExp::kIrregexpCaptureCountIndex)), 0);
      CHECK(arr.get(JSRegExp::kIrregexpMaxRegisterCountIndex).IsSmi());
      CHECK(arr.get(JSRegExp::kIrregexpTicksUntilTierUpIndex).IsSmi());
      CHECK(arr.get(JSRegExp::kIrregexpBacktrackLimit).IsSmi());
      break;
    }
    default:
      CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag());
      CHECK(data().IsUndefined(isolate));
      break;
  }
}

void JSProxy::JSProxyVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSProxyVerify(*this, isolate);
  CHECK(map().GetConstructor().IsJSFunction());
  if (!IsRevoked()) {
    CHECK_EQ(target().IsCallable(), map().is_callable());
    CHECK_EQ(target().IsConstructor(), map().is_constructor());
  }
  CHECK(map().prototype().IsNull(isolate));
  // There should be no properties on a Proxy.
  CHECK_EQ(0, map().NumberOfOwnDescriptors());
}

void JSArrayBuffer::JSArrayBufferVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSArrayBufferVerify(*this, isolate);
  if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
    CHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
    CHECK_EQ(0,
             *reinterpret_cast<uint32_t*>(address() + kOptionalPaddingOffset));
  }
}

void JSArrayBufferView::JSArrayBufferViewVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSArrayBufferViewVerify(*this, isolate);
  CHECK_LE(byte_length(), JSArrayBuffer::kMaxByteLength);
  CHECK_LE(byte_offset(), JSArrayBuffer::kMaxByteLength);
}

void JSTypedArray::JSTypedArrayVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSTypedArrayVerify(*this, isolate);
  CHECK_LE(length(), JSTypedArray::kMaxLength);
}

void JSDataView::JSDataViewVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::JSDataViewVerify(*this, isolate);
  if (!WasDetached()) {
    CHECK_EQ(reinterpret_cast<uint8_t*>(
                 JSArrayBuffer::cast(buffer()).backing_store()) +
                 byte_offset(),
             data_pointer());
  }
}

void AsyncGeneratorRequest::AsyncGeneratorRequestVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::AsyncGeneratorRequestVerify(*this, isolate);
  CHECK_GE(resume_mode(), JSGeneratorObject::kNext);
  CHECK_LE(resume_mode(), JSGeneratorObject::kThrow);
}

void BigIntBase::BigIntBaseVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::BigIntBaseVerify(*this, isolate);
  CHECK_GE(length(), 0);
  CHECK_IMPLIES(is_zero(), !sign());  // There is no -0n.
}

void SourceTextModuleInfoEntry::SourceTextModuleInfoEntryVerify(
    Isolate* isolate) {
  TorqueGeneratedClassVerifiers::SourceTextModuleInfoEntryVerify(*this,
                                                                 isolate);
  CHECK_IMPLIES(import_name().IsString(), module_request() >= 0);
  CHECK_IMPLIES(export_name().IsString() && import_name().IsString(),
                local_name().IsUndefined(isolate));
}

void Module::ModuleVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::ModuleVerify(*this, isolate);

  CHECK_EQ(status() == Module::kErrored, !exception().IsTheHole(isolate));

  CHECK(module_namespace().IsUndefined(isolate) ||
        module_namespace().IsJSModuleNamespace());
  if (module_namespace().IsJSModuleNamespace()) {
    CHECK_LE(Module::kInstantiating, status());
    CHECK_EQ(JSModuleNamespace::cast(module_namespace()).module(), *this);
  }

  CHECK_NE(hash(), 0);
}

void SourceTextModule::SourceTextModuleVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::SourceTextModuleVerify(*this, isolate);

  if (status() == kErrored) {
    CHECK(code().IsSourceTextModuleInfo());
  } else if (status() == kEvaluating || status() == kEvaluated) {
    CHECK(code().IsJSGeneratorObject());
  } else {
    CHECK((status() == kInstantiated && code().IsJSGeneratorObject()) ||
          (status() == kInstantiating && code().IsJSFunction()) ||
          (status() == kPreInstantiating && code().IsSharedFunctionInfo()) ||
          (status() == kUninstantiated && code().IsSharedFunctionInfo()));
    CHECK(top_level_capability().IsUndefined() && !AsyncParentModuleCount() &&
          !pending_async_dependencies() && !async_evaluating());
  }

  CHECK_EQ(requested_modules().length(), info().module_requests().length());
}

void SyntheticModule::SyntheticModuleVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::SyntheticModuleVerify(*this, isolate);

  for (int i = 0; i < export_names().length(); i++) {
    CHECK(export_names().get(i).IsString());
  }
}

void PrototypeInfo::PrototypeInfoVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::PrototypeInfoVerify(*this, isolate);
  if (prototype_users().IsWeakArrayList()) {
    PrototypeUsers::Verify(WeakArrayList::cast(prototype_users()));
  } else {
    CHECK(prototype_users().IsSmi());
  }
}

void PrototypeUsers::Verify(WeakArrayList array) {
  if (array.length() == 0) {
    // Allow empty & uninitialized lists.
    return;
  }
  // Verify empty slot chain.
  int empty_slot = Smi::ToInt(empty_slot_index(array));
  int empty_slots_count = 0;
  while (empty_slot != kNoEmptySlotsMarker) {
    CHECK_GT(empty_slot, 0);
    CHECK_LT(empty_slot, array.length());
    empty_slot = array.Get(empty_slot).ToSmi().value();
    ++empty_slots_count;
  }

  // Verify that all elements are either weak pointers or SMIs marking empty
  // slots.
  int weak_maps_count = 0;
  for (int i = kFirstIndex; i < array.length(); ++i) {
    HeapObject heap_object;
    MaybeObject object = array.Get(i);
    if ((object->GetHeapObjectIfWeak(&heap_object) && heap_object.IsMap()) ||
        object->IsCleared()) {
      ++weak_maps_count;
    } else {
      CHECK(object->IsSmi());
    }
  }

  CHECK_EQ(weak_maps_count + empty_slots_count + 1, array.length());
}

void EnumCache::EnumCacheVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::EnumCacheVerify(*this, isolate);
  Heap* heap = isolate->heap();
  if (*this == ReadOnlyRoots(heap).empty_enum_cache()) {
    CHECK_EQ(ReadOnlyRoots(heap).empty_fixed_array(), keys());
    CHECK_EQ(ReadOnlyRoots(heap).empty_fixed_array(), indices());
  }
}

void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionVerify(
    Isolate* isolate) {
  CHECK(IsObjectBoilerplateDescription());
  CHECK_GE(this->length(),
           ObjectBoilerplateDescription::kDescriptionStartIndex);
  this->FixedArrayVerify(isolate);
  for (int i = 0; i < length(); ++i) {
    // No ThinStrings in the boilerplate.
    CHECK(!get(isolate, i).IsThinString(isolate));
  }
}

USE_TORQUE_VERIFIER(AsmWasmData)

void WasmInstanceObject::WasmInstanceObjectVerify(Isolate* isolate) {
  JSObjectVerify(isolate);
  CHECK(IsWasmInstanceObject());

  // Just generically check all tagged fields. Don't check the untagged fields,
  // as some of them might still contain the "undefined" value if the
  // WasmInstanceObject is not fully set up yet.
  for (int offset = kHeaderSize; offset < kEndOfStrongFieldsOffset;
       offset += kTaggedSize) {
    VerifyObjectField(isolate, offset);
  }
}

void WasmExportedFunctionData::WasmExportedFunctionDataVerify(
    Isolate* isolate) {
  TorqueGeneratedClassVerifiers::WasmExportedFunctionDataVerify(*this, isolate);
  CHECK(wrapper_code().kind() == CodeKind::JS_TO_WASM_FUNCTION ||
        wrapper_code().kind() == CodeKind::C_WASM_ENTRY ||
        (wrapper_code().is_builtin() &&
         wrapper_code().builtin_index() == Builtins::kGenericJSToWasmWrapper));
}

USE_TORQUE_VERIFIER(WasmModuleObject)

USE_TORQUE_VERIFIER(WasmTableObject)

USE_TORQUE_VERIFIER(WasmMemoryObject)

USE_TORQUE_VERIFIER(WasmGlobalObject)

USE_TORQUE_VERIFIER(WasmExceptionObject)

void DataHandler::DataHandlerVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::DataHandlerVerify(*this, isolate);
  CHECK_IMPLIES(!smi_handler().IsSmi(),
                smi_handler().IsCode() && IsStoreHandler());
  int data_count = data_field_count();
  if (data_count >= 1) {
    VerifyMaybeObjectField(isolate, kData1Offset);
  }
  if (data_count >= 2) {
    VerifyMaybeObjectField(isolate, kData2Offset);
  }
  if (data_count >= 3) {
    VerifyMaybeObjectField(isolate, kData3Offset);
  }
}

void LoadHandler::LoadHandlerVerify(Isolate* isolate) {
  DataHandler::DataHandlerVerify(isolate);
  // TODO(ishell): check handler integrity
}

void StoreHandler::StoreHandlerVerify(Isolate* isolate) {
  DataHandler::DataHandlerVerify(isolate);
  // TODO(ishell): check handler integrity
}

void CallHandlerInfo::CallHandlerInfoVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::CallHandlerInfoVerify(*this, isolate);
  CHECK(map() == ReadOnlyRoots(isolate).side_effect_call_handler_info_map() ||
        map() ==
            ReadOnlyRoots(isolate).side_effect_free_call_handler_info_map() ||
        map() == ReadOnlyRoots(isolate)
                     .next_call_side_effect_free_call_handler_info_map());
}

USE_TORQUE_VERIFIER(WasmCapiFunctionData)

USE_TORQUE_VERIFIER(WasmJSFunctionData)

USE_TORQUE_VERIFIER(WasmIndirectFunctionTable)

void AllocationSite::AllocationSiteVerify(Isolate* isolate) {
  CHECK(IsAllocationSite());
  CHECK(dependent_code().IsDependentCode());
  CHECK(transition_info_or_boilerplate().IsSmi() ||
        transition_info_or_boilerplate().IsJSObject());
  CHECK(nested_site().IsAllocationSite() || nested_site() == Smi::zero());
}

void Script::ScriptVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::ScriptVerify(*this, isolate);
  for (int i = 0; i < shared_function_infos().length(); ++i) {
    MaybeObject maybe_object = shared_function_infos().Get(i);
    HeapObject heap_object;
    CHECK(maybe_object->IsWeak() || maybe_object->IsCleared() ||
          (maybe_object->GetHeapObjectIfStrong(&heap_object) &&
           heap_object.IsUndefined(isolate)));
  }
}

void NormalizedMapCache::NormalizedMapCacheVerify(Isolate* isolate) {
  WeakFixedArray::cast(*this).WeakFixedArrayVerify(isolate);
  if (FLAG_enable_slow_asserts) {
    for (int i = 0; i < length(); i++) {
      MaybeObject e = WeakFixedArray::Get(i);
      HeapObject heap_object;
      if (e->GetHeapObjectIfWeak(&heap_object)) {
        Map::cast(heap_object).DictionaryMapVerify(isolate);
      } else {
        CHECK(e->IsCleared() || (e->GetHeapObjectIfStrong(&heap_object) &&
                                 heap_object.IsUndefined(isolate)));
      }
    }
  }
}

void PreparseData::PreparseDataVerify(Isolate* isolate) {
  TorqueGeneratedClassVerifiers::PreparseDataVerify(*this, isolate);
  CHECK_LE(0, data_length());
  CHECK_LE(0, children_length());

  for (int i = 0; i < children_length(); ++i) {
    Object child = get_child_raw(i);
    CHECK(child.IsNull() || child.IsPreparseData());
    VerifyPointer(isolate, child);
  }
}

USE_TORQUE_VERIFIER(InterpreterData)

#endif  // VERIFY_HEAP

#ifdef DEBUG

void JSObject::IncrementSpillStatistics(Isolate* isolate,
                                        SpillInformation* info) {
  info->number_of_objects_++;
  // Named properties
  if (HasFastProperties()) {
    info->number_of_objects_with_fast_properties_++;
    info->number_of_fast_used_fields_ += map().NextFreePropertyIndex();
    info->number_of_fast_unused_fields_ += map().UnusedPropertyFields();
  } else if (IsJSGlobalObject()) {
    GlobalDictionary dict = JSGlobalObject::cast(*this).global_dictionary();
    info->number_of_slow_used_properties_ += dict.NumberOfElements();
    info->number_of_slow_unused_properties_ +=
        dict.Capacity() - dict.NumberOfElements();
  } else {
    NameDictionary dict = property_dictionary();
    info->number_of_slow_used_properties_ += dict.NumberOfElements();
    info->number_of_slow_unused_properties_ +=
        dict.Capacity() - dict.NumberOfElements();
  }
  // Indexed properties
  switch (GetElementsKind()) {
    case HOLEY_SMI_ELEMENTS:
    case PACKED_SMI_ELEMENTS:
    case HOLEY_DOUBLE_ELEMENTS:
    case PACKED_DOUBLE_ELEMENTS:
    case HOLEY_ELEMENTS:
    case HOLEY_FROZEN_ELEMENTS:
    case HOLEY_SEALED_ELEMENTS:
    case HOLEY_NONEXTENSIBLE_ELEMENTS:
    case PACKED_ELEMENTS:
    case PACKED_FROZEN_ELEMENTS:
    case PACKED_SEALED_ELEMENTS:
    case PACKED_NONEXTENSIBLE_ELEMENTS:
    case FAST_STRING_WRAPPER_ELEMENTS: {
      info->number_of_objects_with_fast_elements_++;
      int holes = 0;
      FixedArray e = FixedArray::cast(elements());
      int len = e.length();
      for (int i = 0; i < len; i++) {
        if (e.get(i).IsTheHole(isolate)) holes++;
      }
      info->number_of_fast_used_elements_ += len - holes;
      info->number_of_fast_unused_elements_ += holes;
      break;
    }

#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:

      TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
      {
        info->number_of_objects_with_fast_elements_++;
        FixedArrayBase e = FixedArrayBase::cast(elements());
        info->number_of_fast_used_elements_ += e.length();
        break;
      }
    case DICTIONARY_ELEMENTS:
    case SLOW_STRING_WRAPPER_ELEMENTS: {
      NumberDictionary dict = element_dictionary();
      info->number_of_slow_used_elements_ += dict.NumberOfElements();
      info->number_of_slow_unused_elements_ +=
          dict.Capacity() - dict.NumberOfElements();
      break;
    }
    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
    case NO_ELEMENTS:
      break;
  }
}

void JSObject::SpillInformation::Clear() {
  number_of_objects_ = 0;
  number_of_objects_with_fast_properties_ = 0;
  number_of_objects_with_fast_elements_ = 0;
  number_of_fast_used_fields_ = 0;
  number_of_fast_unused_fields_ = 0;
  number_of_slow_used_properties_ = 0;
  number_of_slow_unused_properties_ = 0;
  number_of_fast_used_elements_ = 0;
  number_of_fast_unused_elements_ = 0;
  number_of_slow_used_elements_ = 0;
  number_of_slow_unused_elements_ = 0;
}

void JSObject::SpillInformation::Print() {
  PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);

  PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
         number_of_objects_with_fast_properties_, number_of_fast_used_fields_,
         number_of_fast_unused_fields_);

  PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
         number_of_objects_ - number_of_objects_with_fast_properties_,
         number_of_slow_used_properties_, number_of_slow_unused_properties_);

  PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
         number_of_objects_with_fast_elements_, number_of_fast_used_elements_,
         number_of_fast_unused_elements_);

  PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
         number_of_objects_ - number_of_objects_with_fast_elements_,
         number_of_slow_used_elements_, number_of_slow_unused_elements_);

  PrintF("\n");
}

bool DescriptorArray::IsSortedNoDuplicates() {
  Name current_key;
  uint32_t current = 0;
  for (int i = 0; i < number_of_descriptors(); i++) {
    Name key = GetSortedKey(i);
    if (key == current_key) {
      Print();
      return false;
    }
    current_key = key;
    uint32_t hash = GetSortedKey(i).Hash();
    if (hash < current) {
      Print();
      return false;
    }
    current = hash;
  }
  return true;
}

bool TransitionArray::IsSortedNoDuplicates() {
  Name prev_key;
  PropertyKind prev_kind = kData;
  PropertyAttributes prev_attributes = NONE;
  uint32_t prev_hash = 0;

  for (int i = 0; i < number_of_transitions(); i++) {
    Name key = GetSortedKey(i);
    uint32_t hash = key.Hash();
    PropertyKind kind = kData;
    PropertyAttributes attributes = NONE;
    if (!TransitionsAccessor::IsSpecialTransition(key.GetReadOnlyRoots(),
                                                  key)) {
      Map target = GetTarget(i);
      PropertyDetails details =
          TransitionsAccessor::GetTargetDetails(key, target);
      kind = details.kind();
      attributes = details.attributes();
    } else {
      // Duplicate entries are not allowed for non-property transitions.
      DCHECK_NE(prev_key, key);
    }

    int cmp = CompareKeys(prev_key, prev_hash, prev_kind, prev_attributes, key,
                          hash, kind, attributes);
    if (cmp >= 0) {
      Print();
      return false;
    }
    prev_key = key;
    prev_hash = hash;
    prev_attributes = attributes;
    prev_kind = kind;
  }
  return true;
}

bool TransitionsAccessor::IsSortedNoDuplicates() {
  // Simple and non-existent transitions are always sorted.
  if (encoding() != kFullTransitionArray) return true;
  return transitions().IsSortedNoDuplicates();
}

static bool CheckOneBackPointer(Map current_map, Object target) {
  return !target.IsMap() || Map::cast(target).GetBackPointer() == current_map;
}

bool TransitionsAccessor::IsConsistentWithBackPointers() {
  int num_transitions = NumberOfTransitions();
  for (int i = 0; i < num_transitions; i++) {
    Map target = GetTarget(i);
    if (!CheckOneBackPointer(map_, target)) return false;
  }
  return true;
}

#undef USE_TORQUE_VERIFIER

#endif  // DEBUG

}  // namespace internal
}  // namespace v8
