1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/codegen/assembler-inl.h"
6#include "src/common/globals.h"
7#include "src/date/date.h"
8#include "src/diagnostics/disasm.h"
9#include "src/diagnostics/disassembler.h"
10#include "src/heap/combined-heap.h"
11#include "src/heap/heap-write-barrier-inl.h"
12#include "src/heap/read-only-heap.h"
13#include "src/ic/handler-configuration-inl.h"
14#include "src/init/bootstrapper.h"
15#include "src/logging/runtime-call-stats-scope.h"
16#include "src/objects/allocation-site-inl.h"
17#include "src/objects/arguments-inl.h"
18#include "src/objects/bigint.h"
19#include "src/objects/call-site-info-inl.h"
20#include "src/objects/cell-inl.h"
21#include "src/objects/data-handler-inl.h"
22#include "src/objects/debug-objects-inl.h"
23#include "src/objects/elements.h"
24#include "src/objects/embedder-data-array-inl.h"
25#include "src/objects/embedder-data-slot-inl.h"
26#include "src/objects/feedback-cell-inl.h"
27#include "src/objects/field-type.h"
28#include "src/objects/foreign-inl.h"
29#include "src/objects/free-space-inl.h"
30#include "src/objects/function-kind.h"
31#include "src/objects/hash-table-inl.h"
32#include "src/objects/instance-type.h"
33#include "src/objects/js-array-buffer-inl.h"
34#include "src/objects/js-array-inl.h"
35#include "src/objects/objects-inl.h"
36#include "src/objects/objects.h"
37#include "src/objects/turbofan-types-inl.h"
38#include "src/roots/roots.h"
39#ifdef V8_INTL_SUPPORT
40#include "src/objects/js-break-iterator-inl.h"
41#include "src/objects/js-collator-inl.h"
42#endif  // V8_INTL_SUPPORT
43#include "src/objects/js-collection-inl.h"
44#ifdef V8_INTL_SUPPORT
45#include "src/objects/js-date-time-format-inl.h"
46#include "src/objects/js-display-names-inl.h"
47#endif  // V8_INTL_SUPPORT
48#include "src/objects/js-generator-inl.h"
49#ifdef V8_INTL_SUPPORT
50#include "src/objects/js-list-format-inl.h"
51#include "src/objects/js-locale-inl.h"
52#include "src/objects/js-number-format-inl.h"
53#include "src/objects/js-plural-rules-inl.h"
54#endif  // V8_INTL_SUPPORT
55#include "src/objects/js-regexp-inl.h"
56#include "src/objects/js-regexp-string-iterator-inl.h"
57#include "src/objects/js-shadow-realms-inl.h"
58#ifdef V8_INTL_SUPPORT
59#include "src/objects/js-relative-time-format-inl.h"
60#include "src/objects/js-segment-iterator-inl.h"
61#include "src/objects/js-segmenter-inl.h"
62#include "src/objects/js-segments-inl.h"
63#endif  // V8_INTL_SUPPORT
64#include "src/objects/js-struct-inl.h"
65#include "src/objects/js-temporal-objects-inl.h"
66#include "src/objects/js-weak-refs-inl.h"
67#include "src/objects/literal-objects-inl.h"
68#include "src/objects/maybe-object.h"
69#include "src/objects/megadom-handler-inl.h"
70#include "src/objects/microtask-inl.h"
71#include "src/objects/module-inl.h"
72#include "src/objects/oddball-inl.h"
73#include "src/objects/promise-inl.h"
74#include "src/objects/property-descriptor-object-inl.h"
75#include "src/objects/struct-inl.h"
76#include "src/objects/swiss-name-dictionary-inl.h"
77#include "src/objects/synthetic-module-inl.h"
78#include "src/objects/template-objects-inl.h"
79#include "src/objects/torque-defined-classes-inl.h"
80#include "src/objects/transitions-inl.h"
81#include "src/regexp/regexp.h"
82#include "src/utils/ostreams.h"
83#include "torque-generated/class-verifiers.h"
84
85#if V8_ENABLE_WEBASSEMBLY
86#include "src/base/strings.h"
87#include "src/debug/debug-wasm-objects-inl.h"
88#include "src/wasm/wasm-objects-inl.h"
89#endif  // V8_ENABLE_WEBASSEMBLY
90
91namespace v8 {
92namespace internal {
93
94// Heap Verification Overview
95// --------------------------
96// - Each InstanceType has a separate XXXVerify method which checks an object's
97//   integrity in isolation.
98// - --verify-heap will iterate over all gc spaces and call ObjectVerify() on
99//   every encountered tagged pointer.
100// - Verification should be pushed down to the specific instance type if its
101//   integrity is independent of an outer object.
102// - In cases where the InstanceType is too generic (e.g. FixedArray) the
103//   XXXVerify of the outer method has to do recursive verification.
104// - If the corresponding objects have inheritence the parent's Verify method
105//   is called as well.
106// - For any field containing pointes VerifyPointer(...) should be called.
107//
108// Caveats
109// -------
110// - Assume that any of the verify methods is incomplete!
111// - Some integrity checks are only partially done due to objects being in
112//   partially initialized states when a gc happens, for instance when outer
113//   objects are allocted before inner ones.
114//
115
116#ifdef VERIFY_HEAP
117
118#define USE_TORQUE_VERIFIER(Class)                                \
119  void Class::Class##Verify(Isolate* isolate) {                   \
120    TorqueGeneratedClassVerifiers::Class##Verify(*this, isolate); \
121  }
122
123void Object::ObjectVerify(Isolate* isolate) {
124  RCS_SCOPE(isolate, RuntimeCallCounterId::kObjectVerify);
125  if (IsSmi()) {
126    Smi::cast(*this).SmiVerify(isolate);
127  } else {
128    HeapObject::cast(*this).HeapObjectVerify(isolate);
129  }
130  PtrComprCageBase cage_base(isolate);
131  CHECK(!IsConstructor(cage_base) || IsCallable(cage_base));
132}
133
134void Object::VerifyPointer(Isolate* isolate, Object p) {
135  if (p.IsHeapObject()) {
136    HeapObject::VerifyHeapPointer(isolate, p);
137  } else {
138    CHECK(p.IsSmi());
139  }
140}
141
142void Object::VerifyAnyTagged(Isolate* isolate, Object p) {
143  if (p.IsHeapObject()) {
144    if (V8_EXTERNAL_CODE_SPACE_BOOL) {
145      CHECK(IsValidHeapObject(isolate->heap(), HeapObject::cast(p)));
146    } else {
147      HeapObject::VerifyHeapPointer(isolate, p);
148    }
149  } else {
150    CHECK(p.IsSmi());
151  }
152}
153
154void MaybeObject::VerifyMaybeObjectPointer(Isolate* isolate, MaybeObject p) {
155  HeapObject heap_object;
156  if (p->GetHeapObject(&heap_object)) {
157    HeapObject::VerifyHeapPointer(isolate, heap_object);
158  } else {
159    CHECK(p->IsSmi() || p->IsCleared() || MapWord::IsPacked(p->ptr()));
160  }
161}
162
163void Smi::SmiVerify(Isolate* isolate) {
164  CHECK(IsSmi());
165  CHECK(!IsCallable());
166  CHECK(!IsConstructor());
167}
168
169void TaggedIndex::TaggedIndexVerify(Isolate* isolate) {
170  CHECK(IsTaggedIndex());
171}
172
173void HeapObject::HeapObjectVerify(Isolate* isolate) {
174  CHECK(IsHeapObject());
175  PtrComprCageBase cage_base(isolate);
176  VerifyPointer(isolate, map(cage_base));
177  CHECK(map(cage_base).IsMap(cage_base));
178
179  switch (map(cage_base).instance_type()) {
180#define STRING_TYPE_CASE(TYPE, size, name, CamelName) case TYPE:
181    STRING_TYPE_LIST(STRING_TYPE_CASE)
182#undef STRING_TYPE_CASE
183    if (IsConsString(cage_base)) {
184      ConsString::cast(*this).ConsStringVerify(isolate);
185    } else if (IsSlicedString(cage_base)) {
186      SlicedString::cast(*this).SlicedStringVerify(isolate);
187    } else if (IsThinString(cage_base)) {
188      ThinString::cast(*this).ThinStringVerify(isolate);
189    } else if (IsSeqString(cage_base)) {
190      SeqString::cast(*this).SeqStringVerify(isolate);
191    } else if (IsExternalString(cage_base)) {
192      ExternalString::cast(*this).ExternalStringVerify(isolate);
193    } else {
194      String::cast(*this).StringVerify(isolate);
195    }
196    break;
197    case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
198      ObjectBoilerplateDescription::cast(*this)
199          .ObjectBoilerplateDescriptionVerify(isolate);
200      break;
201    // FixedArray types
202    case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
203    case HASH_TABLE_TYPE:
204    case ORDERED_HASH_MAP_TYPE:
205    case ORDERED_HASH_SET_TYPE:
206    case ORDERED_NAME_DICTIONARY_TYPE:
207    case NAME_TO_INDEX_HASH_TABLE_TYPE:
208    case REGISTERED_SYMBOL_TABLE_TYPE:
209    case NAME_DICTIONARY_TYPE:
210    case GLOBAL_DICTIONARY_TYPE:
211    case NUMBER_DICTIONARY_TYPE:
212    case SIMPLE_NUMBER_DICTIONARY_TYPE:
213    case EPHEMERON_HASH_TABLE_TYPE:
214    case SCRIPT_CONTEXT_TABLE_TYPE:
215      FixedArray::cast(*this).FixedArrayVerify(isolate);
216      break;
217    case AWAIT_CONTEXT_TYPE:
218    case BLOCK_CONTEXT_TYPE:
219    case CATCH_CONTEXT_TYPE:
220    case DEBUG_EVALUATE_CONTEXT_TYPE:
221    case EVAL_CONTEXT_TYPE:
222    case FUNCTION_CONTEXT_TYPE:
223    case MODULE_CONTEXT_TYPE:
224    case SCRIPT_CONTEXT_TYPE:
225    case WITH_CONTEXT_TYPE:
226      Context::cast(*this).ContextVerify(isolate);
227      break;
228    case NATIVE_CONTEXT_TYPE:
229      NativeContext::cast(*this).NativeContextVerify(isolate);
230      break;
231    case FEEDBACK_METADATA_TYPE:
232      FeedbackMetadata::cast(*this).FeedbackMetadataVerify(isolate);
233      break;
234    case TRANSITION_ARRAY_TYPE:
235      TransitionArray::cast(*this).TransitionArrayVerify(isolate);
236      break;
237
238    case CODE_TYPE:
239      Code::cast(*this).CodeVerify(isolate);
240      break;
241    case JS_API_OBJECT_TYPE:
242    case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE:
243    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
244    case JS_ERROR_TYPE:
245    case JS_ITERATOR_PROTOTYPE_TYPE:
246    case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
247    case JS_OBJECT_PROTOTYPE_TYPE:
248    case JS_PROMISE_PROTOTYPE_TYPE:
249    case JS_REG_EXP_PROTOTYPE_TYPE:
250    case JS_SET_ITERATOR_PROTOTYPE_TYPE:
251    case JS_SET_PROTOTYPE_TYPE:
252    case JS_SPECIAL_API_OBJECT_TYPE:
253    case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
254    case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
255      JSObject::cast(*this).JSObjectVerify(isolate);
256      break;
257#if V8_ENABLE_WEBASSEMBLY
258    case WASM_INSTANCE_OBJECT_TYPE:
259      WasmInstanceObject::cast(*this).WasmInstanceObjectVerify(isolate);
260      break;
261    case WASM_VALUE_OBJECT_TYPE:
262      WasmValueObject::cast(*this).WasmValueObjectVerify(isolate);
263      break;
264#endif  // V8_ENABLE_WEBASSEMBLY
265    case JS_SET_KEY_VALUE_ITERATOR_TYPE:
266    case JS_SET_VALUE_ITERATOR_TYPE:
267      JSSetIterator::cast(*this).JSSetIteratorVerify(isolate);
268      break;
269    case JS_MAP_KEY_ITERATOR_TYPE:
270    case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
271    case JS_MAP_VALUE_ITERATOR_TYPE:
272      JSMapIterator::cast(*this).JSMapIteratorVerify(isolate);
273      break;
274    case FILLER_TYPE:
275      break;
276    case CODE_DATA_CONTAINER_TYPE:
277      CodeDataContainer::cast(*this).CodeDataContainerVerify(isolate);
278      break;
279
280#define MAKE_TORQUE_CASE(Name, TYPE)         \
281  case TYPE:                                 \
282    Name::cast(*this).Name##Verify(isolate); \
283    break;
284      // Every class that has its fields defined in a .tq file and corresponds
285      // to exactly one InstanceType value is included in the following list.
286      TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
287      TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
288#undef MAKE_TORQUE_CASE
289
290    case ALLOCATION_SITE_TYPE:
291      AllocationSite::cast(*this).AllocationSiteVerify(isolate);
292      break;
293
294    case LOAD_HANDLER_TYPE:
295      LoadHandler::cast(*this).LoadHandlerVerify(isolate);
296      break;
297
298    case STORE_HANDLER_TYPE:
299      StoreHandler::cast(*this).StoreHandlerVerify(isolate);
300      break;
301
302    case BIG_INT_BASE_TYPE:
303      BigIntBase::cast(*this).BigIntBaseVerify(isolate);
304      break;
305
306    case JS_CLASS_CONSTRUCTOR_TYPE:
307    case JS_PROMISE_CONSTRUCTOR_TYPE:
308    case JS_REG_EXP_CONSTRUCTOR_TYPE:
309    case JS_ARRAY_CONSTRUCTOR_TYPE:
310#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
311  case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
312      TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
313#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
314      JSFunction::cast(*this).JSFunctionVerify(isolate);
315      break;
316    case JS_LAST_DUMMY_API_OBJECT_TYPE:
317      UNREACHABLE();
318  }
319}
320
321// static
322void HeapObject::VerifyHeapPointer(Isolate* isolate, Object p) {
323  CHECK(p.IsHeapObject());
324  CHECK(IsValidHeapObject(isolate->heap(), HeapObject::cast(p)));
325  CHECK_IMPLIES(V8_EXTERNAL_CODE_SPACE_BOOL, !p.IsCode());
326}
327
328// static
329void HeapObject::VerifyCodePointer(Isolate* isolate, Object p) {
330  CHECK(p.IsHeapObject());
331  CHECK(IsValidCodeObject(isolate->heap(), HeapObject::cast(p)));
332  PtrComprCageBase cage_base(isolate);
333  CHECK(HeapObject::cast(p).IsCode(cage_base));
334}
335
336void Symbol::SymbolVerify(Isolate* isolate) {
337  TorqueGeneratedClassVerifiers::SymbolVerify(*this, isolate);
338  CHECK(HasHashCode());
339  CHECK_GT(hash(), 0);
340  CHECK(description().IsUndefined(isolate) || description().IsString());
341  CHECK_IMPLIES(IsPrivateName(), IsPrivate());
342  CHECK_IMPLIES(IsPrivateBrand(), IsPrivateName());
343}
344
345void BytecodeArray::BytecodeArrayVerify(Isolate* isolate) {
346  // TODO(oth): Walk bytecodes and immediate values to validate sanity.
347  // - All bytecodes are known and well formed.
348  // - Jumps must go to new instructions starts.
349  // - No Illegal bytecodes.
350  // - No consecutive sequences of prefix Wide / ExtraWide.
351  TorqueGeneratedClassVerifiers::BytecodeArrayVerify(*this, isolate);
352  for (int i = 0; i < constant_pool(isolate).length(); ++i) {
353    // No ThinStrings in the constant pool.
354    CHECK(!constant_pool(isolate).get(isolate, i).IsThinString(isolate));
355  }
356}
357
358bool JSObject::ElementsAreSafeToExamine(PtrComprCageBase cage_base) const {
359  // If a GC was caused while constructing this object, the elements
360  // pointer may point to a one pointer filler map.
361  return elements(cage_base) !=
362         GetReadOnlyRoots(cage_base).one_pointer_filler_map();
363}
364
365namespace {
366
367void VerifyJSObjectElements(Isolate* isolate, JSObject object) {
368  // Only TypedArrays can have these specialized elements.
369  if (object.IsJSTypedArray()) {
370    // TODO(bmeurer,v8:4153): Fix CreateTypedArray to either not instantiate
371    // the object or propertly initialize it on errors during construction.
372    /* CHECK(object->HasTypedArrayOrRabGsabTypedArrayElements()); */
373    return;
374  }
375  CHECK(!object.elements().IsByteArray());
376
377  if (object.HasDoubleElements()) {
378    if (object.elements().length() > 0) {
379      CHECK(object.elements().IsFixedDoubleArray());
380    }
381    return;
382  }
383
384  if (object.HasSloppyArgumentsElements()) {
385    CHECK(object.elements().IsSloppyArgumentsElements());
386    return;
387  }
388
389  FixedArray elements = FixedArray::cast(object.elements());
390  if (object.HasSmiElements()) {
391    // We might have a partially initialized backing store, in which case we
392    // allow the hole + smi values.
393    for (int i = 0; i < elements.length(); i++) {
394      Object value = elements.get(i);
395      CHECK(value.IsSmi() || value.IsTheHole(isolate));
396    }
397  } else if (object.HasObjectElements()) {
398    for (int i = 0; i < elements.length(); i++) {
399      Object element = elements.get(i);
400      CHECK(!HasWeakHeapObjectTag(element));
401    }
402  }
403}
404}  // namespace
405
406void JSObject::JSObjectVerify(Isolate* isolate) {
407  TorqueGeneratedClassVerifiers::JSObjectVerify(*this, isolate);
408  VerifyHeapPointer(isolate, elements());
409
410  CHECK_IMPLIES(HasSloppyArgumentsElements(), IsJSArgumentsObject());
411  if (HasFastProperties()) {
412    int actual_unused_property_fields = map().GetInObjectProperties() +
413                                        property_array().length() -
414                                        map().NextFreePropertyIndex();
415    if (map().UnusedPropertyFields() != actual_unused_property_fields) {
416      // There are two reasons why this can happen:
417      // - in the middle of StoreTransitionStub when the new extended backing
418      //   store is already set into the object and the allocation of the
419      //   HeapNumber triggers GC while the map isn't updated yet.
420      // - deletion of the last property can leave additional backing store
421      //   capacity behind.
422      CHECK_GT(actual_unused_property_fields, map().UnusedPropertyFields());
423      int delta = actual_unused_property_fields - map().UnusedPropertyFields();
424      CHECK_EQ(0, delta % JSObject::kFieldsAdded);
425    }
426    DescriptorArray descriptors = map().instance_descriptors(isolate);
427    bool is_transitionable_fast_elements_kind =
428        IsTransitionableFastElementsKind(map().elements_kind());
429
430    for (InternalIndex i : map().IterateOwnDescriptors()) {
431      PropertyDetails details = descriptors.GetDetails(i);
432      if (details.location() == PropertyLocation::kField) {
433        DCHECK_EQ(PropertyKind::kData, details.kind());
434        Representation r = details.representation();
435        FieldIndex index = FieldIndex::ForDescriptor(map(), i);
436        if (COMPRESS_POINTERS_BOOL && index.is_inobject()) {
437          VerifyObjectField(isolate, index.offset());
438        }
439        Object value = RawFastPropertyAt(index);
440        if (r.IsDouble()) DCHECK(value.IsHeapNumber());
441        if (value.IsUninitialized(isolate)) continue;
442        if (r.IsSmi()) DCHECK(value.IsSmi());
443        if (r.IsHeapObject()) DCHECK(value.IsHeapObject());
444        FieldType field_type = descriptors.GetFieldType(i);
445        bool type_is_none = field_type.IsNone();
446        bool type_is_any = field_type.IsAny();
447        if (r.IsNone()) {
448          CHECK(type_is_none);
449        } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) {
450          CHECK(!field_type.NowStable() || field_type.NowContains(value));
451        }
452        CHECK_IMPLIES(is_transitionable_fast_elements_kind,
453                      Map::IsMostGeneralFieldType(r, field_type));
454      }
455    }
456
457    if (map().EnumLength() != kInvalidEnumCacheSentinel) {
458      EnumCache enum_cache = descriptors.enum_cache();
459      FixedArray keys = enum_cache.keys();
460      FixedArray indices = enum_cache.indices();
461      CHECK_LE(map().EnumLength(), keys.length());
462      CHECK_IMPLIES(indices != ReadOnlyRoots(isolate).empty_fixed_array(),
463                    keys.length() == indices.length());
464    }
465  }
466
467  // If a GC was caused while constructing this object, the elements
468  // pointer may point to a one pointer filler map.
469  if (ElementsAreSafeToExamine(isolate)) {
470    CHECK_EQ((map().has_fast_smi_or_object_elements() ||
471              map().has_any_nonextensible_elements() ||
472              (elements() == GetReadOnlyRoots().empty_fixed_array()) ||
473              HasFastStringWrapperElements()),
474             (elements().map() == GetReadOnlyRoots().fixed_array_map() ||
475              elements().map() == GetReadOnlyRoots().fixed_cow_array_map()));
476    CHECK_EQ(map().has_fast_object_elements(), HasObjectElements());
477    VerifyJSObjectElements(isolate, *this);
478  }
479}
480
481void Map::MapVerify(Isolate* isolate) {
482  TorqueGeneratedClassVerifiers::MapVerify(*this, isolate);
483  Heap* heap = isolate->heap();
484  CHECK(!ObjectInYoungGeneration(*this));
485  CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
486  CHECK(instance_size() == kVariableSizeSentinel ||
487        (kTaggedSize <= instance_size() &&
488         static_cast<size_t>(instance_size()) < heap->Capacity()));
489  if (IsContextMap()) {
490    // The map for the NativeContext is allocated before the NativeContext
491    // itself, so it may happen that during a GC the native_context() is still
492    // null.
493    CHECK(native_context_or_null().IsNull() ||
494          native_context().IsNativeContext());
495  } else {
496    if (GetBackPointer().IsUndefined(isolate)) {
497      // Root maps must not have descriptors in the descriptor array that do not
498      // belong to the map.
499      CHECK_EQ(NumberOfOwnDescriptors(),
500               instance_descriptors(isolate).number_of_descriptors());
501    } else {
502      // If there is a parent map it must be non-stable.
503      Map parent = Map::cast(GetBackPointer());
504      CHECK(!parent.is_stable());
505      DescriptorArray descriptors = instance_descriptors(isolate);
506      if (descriptors == parent.instance_descriptors(isolate)) {
507        if (NumberOfOwnDescriptors() == parent.NumberOfOwnDescriptors() + 1) {
508          // Descriptors sharing through property transitions takes over
509          // ownership from the parent map.
510          CHECK(!parent.owns_descriptors());
511        } else {
512          CHECK_EQ(NumberOfOwnDescriptors(), parent.NumberOfOwnDescriptors());
513          // Descriptors sharing through special transitions properly takes over
514          // ownership from the parent map unless it uses the canonical empty
515          // descriptor array.
516          if (descriptors != ReadOnlyRoots(isolate).empty_descriptor_array()) {
517            CHECK_IMPLIES(owns_descriptors(), !parent.owns_descriptors());
518            CHECK_IMPLIES(parent.owns_descriptors(), !owns_descriptors());
519          }
520        }
521      }
522    }
523  }
524  SLOW_DCHECK(instance_descriptors(isolate).IsSortedNoDuplicates());
525  SLOW_DCHECK(TransitionsAccessor(isolate, *this).IsSortedNoDuplicates());
526  SLOW_DCHECK(
527      TransitionsAccessor(isolate, *this).IsConsistentWithBackPointers());
528  // Only JSFunction maps have has_prototype_slot() bit set and constructible
529  // JSFunction objects must have prototype slot.
530  CHECK_IMPLIES(has_prototype_slot(), IsJSFunctionMap());
531
532  if (IsJSObjectMap()) {
533    int header_end_offset = JSObject::GetHeaderSize(*this);
534    int inobject_fields_start_offset = GetInObjectPropertyOffset(0);
535    // Ensure that embedder fields are located exactly between header and
536    // inobject properties.
537    CHECK_EQ(header_end_offset, JSObject::GetEmbedderFieldsStartOffset(*this));
538    CHECK_EQ(header_end_offset +
539                 JSObject::GetEmbedderFieldCount(*this) * kEmbedderDataSlotSize,
540             inobject_fields_start_offset);
541  }
542
543  if (!may_have_interesting_symbols()) {
544    CHECK(!has_named_interceptor());
545    CHECK(!is_dictionary_map());
546    CHECK(!is_access_check_needed());
547    DescriptorArray const descriptors = instance_descriptors(isolate);
548    for (InternalIndex i : IterateOwnDescriptors()) {
549      CHECK(!descriptors.GetKey(i).IsInterestingSymbol());
550    }
551  }
552  CHECK_IMPLIES(has_named_interceptor(), may_have_interesting_symbols());
553  CHECK_IMPLIES(is_dictionary_map(), may_have_interesting_symbols());
554  CHECK_IMPLIES(is_access_check_needed(), may_have_interesting_symbols());
555  CHECK_IMPLIES(IsJSObjectMap() && !CanHaveFastTransitionableElementsKind(),
556                IsDictionaryElementsKind(elements_kind()) ||
557                    IsTerminalElementsKind(elements_kind()) ||
558                    IsAnyHoleyNonextensibleElementsKind(elements_kind()));
559  CHECK_IMPLIES(is_deprecated(), !is_stable());
560  if (is_prototype_map()) {
561    DCHECK(prototype_info() == Smi::zero() ||
562           prototype_info().IsPrototypeInfo());
563  }
564}
565
566void Map::DictionaryMapVerify(Isolate* isolate) {
567  MapVerify(isolate);
568  CHECK(is_dictionary_map());
569  CHECK_EQ(kInvalidEnumCacheSentinel, EnumLength());
570  CHECK_EQ(ReadOnlyRoots(isolate).empty_descriptor_array(),
571           instance_descriptors(isolate));
572  CHECK_EQ(0, UnusedPropertyFields());
573  CHECK_EQ(Map::GetVisitorId(*this), visitor_id());
574}
575
576void EmbedderDataArray::EmbedderDataArrayVerify(Isolate* isolate) {
577  TorqueGeneratedClassVerifiers::EmbedderDataArrayVerify(*this, isolate);
578  EmbedderDataSlot start(*this, 0);
579  EmbedderDataSlot end(*this, length());
580  for (EmbedderDataSlot slot = start; slot < end; ++slot) {
581    Object e = slot.load_tagged();
582    Object::VerifyPointer(isolate, e);
583  }
584}
585
586void FixedArray::FixedArrayVerify(Isolate* isolate) {
587  TorqueGeneratedClassVerifiers::FixedArrayVerify(*this, isolate);
588  if (*this == ReadOnlyRoots(isolate).empty_fixed_array()) {
589    CHECK_EQ(length(), 0);
590    CHECK_EQ(map(), ReadOnlyRoots(isolate).fixed_array_map());
591  } else if (IsArrayList()) {
592    ArrayList::cast(*this).ArrayListVerify(isolate);
593  }
594}
595
596void WeakFixedArray::WeakFixedArrayVerify(Isolate* isolate) {
597  TorqueGeneratedClassVerifiers::WeakFixedArrayVerify(*this, isolate);
598  for (int i = 0; i < length(); i++) {
599    MaybeObject::VerifyMaybeObjectPointer(isolate, Get(i));
600  }
601}
602
603void ArrayList::ArrayListVerify(Isolate* isolate) {
604  // Avoid calling the torque-generated ArrayListVerify to prevent an endlessly
605  // recursion verification.
606  CHECK(IsArrayList());
607  CHECK_LE(ArrayList::kLengthIndex, length());
608  CHECK_LE(0, Length());
609  if (Length() == 0 && length() == ArrayList::kLengthIndex) {
610    CHECK_EQ(*this, ReadOnlyRoots(isolate).empty_array_list());
611  }
612}
613
614void PropertyArray::PropertyArrayVerify(Isolate* isolate) {
615  TorqueGeneratedClassVerifiers::PropertyArrayVerify(*this, isolate);
616  if (length() == 0) {
617    CHECK_EQ(*this, ReadOnlyRoots(isolate).empty_property_array());
618    return;
619  }
620  // There are no empty PropertyArrays.
621  CHECK_LT(0, length());
622  for (int i = 0; i < length(); i++) {
623    Object e = get(i);
624    Object::VerifyPointer(isolate, e);
625  }
626}
627
628void FixedDoubleArray::FixedDoubleArrayVerify(Isolate* isolate) {
629  TorqueGeneratedClassVerifiers::FixedDoubleArrayVerify(*this, isolate);
630  for (int i = 0; i < length(); i++) {
631    if (!is_the_hole(i)) {
632      uint64_t value = get_representation(i);
633      uint64_t unexpected =
634          bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN()) &
635          uint64_t{0x7FF8000000000000};
636      // Create implementation specific sNaN by inverting relevant bit.
637      unexpected ^= uint64_t{0x0008000000000000};
638      CHECK((value & uint64_t{0x7FF8000000000000}) != unexpected ||
639            (value & uint64_t{0x0007FFFFFFFFFFFF}) == uint64_t{0});
640    }
641  }
642}
643
644void Context::ContextVerify(Isolate* isolate) {
645  if (has_extension()) VerifyExtensionSlot(extension());
646  TorqueGeneratedClassVerifiers::ContextVerify(*this, isolate);
647  for (int i = 0; i < length(); i++) {
648    VerifyObjectField(isolate, OffsetOfElementAt(i));
649  }
650}
651
652void NativeContext::NativeContextVerify(Isolate* isolate) {
653  ContextVerify(isolate);
654  CHECK(retained_maps() == Smi::zero() || retained_maps().IsWeakArrayList());
655  CHECK_EQ(length(), NativeContext::NATIVE_CONTEXT_SLOTS);
656  CHECK_EQ(kVariableSizeSentinel, map().instance_size());
657}
658
659void FeedbackMetadata::FeedbackMetadataVerify(Isolate* isolate) {
660  if (slot_count() == 0 && create_closure_slot_count() == 0) {
661    CHECK_EQ(ReadOnlyRoots(isolate).empty_feedback_metadata(), *this);
662  } else {
663    FeedbackMetadataIterator iter(*this);
664    while (iter.HasNext()) {
665      iter.Next();
666      FeedbackSlotKind kind = iter.kind();
667      CHECK_NE(FeedbackSlotKind::kInvalid, kind);
668      CHECK_GT(FeedbackSlotKind::kKindsNumber, kind);
669    }
670  }
671}
672
673void DescriptorArray::DescriptorArrayVerify(Isolate* isolate) {
674  TorqueGeneratedClassVerifiers::DescriptorArrayVerify(*this, isolate);
675  if (number_of_all_descriptors() == 0) {
676    CHECK_EQ(ReadOnlyRoots(isolate).empty_descriptor_array(), *this);
677    CHECK_EQ(0, number_of_all_descriptors());
678    CHECK_EQ(0, number_of_descriptors());
679    CHECK_EQ(ReadOnlyRoots(isolate).empty_enum_cache(), enum_cache());
680  } else {
681    CHECK_LT(0, number_of_all_descriptors());
682    CHECK_LE(number_of_descriptors(), number_of_all_descriptors());
683
684    // Check that properties with private symbols names are non-enumerable, and
685    // that fields are in order.
686    int expected_field_index = 0;
687    for (InternalIndex descriptor :
688         InternalIndex::Range(number_of_descriptors())) {
689      Object key = *(GetDescriptorSlot(descriptor.as_int()) + kEntryKeyIndex);
690      // number_of_descriptors() may be out of sync with the actual descriptors
691      // written during descriptor array construction.
692      if (key.IsUndefined(isolate)) continue;
693      PropertyDetails details = GetDetails(descriptor);
694      if (Name::cast(key).IsPrivate()) {
695        CHECK_NE(details.attributes() & DONT_ENUM, 0);
696      }
697      MaybeObject value = GetValue(descriptor);
698      HeapObject heap_object;
699      if (details.location() == PropertyLocation::kField) {
700        CHECK_EQ(details.field_index(), expected_field_index);
701        CHECK(
702            value == MaybeObject::FromObject(FieldType::None()) ||
703            value == MaybeObject::FromObject(FieldType::Any()) ||
704            value->IsCleared() ||
705            (value->GetHeapObjectIfWeak(&heap_object) && heap_object.IsMap()));
706        expected_field_index += details.field_width_in_words();
707      } else {
708        CHECK(!value->IsWeakOrCleared());
709        CHECK(!value->cast<Object>().IsMap());
710      }
711    }
712  }
713}
714
715void TransitionArray::TransitionArrayVerify(Isolate* isolate) {
716  WeakFixedArrayVerify(isolate);
717  CHECK_LE(LengthFor(number_of_transitions()), length());
718}
719
720namespace {
721void SloppyArgumentsElementsVerify(Isolate* isolate,
722                                   SloppyArgumentsElements elements,
723                                   JSObject holder) {
724  elements.SloppyArgumentsElementsVerify(isolate);
725  ElementsKind kind = holder.GetElementsKind();
726  bool is_fast = kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
727  Context context_object = elements.context();
728  FixedArray arg_elements = elements.arguments();
729  if (arg_elements.length() == 0) {
730    CHECK(arg_elements == ReadOnlyRoots(isolate).empty_fixed_array());
731    return;
732  }
733  ElementsAccessor* accessor;
734  if (is_fast) {
735    accessor = ElementsAccessor::ForKind(HOLEY_ELEMENTS);
736  } else {
737    accessor = ElementsAccessor::ForKind(DICTIONARY_ELEMENTS);
738  }
739  int nofMappedParameters = 0;
740  int maxMappedIndex = 0;
741  for (int i = 0; i < nofMappedParameters; i++) {
742    // Verify that each context-mapped argument is either the hole or a valid
743    // Smi within context length range.
744    Object mapped = elements.mapped_entries(i, kRelaxedLoad);
745    if (mapped.IsTheHole(isolate)) {
746      // Slow sloppy arguments can be holey.
747      if (!is_fast) continue;
748      // Fast sloppy arguments elements are never holey. Either the element is
749      // context-mapped or present in the arguments elements.
750      CHECK(accessor->HasElement(holder, i, arg_elements));
751      continue;
752    }
753    int mappedIndex = Smi::ToInt(mapped);
754    nofMappedParameters++;
755    CHECK_LE(maxMappedIndex, mappedIndex);
756    maxMappedIndex = mappedIndex;
757    Object value = context_object.get(mappedIndex);
758    CHECK(value.IsObject());
759    // None of the context-mapped entries should exist in the arguments
760    // elements.
761    CHECK(!accessor->HasElement(holder, i, arg_elements));
762  }
763  CHECK_LE(nofMappedParameters, context_object.length());
764  CHECK_LE(nofMappedParameters, arg_elements.length());
765  CHECK_LE(maxMappedIndex, context_object.length());
766  CHECK_LE(maxMappedIndex, arg_elements.length());
767}
768}  // namespace
769
770void JSArgumentsObject::JSArgumentsObjectVerify(Isolate* isolate) {
771  TorqueGeneratedClassVerifiers::JSArgumentsObjectVerify(*this, isolate);
772  if (IsSloppyArgumentsElementsKind(GetElementsKind())) {
773    SloppyArgumentsElementsVerify(
774        isolate, SloppyArgumentsElements::cast(elements()), *this);
775  }
776  if (isolate->IsInAnyContext(map(), Context::SLOPPY_ARGUMENTS_MAP_INDEX) ||
777      isolate->IsInAnyContext(map(),
778                              Context::SLOW_ALIASED_ARGUMENTS_MAP_INDEX) ||
779      isolate->IsInAnyContext(map(),
780                              Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX)) {
781    VerifyObjectField(isolate, JSSloppyArgumentsObject::kLengthOffset);
782    VerifyObjectField(isolate, JSSloppyArgumentsObject::kCalleeOffset);
783  } else if (isolate->IsInAnyContext(map(),
784                                     Context::STRICT_ARGUMENTS_MAP_INDEX)) {
785    VerifyObjectField(isolate, JSStrictArgumentsObject::kLengthOffset);
786  }
787}
788
789void JSAsyncFunctionObject::JSAsyncFunctionObjectVerify(Isolate* isolate) {
790  TorqueGeneratedClassVerifiers::JSAsyncFunctionObjectVerify(*this, isolate);
791}
792
793void JSAsyncGeneratorObject::JSAsyncGeneratorObjectVerify(Isolate* isolate) {
794  TorqueGeneratedClassVerifiers::JSAsyncGeneratorObjectVerify(*this, isolate);
795}
796
797void JSDate::JSDateVerify(Isolate* isolate) {
798  TorqueGeneratedClassVerifiers::JSDateVerify(*this, isolate);
799
800  if (month().IsSmi()) {
801    int month = Smi::ToInt(this->month());
802    CHECK(0 <= month && month <= 11);
803  }
804  if (day().IsSmi()) {
805    int day = Smi::ToInt(this->day());
806    CHECK(1 <= day && day <= 31);
807  }
808  if (hour().IsSmi()) {
809    int hour = Smi::ToInt(this->hour());
810    CHECK(0 <= hour && hour <= 23);
811  }
812  if (min().IsSmi()) {
813    int min = Smi::ToInt(this->min());
814    CHECK(0 <= min && min <= 59);
815  }
816  if (sec().IsSmi()) {
817    int sec = Smi::ToInt(this->sec());
818    CHECK(0 <= sec && sec <= 59);
819  }
820  if (weekday().IsSmi()) {
821    int weekday = Smi::ToInt(this->weekday());
822    CHECK(0 <= weekday && weekday <= 6);
823  }
824  if (cache_stamp().IsSmi()) {
825    CHECK(Smi::ToInt(cache_stamp()) <=
826          Smi::ToInt(isolate->date_cache()->stamp()));
827  }
828}
829
830void String::StringVerify(Isolate* isolate) {
831  TorqueGeneratedClassVerifiers::StringVerify(*this, isolate);
832  CHECK(length() >= 0 && length() <= Smi::kMaxValue);
833  CHECK_IMPLIES(length() == 0, *this == ReadOnlyRoots(isolate).empty_string());
834  if (IsInternalizedString()) {
835    CHECK(!ObjectInYoungGeneration(*this));
836  }
837}
838
839void ConsString::ConsStringVerify(Isolate* isolate) {
840  TorqueGeneratedClassVerifiers::ConsStringVerify(*this, isolate);
841  CHECK_GE(length(), ConsString::kMinLength);
842  CHECK(length() == first().length() + second().length());
843  if (IsFlat(isolate)) {
844    // A flat cons can only be created by String::SlowFlatten.
845    // Afterwards, the first part may be externalized or internalized.
846    CHECK(first().IsSeqString() || first().IsExternalString() ||
847          first().IsThinString());
848  }
849}
850
851void ThinString::ThinStringVerify(Isolate* isolate) {
852  TorqueGeneratedClassVerifiers::ThinStringVerify(*this, isolate);
853  CHECK(actual().IsInternalizedString());
854  CHECK(actual().IsSeqString() || actual().IsExternalString());
855}
856
857void SlicedString::SlicedStringVerify(Isolate* isolate) {
858  TorqueGeneratedClassVerifiers::SlicedStringVerify(*this, isolate);
859  CHECK(!parent().IsConsString());
860  CHECK(!parent().IsSlicedString());
861  CHECK_GE(length(), SlicedString::kMinLength);
862}
863
864USE_TORQUE_VERIFIER(ExternalString)
865
866void JSBoundFunction::JSBoundFunctionVerify(Isolate* isolate) {
867  TorqueGeneratedClassVerifiers::JSBoundFunctionVerify(*this, isolate);
868  CHECK(IsCallable());
869  CHECK_EQ(IsConstructor(), bound_target_function().IsConstructor());
870}
871
872void JSFunction::JSFunctionVerify(Isolate* isolate) {
873  // Don't call TorqueGeneratedClassVerifiers::JSFunctionVerify here because the
874  // Torque class definition contains the field `prototype_or_initial_map` which
875  // may not be allocated.
876
877  // This assertion exists to encourage updating this verification function if
878  // new fields are added in the Torque class layout definition.
879  STATIC_ASSERT(JSFunction::TorqueGeneratedClass::kHeaderSize ==
880                8 * kTaggedSize);
881
882  JSFunctionOrBoundFunctionOrWrappedFunctionVerify(isolate);
883  CHECK(IsJSFunction());
884  VerifyPointer(isolate, shared(isolate));
885  CHECK(shared(isolate).IsSharedFunctionInfo());
886  VerifyPointer(isolate, context(isolate, kRelaxedLoad));
887  CHECK(context(isolate, kRelaxedLoad).IsContext());
888  VerifyPointer(isolate, raw_feedback_cell(isolate));
889  CHECK(raw_feedback_cell(isolate).IsFeedbackCell());
890  VerifyPointer(isolate, code(isolate));
891  CHECK(code(isolate).IsCodeT());
892  CHECK(map(isolate).is_callable());
893  Handle<JSFunction> function(*this, isolate);
894  LookupIterator it(isolate, function, isolate->factory()->prototype_string(),
895                    LookupIterator::OWN_SKIP_INTERCEPTOR);
896  if (has_prototype_slot()) {
897    VerifyObjectField(isolate, kPrototypeOrInitialMapOffset);
898  }
899
900  if (has_prototype_property()) {
901    CHECK(it.IsFound());
902    CHECK_EQ(LookupIterator::ACCESSOR, it.state());
903    CHECK(it.GetAccessors()->IsAccessorInfo());
904  } else {
905    CHECK(!it.IsFound() || it.state() != LookupIterator::ACCESSOR ||
906          !it.GetAccessors()->IsAccessorInfo());
907  }
908}
909
910void SharedFunctionInfo::SharedFunctionInfoVerify(Isolate* isolate) {
911  // TODO(leszeks): Add a TorqueGeneratedClassVerifier for LocalIsolate.
912  this->SharedFunctionInfoVerify(ReadOnlyRoots(isolate));
913}
914
915void SharedFunctionInfo::SharedFunctionInfoVerify(LocalIsolate* isolate) {
916  this->SharedFunctionInfoVerify(ReadOnlyRoots(isolate));
917}
918
919void SharedFunctionInfo::SharedFunctionInfoVerify(ReadOnlyRoots roots) {
920  Object value = name_or_scope_info(kAcquireLoad);
921  if (value.IsScopeInfo()) {
922    CHECK(!ScopeInfo::cast(value).IsEmpty());
923    CHECK_NE(value, roots.empty_scope_info());
924  }
925
926#if V8_ENABLE_WEBASSEMBLY
927  bool is_wasm = HasWasmExportedFunctionData() || HasAsmWasmData() ||
928                 HasWasmJSFunctionData() || HasWasmCapiFunctionData() ||
929                 HasWasmOnFulfilledData();
930#else
931  bool is_wasm = false;
932#endif  // V8_ENABLE_WEBASSEMBLY
933  CHECK(is_wasm || IsApiFunction() || HasBytecodeArray() || HasBuiltinId() ||
934        HasUncompiledDataWithPreparseData() ||
935        HasUncompiledDataWithoutPreparseData());
936
937  {
938    auto script = script_or_debug_info(kAcquireLoad);
939    CHECK(script.IsUndefined(roots) || script.IsScript() ||
940          script.IsDebugInfo());
941  }
942
943  if (!is_compiled()) {
944    CHECK(!HasFeedbackMetadata());
945    CHECK(outer_scope_info().IsScopeInfo() ||
946          outer_scope_info().IsTheHole(roots));
947  } else if (HasBytecodeArray() && HasFeedbackMetadata()) {
948    CHECK(feedback_metadata().IsFeedbackMetadata());
949  }
950
951  int expected_map_index =
952      Context::FunctionMapIndex(language_mode(), kind(), HasSharedName());
953  CHECK_EQ(expected_map_index, function_map_index());
954
955  if (!scope_info().IsEmpty()) {
956    ScopeInfo info = scope_info();
957    CHECK(kind() == info.function_kind());
958    CHECK_EQ(internal::IsModule(kind()), info.scope_type() == MODULE_SCOPE);
959  }
960
961  if (IsApiFunction()) {
962    CHECK(construct_as_builtin());
963  } else if (!HasBuiltinId()) {
964    CHECK(!construct_as_builtin());
965  } else {
966    if (builtin_id() != Builtin::kCompileLazy &&
967        builtin_id() != Builtin::kEmptyFunction) {
968      CHECK(construct_as_builtin());
969    } else {
970      CHECK(!construct_as_builtin());
971    }
972  }
973}
974
975void JSGlobalProxy::JSGlobalProxyVerify(Isolate* isolate) {
976  TorqueGeneratedClassVerifiers::JSGlobalProxyVerify(*this, isolate);
977  CHECK(map().is_access_check_needed());
978  // Make sure that this object has no properties, elements.
979  CHECK_EQ(0, FixedArray::cast(elements()).length());
980}
981
982void JSGlobalObject::JSGlobalObjectVerify(Isolate* isolate) {
983  CHECK(IsJSGlobalObject());
984  // Do not check the dummy global object for the builtins.
985  if (global_dictionary(kAcquireLoad).NumberOfElements() == 0 &&
986      elements().length() == 0) {
987    return;
988  }
989  JSObjectVerify(isolate);
990}
991
992void Oddball::OddballVerify(Isolate* isolate) {
993  PrimitiveHeapObjectVerify(isolate);
994  CHECK(IsOddball(isolate));
995
996  Heap* heap = isolate->heap();
997  Object string = to_string();
998  VerifyPointer(isolate, string);
999  CHECK(string.IsString());
1000  Object type = type_of();
1001  VerifyPointer(isolate, type);
1002  CHECK(type.IsString());
1003  Object kind_value = TaggedField<Object>::load(*this, kKindOffset);
1004  VerifyPointer(isolate, kind_value);
1005  CHECK(kind_value.IsSmi());
1006
1007  Object number = to_number();
1008  VerifyPointer(isolate, number);
1009  CHECK(number.IsSmi() || number.IsHeapNumber());
1010  if (number.IsHeapObject()) {
1011    CHECK(number == ReadOnlyRoots(heap).nan_value() ||
1012          number == ReadOnlyRoots(heap).hole_nan_value());
1013  } else {
1014    CHECK(number.IsSmi());
1015    int value = Smi::ToInt(number);
1016    // Hidden oddballs have negative smis.
1017    const int kLeastHiddenOddballNumber = -7;
1018    CHECK_LE(value, 1);
1019    CHECK_GE(value, kLeastHiddenOddballNumber);
1020  }
1021
1022  ReadOnlyRoots roots(heap);
1023  if (map() == roots.undefined_map()) {
1024    CHECK(*this == roots.undefined_value());
1025  } else if (map() == roots.the_hole_map()) {
1026    CHECK(*this == roots.the_hole_value());
1027  } else if (map() == roots.null_map()) {
1028    CHECK(*this == roots.null_value());
1029  } else if (map() == roots.boolean_map()) {
1030    CHECK(*this == roots.true_value() || *this == roots.false_value());
1031  } else if (map() == roots.uninitialized_map()) {
1032    CHECK(*this == roots.uninitialized_value());
1033  } else if (map() == roots.arguments_marker_map()) {
1034    CHECK(*this == roots.arguments_marker());
1035  } else if (map() == roots.termination_exception_map()) {
1036    CHECK(*this == roots.termination_exception());
1037  } else if (map() == roots.exception_map()) {
1038    CHECK(*this == roots.exception());
1039  } else if (map() == roots.optimized_out_map()) {
1040    CHECK(*this == roots.optimized_out());
1041  } else if (map() == roots.stale_register_map()) {
1042    CHECK(*this == roots.stale_register());
1043  } else if (map() == roots.self_reference_marker_map()) {
1044    // Multiple instances of this oddball may exist at once.
1045    CHECK_EQ(kind(), Oddball::kSelfReferenceMarker);
1046  } else if (map() == roots.basic_block_counters_marker_map()) {
1047    CHECK(*this == roots.basic_block_counters_marker());
1048  } else {
1049    UNREACHABLE();
1050  }
1051}
1052
1053void PropertyCell::PropertyCellVerify(Isolate* isolate) {
1054  TorqueGeneratedClassVerifiers::PropertyCellVerify(*this, isolate);
1055  CHECK(name().IsUniqueName());
1056  CheckDataIsCompatible(property_details(), value());
1057}
1058
1059void CodeDataContainer::CodeDataContainerVerify(Isolate* isolate) {
1060  CHECK(IsCodeDataContainer());
1061  VerifyObjectField(isolate, kNextCodeLinkOffset);
1062  CHECK(next_code_link().IsCodeT() || next_code_link().IsUndefined(isolate));
1063  if (V8_EXTERNAL_CODE_SPACE_BOOL) {
1064    if (raw_code() != Smi::zero()) {
1065#ifdef V8_EXTERNAL_CODE_SPACE
1066      // kind and builtin_id() getters are not available on CodeDataContainer
1067      // when external code space is not enabled.
1068      CHECK_EQ(code().kind(), kind());
1069      CHECK_EQ(code().builtin_id(), builtin_id());
1070#endif  // V8_EXTERNAL_CODE_SPACE
1071      CHECK_EQ(code().code_data_container(kAcquireLoad), *this);
1072
1073      // Ensure the cached code entry point corresponds to the Code object
1074      // associated with this CodeDataContainer.
1075#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
1076      if (V8_SHORT_BUILTIN_CALLS_BOOL) {
1077        if (code().InstructionStart() == code_entry_point()) {
1078          // Most common case, all good.
1079        } else {
1080          // When shared pointer compression cage is enabled and it has the
1081          // embedded code blob copy then the Code::InstructionStart() might
1082          // return address of the remapped builtin regardless of whether the
1083          // builtins copy exsisted when the code_entry_point value was cached
1084          // in the CodeDataContainer (see Code::OffHeapInstructionStart()).
1085          // So, do a reverse Code object lookup via code_entry_point value to
1086          // ensure it corresponds to the same Code object associated with this
1087          // CodeDataContainer.
1088          Code the_code = isolate->heap()->GcSafeFindCodeForInnerPointer(
1089              code_entry_point());
1090          CHECK_EQ(the_code, code());
1091        }
1092      } else {
1093        CHECK_EQ(code().InstructionStart(), code_entry_point());
1094      }
1095#else
1096      CHECK_EQ(code().InstructionStart(), code_entry_point());
1097#endif  // V8_COMPRESS_POINTERS_IN_SHARED_CAGE
1098    }
1099  }
1100}
1101
1102void Code::CodeVerify(Isolate* isolate) {
1103  CHECK(IsAligned(InstructionSize(),
1104                  static_cast<unsigned>(Code::kMetadataAlignment)));
1105  CHECK_EQ(safepoint_table_offset(), 0);
1106  CHECK_LE(safepoint_table_offset(), handler_table_offset());
1107  CHECK_LE(handler_table_offset(), constant_pool_offset());
1108  CHECK_LE(constant_pool_offset(), code_comments_offset());
1109  CHECK_LE(code_comments_offset(), unwinding_info_offset());
1110  CHECK_LE(unwinding_info_offset(), MetadataSize());
1111#if !defined(_MSC_VER) || defined(__clang__)
1112  // See also: PlatformEmbeddedFileWriterWin::AlignToCodeAlignment.
1113  CHECK_IMPLIES(!ReadOnlyHeap::Contains(*this),
1114                IsAligned(InstructionStart(), kCodeAlignment));
1115#endif  // !defined(_MSC_VER) || defined(__clang__)
1116  CHECK_IMPLIES(!ReadOnlyHeap::Contains(*this),
1117                IsAligned(raw_instruction_start(), kCodeAlignment));
1118  if (V8_EXTERNAL_CODE_SPACE_BOOL) {
1119    CHECK_EQ(*this, code_data_container(kAcquireLoad).code());
1120  }
1121  // TODO(delphick): Refactor Factory::CodeBuilder::BuildInternal, so that the
1122  // following CHECK works builtin trampolines. It currently fails because
1123  // CodeVerify is called halfway through constructing the trampoline and so not
1124  // everything is set up.
1125  // CHECK_EQ(ReadOnlyHeap::Contains(*this), !IsExecutable());
1126  relocation_info().ObjectVerify(isolate);
1127  CHECK(V8_ENABLE_THIRD_PARTY_HEAP_BOOL ||
1128        CodeSize() <= MemoryChunkLayout::MaxRegularCodeObjectSize() ||
1129        isolate->heap()->InSpace(*this, CODE_LO_SPACE));
1130  Address last_gc_pc = kNullAddress;
1131
1132  for (RelocIterator it(*this); !it.done(); it.next()) {
1133    it.rinfo()->Verify(isolate);
1134    // Ensure that GC will not iterate twice over the same pointer.
1135    if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
1136      CHECK(it.rinfo()->pc() != last_gc_pc);
1137      last_gc_pc = it.rinfo()->pc();
1138    }
1139  }
1140}
1141
1142void JSArray::JSArrayVerify(Isolate* isolate) {
1143  TorqueGeneratedClassVerifiers::JSArrayVerify(*this, isolate);
1144  // If a GC was caused while constructing this array, the elements
1145  // pointer may point to a one pointer filler map.
1146  if (!ElementsAreSafeToExamine(isolate)) return;
1147  if (elements().IsUndefined(isolate)) return;
1148  CHECK(elements().IsFixedArray() || elements().IsFixedDoubleArray());
1149  if (elements().length() == 0) {
1150    CHECK_EQ(elements(), ReadOnlyRoots(isolate).empty_fixed_array());
1151  }
1152  // Verify that the length and the elements backing store are in sync.
1153  if (length().IsSmi() &&
1154      (HasFastElements() || HasAnyNonextensibleElements())) {
1155    if (elements().length() > 0) {
1156      CHECK_IMPLIES(HasDoubleElements(), elements().IsFixedDoubleArray());
1157      CHECK_IMPLIES(HasSmiOrObjectElements() || HasAnyNonextensibleElements(),
1158                    elements().IsFixedArray());
1159    }
1160    int size = Smi::ToInt(length());
1161    // Holey / Packed backing stores might have slack or might have not been
1162    // properly initialized yet.
1163    CHECK(size <= elements().length() ||
1164          elements() == ReadOnlyRoots(isolate).empty_fixed_array());
1165  } else {
1166    CHECK(HasDictionaryElements());
1167    uint32_t array_length;
1168    CHECK(length().ToArrayLength(&array_length));
1169    if (array_length == 0xFFFFFFFF) {
1170      CHECK(length().ToArrayLength(&array_length));
1171    }
1172    if (array_length != 0) {
1173      NumberDictionary dict = NumberDictionary::cast(elements());
1174      // The dictionary can never have more elements than the array length + 1.
1175      // If the backing store grows the verification might be triggered with
1176      // the old length in place.
1177      uint32_t nof_elements = static_cast<uint32_t>(dict.NumberOfElements());
1178      if (nof_elements != 0) nof_elements--;
1179      CHECK_LE(nof_elements, array_length);
1180    }
1181  }
1182}
1183
1184void JSSet::JSSetVerify(Isolate* isolate) {
1185  TorqueGeneratedClassVerifiers::JSSetVerify(*this, isolate);
1186  CHECK(table().IsOrderedHashSet() || table().IsUndefined(isolate));
1187  // TODO(arv): Verify OrderedHashTable too.
1188}
1189
1190void JSMap::JSMapVerify(Isolate* isolate) {
1191  TorqueGeneratedClassVerifiers::JSMapVerify(*this, isolate);
1192  CHECK(table().IsOrderedHashMap() || table().IsUndefined(isolate));
1193  // TODO(arv): Verify OrderedHashTable too.
1194}
1195
1196void JSSetIterator::JSSetIteratorVerify(Isolate* isolate) {
1197  CHECK(IsJSSetIterator());
1198  JSCollectionIteratorVerify(isolate);
1199  CHECK(table().IsOrderedHashSet());
1200  CHECK(index().IsSmi());
1201}
1202
1203void JSMapIterator::JSMapIteratorVerify(Isolate* isolate) {
1204  CHECK(IsJSMapIterator());
1205  JSCollectionIteratorVerify(isolate);
1206  CHECK(table().IsOrderedHashMap());
1207  CHECK(index().IsSmi());
1208}
1209
1210USE_TORQUE_VERIFIER(JSShadowRealm)
1211USE_TORQUE_VERIFIER(JSWrappedFunction)
1212
1213void JSSharedStruct::JSSharedStructVerify(Isolate* isolate) {
1214  CHECK(IsJSSharedStruct());
1215  JSObjectVerify(isolate);
1216  CHECK(HasFastProperties());
1217  // Shared structs can only point to primitives or other shared HeapObjects,
1218  // even internally.
1219  // TODO(v8:12547): Generalize shared -> shared pointer verification.
1220  Map struct_map = map();
1221  CHECK(struct_map.InSharedHeap());
1222  CHECK(struct_map.GetBackPointer().IsUndefined(isolate));
1223  Object maybe_cell = struct_map.prototype_validity_cell();
1224  if (maybe_cell.IsCell()) CHECK(maybe_cell.InSharedHeap());
1225  CHECK(!struct_map.is_extensible());
1226  CHECK(!struct_map.is_prototype_map());
1227  CHECK(property_array().InSharedHeap());
1228  DescriptorArray descriptors = struct_map.instance_descriptors(isolate);
1229  CHECK(descriptors.InSharedHeap());
1230  for (InternalIndex i : struct_map.IterateOwnDescriptors()) {
1231    PropertyDetails details = descriptors.GetDetails(i);
1232    CHECK_EQ(PropertyKind::kData, details.kind());
1233    CHECK_EQ(PropertyLocation::kField, details.location());
1234    CHECK(details.representation().IsTagged());
1235    CHECK(
1236        RawFastPropertyAt(FieldIndex::ForDescriptor(struct_map, i)).IsShared());
1237  }
1238}
1239
1240void WeakCell::WeakCellVerify(Isolate* isolate) {
1241  CHECK(IsWeakCell());
1242
1243  CHECK(target().IsUndefined(isolate) || target().CanBeHeldWeakly());
1244
1245  CHECK(prev().IsWeakCell() || prev().IsUndefined(isolate));
1246  if (prev().IsWeakCell()) {
1247    CHECK_EQ(WeakCell::cast(prev()).next(), *this);
1248  }
1249
1250  CHECK(next().IsWeakCell() || next().IsUndefined(isolate));
1251  if (next().IsWeakCell()) {
1252    CHECK_EQ(WeakCell::cast(next()).prev(), *this);
1253  }
1254
1255  CHECK_IMPLIES(unregister_token().IsUndefined(isolate),
1256                key_list_prev().IsUndefined(isolate));
1257  CHECK_IMPLIES(unregister_token().IsUndefined(isolate),
1258                key_list_next().IsUndefined(isolate));
1259
1260  CHECK(key_list_prev().IsWeakCell() || key_list_prev().IsUndefined(isolate));
1261
1262  CHECK(key_list_next().IsWeakCell() || key_list_next().IsUndefined(isolate));
1263
1264  CHECK(finalization_registry().IsUndefined(isolate) ||
1265        finalization_registry().IsJSFinalizationRegistry());
1266}
1267
1268void JSWeakRef::JSWeakRefVerify(Isolate* isolate) {
1269  CHECK(IsJSWeakRef());
1270  JSObjectVerify(isolate);
1271  CHECK(target().IsUndefined(isolate) || target().CanBeHeldWeakly());
1272}
1273
1274void JSFinalizationRegistry::JSFinalizationRegistryVerify(Isolate* isolate) {
1275  TorqueGeneratedClassVerifiers::JSFinalizationRegistryVerify(*this, isolate);
1276  if (active_cells().IsWeakCell()) {
1277    CHECK(WeakCell::cast(active_cells()).prev().IsUndefined(isolate));
1278  }
1279  if (cleared_cells().IsWeakCell()) {
1280    CHECK(WeakCell::cast(cleared_cells()).prev().IsUndefined(isolate));
1281  }
1282}
1283
1284void JSWeakMap::JSWeakMapVerify(Isolate* isolate) {
1285  TorqueGeneratedClassVerifiers::JSWeakMapVerify(*this, isolate);
1286  CHECK(table().IsEphemeronHashTable() || table().IsUndefined(isolate));
1287}
1288
1289void JSArrayIterator::JSArrayIteratorVerify(Isolate* isolate) {
1290  TorqueGeneratedClassVerifiers::JSArrayIteratorVerify(*this, isolate);
1291
1292  CHECK_GE(next_index().Number(), 0);
1293  CHECK_LE(next_index().Number(), kMaxSafeInteger);
1294
1295  if (iterated_object().IsJSTypedArray()) {
1296    // JSTypedArray::length is limited to Smi range.
1297    CHECK(next_index().IsSmi());
1298    CHECK_LE(next_index().Number(), Smi::kMaxValue);
1299  } else if (iterated_object().IsJSArray()) {
1300    // JSArray::length is limited to Uint32 range.
1301    CHECK_LE(next_index().Number(), kMaxUInt32);
1302  }
1303}
1304
1305void JSStringIterator::JSStringIteratorVerify(Isolate* isolate) {
1306  TorqueGeneratedClassVerifiers::JSStringIteratorVerify(*this, isolate);
1307  CHECK_GE(index(), 0);
1308  CHECK_LE(index(), String::kMaxLength);
1309}
1310
1311void JSWeakSet::JSWeakSetVerify(Isolate* isolate) {
1312  TorqueGeneratedClassVerifiers::JSWeakSetVerify(*this, isolate);
1313  CHECK(table().IsEphemeronHashTable() || table().IsUndefined(isolate));
1314}
1315
1316void CallableTask::CallableTaskVerify(Isolate* isolate) {
1317  TorqueGeneratedClassVerifiers::CallableTaskVerify(*this, isolate);
1318  CHECK(callable().IsCallable());
1319}
1320
1321void JSPromise::JSPromiseVerify(Isolate* isolate) {
1322  TorqueGeneratedClassVerifiers::JSPromiseVerify(*this, isolate);
1323  if (status() == Promise::kPending) {
1324    CHECK(reactions().IsSmi() || reactions().IsPromiseReaction());
1325  }
1326}
1327
1328template <typename Derived>
1329void SmallOrderedHashTable<Derived>::SmallOrderedHashTableVerify(
1330    Isolate* isolate) {
1331  CHECK(IsSmallOrderedHashTable());
1332
1333  int capacity = Capacity();
1334  CHECK_GE(capacity, kMinCapacity);
1335  CHECK_LE(capacity, kMaxCapacity);
1336
1337  for (int entry = 0; entry < NumberOfBuckets(); entry++) {
1338    int bucket = GetFirstEntry(entry);
1339    if (bucket == kNotFound) continue;
1340    CHECK_GE(bucket, 0);
1341    CHECK_LE(bucket, capacity);
1342  }
1343
1344  for (int entry = 0; entry < NumberOfElements(); entry++) {
1345    int chain = GetNextEntry(entry);
1346    if (chain == kNotFound) continue;
1347    CHECK_GE(chain, 0);
1348    CHECK_LE(chain, capacity);
1349  }
1350
1351  for (int entry = 0; entry < NumberOfElements(); entry++) {
1352    for (int offset = 0; offset < Derived::kEntrySize; offset++) {
1353      Object val = GetDataEntry(entry, offset);
1354      VerifyPointer(isolate, val);
1355    }
1356  }
1357
1358  for (int entry = NumberOfElements() + NumberOfDeletedElements();
1359       entry < Capacity(); entry++) {
1360    for (int offset = 0; offset < Derived::kEntrySize; offset++) {
1361      Object val = GetDataEntry(entry, offset);
1362      CHECK(val.IsTheHole(isolate));
1363    }
1364  }
1365}
1366
1367void SmallOrderedHashMap::SmallOrderedHashMapVerify(Isolate* isolate) {
1368  CHECK(IsSmallOrderedHashMap());
1369  SmallOrderedHashTable<SmallOrderedHashMap>::SmallOrderedHashTableVerify(
1370      isolate);
1371  for (int entry = NumberOfElements(); entry < NumberOfDeletedElements();
1372       entry++) {
1373    for (int offset = 0; offset < kEntrySize; offset++) {
1374      Object val = GetDataEntry(entry, offset);
1375      CHECK(val.IsTheHole(isolate));
1376    }
1377  }
1378}
1379
1380void SmallOrderedHashSet::SmallOrderedHashSetVerify(Isolate* isolate) {
1381  CHECK(IsSmallOrderedHashSet());
1382  SmallOrderedHashTable<SmallOrderedHashSet>::SmallOrderedHashTableVerify(
1383      isolate);
1384  for (int entry = NumberOfElements(); entry < NumberOfDeletedElements();
1385       entry++) {
1386    for (int offset = 0; offset < kEntrySize; offset++) {
1387      Object val = GetDataEntry(entry, offset);
1388      CHECK(val.IsTheHole(isolate));
1389    }
1390  }
1391}
1392
1393void SmallOrderedNameDictionary::SmallOrderedNameDictionaryVerify(
1394    Isolate* isolate) {
1395  CHECK(IsSmallOrderedNameDictionary());
1396  SmallOrderedHashTable<
1397      SmallOrderedNameDictionary>::SmallOrderedHashTableVerify(isolate);
1398  for (int entry = NumberOfElements(); entry < NumberOfDeletedElements();
1399       entry++) {
1400    for (int offset = 0; offset < kEntrySize; offset++) {
1401      Object val = GetDataEntry(entry, offset);
1402      CHECK(val.IsTheHole(isolate) ||
1403            (PropertyDetails::Empty().AsSmi() == Smi::cast(val)));
1404    }
1405  }
1406}
1407
1408void SwissNameDictionary::SwissNameDictionaryVerify(Isolate* isolate) {
1409  this->SwissNameDictionaryVerify(isolate, false);
1410}
1411
1412void SwissNameDictionary::SwissNameDictionaryVerify(Isolate* isolate,
1413                                                    bool slow_checks) {
1414  DisallowHeapAllocation no_gc;
1415
1416  CHECK(IsValidCapacity(Capacity()));
1417
1418  meta_table().ByteArrayVerify(isolate);
1419
1420  int seen_deleted = 0;
1421  int seen_present = 0;
1422
1423  for (int i = 0; i < Capacity(); i++) {
1424    ctrl_t ctrl = GetCtrl(i);
1425
1426    if (IsFull(ctrl) || slow_checks) {
1427      Object key = KeyAt(i);
1428      Object value = ValueAtRaw(i);
1429
1430      if (IsFull(ctrl)) {
1431        ++seen_present;
1432
1433        Name name = Name::cast(key);
1434        if (slow_checks) {
1435          CHECK_EQ(swiss_table::H2(name.hash()), ctrl);
1436        }
1437
1438        CHECK(!key.IsTheHole());
1439        CHECK(!value.IsTheHole());
1440        name.NameVerify(isolate);
1441        value.ObjectVerify(isolate);
1442      } else if (IsDeleted(ctrl)) {
1443        ++seen_deleted;
1444        CHECK(key.IsTheHole());
1445        CHECK(value.IsTheHole());
1446      } else if (IsEmpty(ctrl)) {
1447        CHECK(key.IsTheHole());
1448        CHECK(value.IsTheHole());
1449      } else {
1450        // Something unexpected. Note that we don't use kSentinel at the moment.
1451        UNREACHABLE();
1452      }
1453    }
1454  }
1455
1456  CHECK_EQ(seen_present, NumberOfElements());
1457  if (slow_checks) {
1458    CHECK_EQ(seen_deleted, NumberOfDeletedElements());
1459
1460    // Verify copy of first group at end (= after Capacity() slots) of control
1461    // table.
1462    for (int i = 0; i < std::min(static_cast<int>(Group::kWidth), Capacity());
1463         ++i) {
1464      CHECK_EQ(CtrlTable()[i], CtrlTable()[Capacity() + i]);
1465    }
1466    // If 2 * capacity is smaller than the capacity plus group width, the slots
1467    // after that must be empty.
1468    for (int i = 2 * Capacity(); i < Capacity() + kGroupWidth; ++i) {
1469      CHECK_EQ(Ctrl::kEmpty, CtrlTable()[i]);
1470    }
1471
1472    for (int enum_index = 0; enum_index < UsedCapacity(); ++enum_index) {
1473      int entry = EntryForEnumerationIndex(enum_index);
1474      CHECK_LT(entry, Capacity());
1475      ctrl_t ctrl = GetCtrl(entry);
1476
1477      // Enum table must not point to empty slots.
1478      CHECK(IsFull(ctrl) || IsDeleted(ctrl));
1479    }
1480  }
1481}
1482
1483void JSRegExp::JSRegExpVerify(Isolate* isolate) {
1484  TorqueGeneratedClassVerifiers::JSRegExpVerify(*this, isolate);
1485  switch (type_tag()) {
1486    case JSRegExp::ATOM: {
1487      FixedArray arr = FixedArray::cast(data());
1488      CHECK(arr.get(JSRegExp::kAtomPatternIndex).IsString());
1489      break;
1490    }
1491    case JSRegExp::EXPERIMENTAL: {
1492      FixedArray arr = FixedArray::cast(data());
1493      Smi uninitialized = Smi::FromInt(JSRegExp::kUninitializedValue);
1494
1495      Object latin1_code = arr.get(JSRegExp::kIrregexpLatin1CodeIndex);
1496      Object uc16_code = arr.get(JSRegExp::kIrregexpUC16CodeIndex);
1497      Object latin1_bytecode = arr.get(JSRegExp::kIrregexpLatin1BytecodeIndex);
1498      Object uc16_bytecode = arr.get(JSRegExp::kIrregexpUC16BytecodeIndex);
1499
1500      bool is_compiled = latin1_code.IsCodeT();
1501      if (is_compiled) {
1502        CHECK_EQ(FromCodeT(CodeT::cast(latin1_code)).builtin_id(),
1503                 Builtin::kRegExpExperimentalTrampoline);
1504        CHECK_EQ(uc16_code, latin1_code);
1505
1506        CHECK(latin1_bytecode.IsByteArray());
1507        CHECK_EQ(uc16_bytecode, latin1_bytecode);
1508      } else {
1509        CHECK_EQ(latin1_code, uninitialized);
1510        CHECK_EQ(uc16_code, uninitialized);
1511
1512        CHECK_EQ(latin1_bytecode, uninitialized);
1513        CHECK_EQ(uc16_bytecode, uninitialized);
1514      }
1515
1516      CHECK_EQ(arr.get(JSRegExp::kIrregexpMaxRegisterCountIndex),
1517               uninitialized);
1518      CHECK(arr.get(JSRegExp::kIrregexpCaptureCountIndex).IsSmi());
1519      CHECK_GE(Smi::ToInt(arr.get(JSRegExp::kIrregexpCaptureCountIndex)), 0);
1520      CHECK_EQ(arr.get(JSRegExp::kIrregexpTicksUntilTierUpIndex),
1521               uninitialized);
1522      CHECK_EQ(arr.get(JSRegExp::kIrregexpBacktrackLimit), uninitialized);
1523      break;
1524    }
1525    case JSRegExp::IRREGEXP: {
1526      bool can_be_interpreted = RegExp::CanGenerateBytecode();
1527
1528      FixedArray arr = FixedArray::cast(data());
1529      Object one_byte_data = arr.get(JSRegExp::kIrregexpLatin1CodeIndex);
1530      // Smi : Not compiled yet (-1).
1531      // Code: Compiled irregexp code or trampoline to the interpreter.
1532      CHECK((one_byte_data.IsSmi() &&
1533             Smi::ToInt(one_byte_data) == JSRegExp::kUninitializedValue) ||
1534            one_byte_data.IsCodeT());
1535      Object uc16_data = arr.get(JSRegExp::kIrregexpUC16CodeIndex);
1536      CHECK((uc16_data.IsSmi() &&
1537             Smi::ToInt(uc16_data) == JSRegExp::kUninitializedValue) ||
1538            uc16_data.IsCodeT());
1539
1540      Object one_byte_bytecode =
1541          arr.get(JSRegExp::kIrregexpLatin1BytecodeIndex);
1542      // Smi : Not compiled yet (-1).
1543      // ByteArray: Bytecode to interpret regexp.
1544      CHECK((one_byte_bytecode.IsSmi() &&
1545             Smi::ToInt(one_byte_bytecode) == JSRegExp::kUninitializedValue) ||
1546            (can_be_interpreted && one_byte_bytecode.IsByteArray()));
1547      Object uc16_bytecode = arr.get(JSRegExp::kIrregexpUC16BytecodeIndex);
1548      CHECK((uc16_bytecode.IsSmi() &&
1549             Smi::ToInt(uc16_bytecode) == JSRegExp::kUninitializedValue) ||
1550            (can_be_interpreted && uc16_bytecode.IsByteArray()));
1551
1552      CHECK_IMPLIES(one_byte_data.IsSmi(), one_byte_bytecode.IsSmi());
1553      CHECK_IMPLIES(uc16_data.IsSmi(), uc16_bytecode.IsSmi());
1554
1555      CHECK(arr.get(JSRegExp::kIrregexpCaptureCountIndex).IsSmi());
1556      CHECK_GE(Smi::ToInt(arr.get(JSRegExp::kIrregexpCaptureCountIndex)), 0);
1557      CHECK(arr.get(JSRegExp::kIrregexpMaxRegisterCountIndex).IsSmi());
1558      CHECK(arr.get(JSRegExp::kIrregexpTicksUntilTierUpIndex).IsSmi());
1559      CHECK(arr.get(JSRegExp::kIrregexpBacktrackLimit).IsSmi());
1560      break;
1561    }
1562    default:
1563      CHECK_EQ(JSRegExp::NOT_COMPILED, type_tag());
1564      CHECK(data().IsUndefined(isolate));
1565      break;
1566  }
1567}
1568
1569void JSProxy::JSProxyVerify(Isolate* isolate) {
1570  TorqueGeneratedClassVerifiers::JSProxyVerify(*this, isolate);
1571  CHECK(map().GetConstructor().IsJSFunction());
1572  if (!IsRevoked()) {
1573    CHECK_EQ(target().IsCallable(), map().is_callable());
1574    CHECK_EQ(target().IsConstructor(), map().is_constructor());
1575  }
1576  CHECK(map().prototype().IsNull(isolate));
1577  // There should be no properties on a Proxy.
1578  CHECK_EQ(0, map().NumberOfOwnDescriptors());
1579}
1580
1581void JSArrayBuffer::JSArrayBufferVerify(Isolate* isolate) {
1582  TorqueGeneratedClassVerifiers::JSArrayBufferVerify(*this, isolate);
1583  if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
1584    CHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
1585    CHECK_EQ(0,
1586             *reinterpret_cast<uint32_t*>(address() + kOptionalPaddingOffset));
1587  }
1588}
1589
1590void JSArrayBufferView::JSArrayBufferViewVerify(Isolate* isolate) {
1591  TorqueGeneratedClassVerifiers::JSArrayBufferViewVerify(*this, isolate);
1592  CHECK_LE(byte_length(), JSArrayBuffer::kMaxByteLength);
1593  CHECK_LE(byte_offset(), JSArrayBuffer::kMaxByteLength);
1594}
1595
1596void JSTypedArray::JSTypedArrayVerify(Isolate* isolate) {
1597  TorqueGeneratedClassVerifiers::JSTypedArrayVerify(*this, isolate);
1598  CHECK_LE(GetLength(), JSTypedArray::kMaxLength);
1599}
1600
1601void JSDataView::JSDataViewVerify(Isolate* isolate) {
1602  TorqueGeneratedClassVerifiers::JSDataViewVerify(*this, isolate);
1603  if (!WasDetached()) {
1604    CHECK_EQ(reinterpret_cast<uint8_t*>(
1605                 JSArrayBuffer::cast(buffer()).backing_store()) +
1606                 byte_offset(),
1607             data_pointer());
1608  }
1609}
1610
1611void AsyncGeneratorRequest::AsyncGeneratorRequestVerify(Isolate* isolate) {
1612  TorqueGeneratedClassVerifiers::AsyncGeneratorRequestVerify(*this, isolate);
1613  CHECK_GE(resume_mode(), JSGeneratorObject::kNext);
1614  CHECK_LE(resume_mode(), JSGeneratorObject::kThrow);
1615}
1616
1617void BigIntBase::BigIntBaseVerify(Isolate* isolate) {
1618  CHECK_GE(length(), 0);
1619  CHECK_IMPLIES(is_zero(), !sign());  // There is no -0n.
1620}
1621
1622void SourceTextModuleInfoEntry::SourceTextModuleInfoEntryVerify(
1623    Isolate* isolate) {
1624  TorqueGeneratedClassVerifiers::SourceTextModuleInfoEntryVerify(*this,
1625                                                                 isolate);
1626  CHECK_IMPLIES(import_name().IsString(), module_request() >= 0);
1627  CHECK_IMPLIES(export_name().IsString() && import_name().IsString(),
1628                local_name().IsUndefined(isolate));
1629}
1630
1631void Module::ModuleVerify(Isolate* isolate) {
1632  TorqueGeneratedClassVerifiers::ModuleVerify(*this, isolate);
1633
1634  CHECK_EQ(status() == Module::kErrored, !exception().IsTheHole(isolate));
1635
1636  CHECK(module_namespace().IsUndefined(isolate) ||
1637        module_namespace().IsJSModuleNamespace());
1638  if (module_namespace().IsJSModuleNamespace()) {
1639    CHECK_LE(Module::kLinking, status());
1640    CHECK_EQ(JSModuleNamespace::cast(module_namespace()).module(), *this);
1641  }
1642
1643  if (!(status() == kErrored || status() == kEvaluating ||
1644        status() == kEvaluated)) {
1645    CHECK(top_level_capability().IsUndefined());
1646  }
1647
1648  CHECK_NE(hash(), 0);
1649}
1650
1651void ModuleRequest::ModuleRequestVerify(Isolate* isolate) {
1652  TorqueGeneratedClassVerifiers::ModuleRequestVerify(*this, isolate);
1653  CHECK_EQ(0,
1654           import_assertions().length() % ModuleRequest::kAssertionEntrySize);
1655
1656  for (int i = 0; i < import_assertions().length();
1657       i += ModuleRequest::kAssertionEntrySize) {
1658    CHECK(import_assertions().get(i).IsString());      // Assertion key
1659    CHECK(import_assertions().get(i + 1).IsString());  // Assertion value
1660    CHECK(import_assertions().get(i + 2).IsSmi());     // Assertion location
1661  }
1662}
1663
1664void SourceTextModule::SourceTextModuleVerify(Isolate* isolate) {
1665  TorqueGeneratedClassVerifiers::SourceTextModuleVerify(*this, isolate);
1666
1667  if (status() == kErrored) {
1668    CHECK(code().IsSharedFunctionInfo());
1669  } else if (status() == kEvaluating || status() == kEvaluated) {
1670    CHECK(code().IsJSGeneratorObject());
1671  } else {
1672    if (status() == kLinked) {
1673      CHECK(code().IsJSGeneratorObject());
1674    } else if (status() == kLinking) {
1675      CHECK(code().IsJSFunction());
1676    } else if (status() == kPreLinking) {
1677      CHECK(code().IsSharedFunctionInfo());
1678    } else if (status() == kUnlinked) {
1679      CHECK(code().IsSharedFunctionInfo());
1680    }
1681    CHECK(!AsyncParentModuleCount());
1682    CHECK(!pending_async_dependencies());
1683    CHECK(!IsAsyncEvaluating());
1684  }
1685
1686  CHECK_EQ(requested_modules().length(), info().module_requests().length());
1687}
1688
1689void SyntheticModule::SyntheticModuleVerify(Isolate* isolate) {
1690  TorqueGeneratedClassVerifiers::SyntheticModuleVerify(*this, isolate);
1691
1692  for (int i = 0; i < export_names().length(); i++) {
1693    CHECK(export_names().get(i).IsString());
1694  }
1695}
1696
1697void PrototypeInfo::PrototypeInfoVerify(Isolate* isolate) {
1698  TorqueGeneratedClassVerifiers::PrototypeInfoVerify(*this, isolate);
1699  if (prototype_users().IsWeakArrayList()) {
1700    PrototypeUsers::Verify(WeakArrayList::cast(prototype_users()));
1701  } else {
1702    CHECK(prototype_users().IsSmi());
1703  }
1704}
1705
1706void PrototypeUsers::Verify(WeakArrayList array) {
1707  if (array.length() == 0) {
1708    // Allow empty & uninitialized lists.
1709    return;
1710  }
1711  // Verify empty slot chain.
1712  int empty_slot = Smi::ToInt(empty_slot_index(array));
1713  int empty_slots_count = 0;
1714  while (empty_slot != kNoEmptySlotsMarker) {
1715    CHECK_GT(empty_slot, 0);
1716    CHECK_LT(empty_slot, array.length());
1717    empty_slot = array.Get(empty_slot).ToSmi().value();
1718    ++empty_slots_count;
1719  }
1720
1721  // Verify that all elements are either weak pointers or SMIs marking empty
1722  // slots.
1723  int weak_maps_count = 0;
1724  for (int i = kFirstIndex; i < array.length(); ++i) {
1725    HeapObject heap_object;
1726    MaybeObject object = array.Get(i);
1727    if ((object->GetHeapObjectIfWeak(&heap_object) && heap_object.IsMap()) ||
1728        object->IsCleared()) {
1729      ++weak_maps_count;
1730    } else {
1731      CHECK(object->IsSmi());
1732    }
1733  }
1734
1735  CHECK_EQ(weak_maps_count + empty_slots_count + 1, array.length());
1736}
1737
1738void EnumCache::EnumCacheVerify(Isolate* isolate) {
1739  TorqueGeneratedClassVerifiers::EnumCacheVerify(*this, isolate);
1740  Heap* heap = isolate->heap();
1741  if (*this == ReadOnlyRoots(heap).empty_enum_cache()) {
1742    CHECK_EQ(ReadOnlyRoots(heap).empty_fixed_array(), keys());
1743    CHECK_EQ(ReadOnlyRoots(heap).empty_fixed_array(), indices());
1744  }
1745}
1746
1747void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionVerify(
1748    Isolate* isolate) {
1749  CHECK(IsObjectBoilerplateDescription());
1750  CHECK_GE(this->length(),
1751           ObjectBoilerplateDescription::kDescriptionStartIndex);
1752  this->FixedArrayVerify(isolate);
1753  for (int i = 0; i < length(); ++i) {
1754    // No ThinStrings in the boilerplate.
1755    CHECK(!get(isolate, i).IsThinString(isolate));
1756  }
1757}
1758
1759#if V8_ENABLE_WEBASSEMBLY
1760
1761void WasmInstanceObject::WasmInstanceObjectVerify(Isolate* isolate) {
1762  JSObjectVerify(isolate);
1763  CHECK(IsWasmInstanceObject());
1764
1765  // Just generically check all tagged fields. Don't check the untagged fields,
1766  // as some of them might still contain the "undefined" value if the
1767  // WasmInstanceObject is not fully set up yet.
1768  for (int offset = kHeaderSize; offset < kEndOfStrongFieldsOffset;
1769       offset += kTaggedSize) {
1770    VerifyObjectField(isolate, offset);
1771  }
1772}
1773
1774void WasmValueObject::WasmValueObjectVerify(Isolate* isolate) {
1775  JSObjectVerify(isolate);
1776  CHECK(IsWasmValueObject());
1777}
1778
1779void WasmExportedFunctionData::WasmExportedFunctionDataVerify(
1780    Isolate* isolate) {
1781  TorqueGeneratedClassVerifiers::WasmExportedFunctionDataVerify(*this, isolate);
1782  CHECK(
1783      wrapper_code().kind() == CodeKind::JS_TO_WASM_FUNCTION ||
1784      wrapper_code().kind() == CodeKind::C_WASM_ENTRY ||
1785      (wrapper_code().is_builtin() &&
1786       (wrapper_code().builtin_id() == Builtin::kGenericJSToWasmWrapper ||
1787        wrapper_code().builtin_id() == Builtin::kWasmReturnPromiseOnSuspend)));
1788}
1789
1790#endif  // V8_ENABLE_WEBASSEMBLY
1791
1792void DataHandler::DataHandlerVerify(Isolate* isolate) {
1793  // Don't call TorqueGeneratedClassVerifiers::DataHandlerVerify because the
1794  // Torque definition of this class includes all of the optional fields.
1795
1796  // This assertion exists to encourage updating this verification function if
1797  // new fields are added in the Torque class layout definition.
1798  STATIC_ASSERT(DataHandler::kHeaderSize == 6 * kTaggedSize);
1799
1800  StructVerify(isolate);
1801  CHECK(IsDataHandler());
1802  VerifyPointer(isolate, smi_handler(isolate));
1803  CHECK_IMPLIES(!smi_handler().IsSmi(),
1804                IsStoreHandler() && smi_handler().IsCodeT());
1805  VerifyPointer(isolate, validity_cell(isolate));
1806  CHECK(validity_cell().IsSmi() || validity_cell().IsCell());
1807  int data_count = data_field_count();
1808  if (data_count >= 1) {
1809    VerifyMaybeObjectField(isolate, kData1Offset);
1810  }
1811  if (data_count >= 2) {
1812    VerifyMaybeObjectField(isolate, kData2Offset);
1813  }
1814  if (data_count >= 3) {
1815    VerifyMaybeObjectField(isolate, kData3Offset);
1816  }
1817}
1818
1819void LoadHandler::LoadHandlerVerify(Isolate* isolate) {
1820  DataHandler::DataHandlerVerify(isolate);
1821  // TODO(ishell): check handler integrity
1822}
1823
1824void StoreHandler::StoreHandlerVerify(Isolate* isolate) {
1825  DataHandler::DataHandlerVerify(isolate);
1826  // TODO(ishell): check handler integrity
1827}
1828
1829void CallHandlerInfo::CallHandlerInfoVerify(Isolate* isolate) {
1830  TorqueGeneratedClassVerifiers::CallHandlerInfoVerify(*this, isolate);
1831  CHECK(map() == ReadOnlyRoots(isolate).side_effect_call_handler_info_map() ||
1832        map() ==
1833            ReadOnlyRoots(isolate).side_effect_free_call_handler_info_map() ||
1834        map() == ReadOnlyRoots(isolate)
1835                     .next_call_side_effect_free_call_handler_info_map());
1836}
1837
1838void AllocationSite::AllocationSiteVerify(Isolate* isolate) {
1839  CHECK(IsAllocationSite());
1840  CHECK(dependent_code().IsDependentCode());
1841  CHECK(transition_info_or_boilerplate().IsSmi() ||
1842        transition_info_or_boilerplate().IsJSObject());
1843  CHECK(nested_site().IsAllocationSite() || nested_site() == Smi::zero());
1844}
1845
1846void Script::ScriptVerify(Isolate* isolate) {
1847  TorqueGeneratedClassVerifiers::ScriptVerify(*this, isolate);
1848  if V8_UNLIKELY (type() == Script::TYPE_WEB_SNAPSHOT) {
1849    CHECK_LE(shared_function_info_count(), shared_function_infos().length());
1850  } else {
1851    // No overallocating shared_function_infos.
1852    CHECK_EQ(shared_function_info_count(), shared_function_infos().length());
1853  }
1854  for (int i = 0; i < shared_function_info_count(); ++i) {
1855    MaybeObject maybe_object = shared_function_infos().Get(i);
1856    HeapObject heap_object;
1857    CHECK(maybe_object->IsWeak() || maybe_object->IsCleared() ||
1858          (maybe_object->GetHeapObjectIfStrong(&heap_object) &&
1859           heap_object.IsUndefined(isolate)));
1860  }
1861}
1862
1863void NormalizedMapCache::NormalizedMapCacheVerify(Isolate* isolate) {
1864  WeakFixedArray::cast(*this).WeakFixedArrayVerify(isolate);
1865  if (FLAG_enable_slow_asserts) {
1866    for (int i = 0; i < length(); i++) {
1867      MaybeObject e = WeakFixedArray::Get(i);
1868      HeapObject heap_object;
1869      if (e->GetHeapObjectIfWeak(&heap_object)) {
1870        Map::cast(heap_object).DictionaryMapVerify(isolate);
1871      } else {
1872        CHECK(e->IsCleared() || (e->GetHeapObjectIfStrong(&heap_object) &&
1873                                 heap_object.IsUndefined(isolate)));
1874      }
1875    }
1876  }
1877}
1878
1879void PreparseData::PreparseDataVerify(Isolate* isolate) {
1880  TorqueGeneratedClassVerifiers::PreparseDataVerify(*this, isolate);
1881  CHECK_LE(0, data_length());
1882  CHECK_LE(0, children_length());
1883
1884  for (int i = 0; i < children_length(); ++i) {
1885    Object child = get_child_raw(i);
1886    CHECK(child.IsNull() || child.IsPreparseData());
1887    VerifyPointer(isolate, child);
1888  }
1889}
1890
1891void CallSiteInfo::CallSiteInfoVerify(Isolate* isolate) {
1892  TorqueGeneratedClassVerifiers::CallSiteInfoVerify(*this, isolate);
1893#if V8_ENABLE_WEBASSEMBLY
1894  CHECK_IMPLIES(IsAsmJsWasm(), IsWasm());
1895  CHECK_IMPLIES(IsWasm(), receiver_or_instance().IsWasmInstanceObject());
1896  CHECK_IMPLIES(IsWasm(), function().IsSmi());
1897  CHECK_IMPLIES(!IsWasm(), function().IsJSFunction());
1898  CHECK_IMPLIES(IsAsync(), !IsWasm());
1899  CHECK_IMPLIES(IsConstructor(), !IsWasm());
1900#endif  // V8_ENABLE_WEBASSEMBLY
1901}
1902
1903void FunctionTemplateRareData::FunctionTemplateRareDataVerify(
1904    Isolate* isolate) {
1905  CHECK(c_function_overloads().IsFixedArray() ||
1906        c_function_overloads().IsUndefined(isolate));
1907}
1908
1909void StackFrameInfo::StackFrameInfoVerify(Isolate* isolate) {
1910  TorqueGeneratedClassVerifiers::StackFrameInfoVerify(*this, isolate);
1911}
1912
1913void ErrorStackData::ErrorStackDataVerify(Isolate* isolate) {
1914  TorqueGeneratedClassVerifiers::ErrorStackDataVerify(*this, isolate);
1915  CHECK_IMPLIES(!call_site_infos_or_formatted_stack().IsFixedArray(),
1916                limit_or_stack_frame_infos().IsFixedArray());
1917}
1918
1919// Helper class for verifying the string table.
1920class StringTableVerifier : public RootVisitor {
1921 public:
1922  explicit StringTableVerifier(Isolate* isolate) : isolate_(isolate) {}
1923
1924  void VisitRootPointers(Root root, const char* description,
1925                         FullObjectSlot start, FullObjectSlot end) override {
1926    UNREACHABLE();
1927  }
1928  void VisitRootPointers(Root root, const char* description,
1929                         OffHeapObjectSlot start,
1930                         OffHeapObjectSlot end) override {
1931    // Visit all HeapObject pointers in [start, end).
1932    for (OffHeapObjectSlot p = start; p < end; ++p) {
1933      Object o = p.load(isolate_);
1934      DCHECK(!HasWeakHeapObjectTag(o));
1935      if (o.IsHeapObject()) {
1936        HeapObject object = HeapObject::cast(o);
1937        // Check that the string is actually internalized.
1938        CHECK(object.IsInternalizedString());
1939      }
1940    }
1941  }
1942
1943 private:
1944  Isolate* isolate_;
1945};
1946
1947void StringTable::VerifyIfOwnedBy(Isolate* isolate) {
1948  DCHECK_EQ(isolate->string_table(), this);
1949  if (!isolate->OwnsStringTable()) return;
1950  StringTableVerifier verifier(isolate);
1951  IterateElements(&verifier);
1952}
1953
1954#endif  // VERIFY_HEAP
1955
1956#ifdef DEBUG
1957
1958void JSObject::IncrementSpillStatistics(Isolate* isolate,
1959                                        SpillInformation* info) {
1960  info->number_of_objects_++;
1961  // Named properties
1962  if (HasFastProperties()) {
1963    info->number_of_objects_with_fast_properties_++;
1964    info->number_of_fast_used_fields_ += map().NextFreePropertyIndex();
1965    info->number_of_fast_unused_fields_ += map().UnusedPropertyFields();
1966  } else if (IsJSGlobalObject()) {
1967    GlobalDictionary dict =
1968        JSGlobalObject::cast(*this).global_dictionary(kAcquireLoad);
1969    info->number_of_slow_used_properties_ += dict.NumberOfElements();
1970    info->number_of_slow_unused_properties_ +=
1971        dict.Capacity() - dict.NumberOfElements();
1972  } else if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
1973    SwissNameDictionary dict = property_dictionary_swiss();
1974    info->number_of_slow_used_properties_ += dict.NumberOfElements();
1975    info->number_of_slow_unused_properties_ +=
1976        dict.Capacity() - dict.NumberOfElements();
1977  } else {
1978    NameDictionary dict = property_dictionary();
1979    info->number_of_slow_used_properties_ += dict.NumberOfElements();
1980    info->number_of_slow_unused_properties_ +=
1981        dict.Capacity() - dict.NumberOfElements();
1982  }
1983  // Indexed properties
1984  switch (GetElementsKind()) {
1985    case HOLEY_SMI_ELEMENTS:
1986    case PACKED_SMI_ELEMENTS:
1987    case HOLEY_DOUBLE_ELEMENTS:
1988    case PACKED_DOUBLE_ELEMENTS:
1989    case HOLEY_ELEMENTS:
1990    case HOLEY_FROZEN_ELEMENTS:
1991    case HOLEY_SEALED_ELEMENTS:
1992    case HOLEY_NONEXTENSIBLE_ELEMENTS:
1993    case PACKED_ELEMENTS:
1994    case PACKED_FROZEN_ELEMENTS:
1995    case PACKED_SEALED_ELEMENTS:
1996    case PACKED_NONEXTENSIBLE_ELEMENTS:
1997    case FAST_STRING_WRAPPER_ELEMENTS: {
1998      info->number_of_objects_with_fast_elements_++;
1999      int holes = 0;
2000      FixedArray e = FixedArray::cast(elements());
2001      int len = e.length();
2002      for (int i = 0; i < len; i++) {
2003        if (e.get(i).IsTheHole(isolate)) holes++;
2004      }
2005      info->number_of_fast_used_elements_ += len - holes;
2006      info->number_of_fast_unused_elements_ += holes;
2007      break;
2008    }
2009
2010#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
2011
2012      TYPED_ARRAYS(TYPED_ARRAY_CASE)
2013      RAB_GSAB_TYPED_ARRAYS(TYPED_ARRAY_CASE)
2014#undef TYPED_ARRAY_CASE
2015      {
2016        info->number_of_objects_with_fast_elements_++;
2017        FixedArrayBase e = FixedArrayBase::cast(elements());
2018        info->number_of_fast_used_elements_ += e.length();
2019        break;
2020      }
2021    case DICTIONARY_ELEMENTS:
2022    case SLOW_STRING_WRAPPER_ELEMENTS: {
2023      NumberDictionary dict = element_dictionary();
2024      info->number_of_slow_used_elements_ += dict.NumberOfElements();
2025      info->number_of_slow_unused_elements_ +=
2026          dict.Capacity() - dict.NumberOfElements();
2027      break;
2028    }
2029    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
2030    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
2031    case WASM_ARRAY_ELEMENTS:
2032    case NO_ELEMENTS:
2033      break;
2034  }
2035}
2036
2037void JSObject::SpillInformation::Clear() {
2038  number_of_objects_ = 0;
2039  number_of_objects_with_fast_properties_ = 0;
2040  number_of_objects_with_fast_elements_ = 0;
2041  number_of_fast_used_fields_ = 0;
2042  number_of_fast_unused_fields_ = 0;
2043  number_of_slow_used_properties_ = 0;
2044  number_of_slow_unused_properties_ = 0;
2045  number_of_fast_used_elements_ = 0;
2046  number_of_fast_unused_elements_ = 0;
2047  number_of_slow_used_elements_ = 0;
2048  number_of_slow_unused_elements_ = 0;
2049}
2050
2051void JSObject::SpillInformation::Print() {
2052  PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);
2053
2054  PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
2055         number_of_objects_with_fast_properties_, number_of_fast_used_fields_,
2056         number_of_fast_unused_fields_);
2057
2058  PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
2059         number_of_objects_ - number_of_objects_with_fast_properties_,
2060         number_of_slow_used_properties_, number_of_slow_unused_properties_);
2061
2062  PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
2063         number_of_objects_with_fast_elements_, number_of_fast_used_elements_,
2064         number_of_fast_unused_elements_);
2065
2066  PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
2067         number_of_objects_ - number_of_objects_with_fast_elements_,
2068         number_of_slow_used_elements_, number_of_slow_unused_elements_);
2069
2070  PrintF("\n");
2071}
2072
2073bool DescriptorArray::IsSortedNoDuplicates() {
2074  Name current_key;
2075  uint32_t current = 0;
2076  for (int i = 0; i < number_of_descriptors(); i++) {
2077    Name key = GetSortedKey(i);
2078    CHECK(key.HasHashCode());
2079    if (key == current_key) {
2080      Print();
2081      return false;
2082    }
2083    current_key = key;
2084    uint32_t hash = key.hash();
2085    if (hash < current) {
2086      Print();
2087      return false;
2088    }
2089    current = hash;
2090  }
2091  return true;
2092}
2093
2094bool TransitionArray::IsSortedNoDuplicates() {
2095  Name prev_key;
2096  PropertyKind prev_kind = PropertyKind::kData;
2097  PropertyAttributes prev_attributes = NONE;
2098  uint32_t prev_hash = 0;
2099
2100  for (int i = 0; i < number_of_transitions(); i++) {
2101    Name key = GetSortedKey(i);
2102    CHECK(key.HasHashCode());
2103    uint32_t hash = key.hash();
2104    PropertyKind kind = PropertyKind::kData;
2105    PropertyAttributes attributes = NONE;
2106    if (!TransitionsAccessor::IsSpecialTransition(key.GetReadOnlyRoots(),
2107                                                  key)) {
2108      Map target = GetTarget(i);
2109      PropertyDetails details =
2110          TransitionsAccessor::GetTargetDetails(key, target);
2111      kind = details.kind();
2112      attributes = details.attributes();
2113    } else {
2114      // Duplicate entries are not allowed for non-property transitions.
2115      DCHECK_NE(prev_key, key);
2116    }
2117
2118    int cmp = CompareKeys(prev_key, prev_hash, prev_kind, prev_attributes, key,
2119                          hash, kind, attributes);
2120    if (cmp >= 0) {
2121      Print();
2122      return false;
2123    }
2124    prev_key = key;
2125    prev_hash = hash;
2126    prev_attributes = attributes;
2127    prev_kind = kind;
2128  }
2129  return true;
2130}
2131
2132bool TransitionsAccessor::IsSortedNoDuplicates() {
2133  // Simple and non-existent transitions are always sorted.
2134  if (encoding() != kFullTransitionArray) return true;
2135  return transitions().IsSortedNoDuplicates();
2136}
2137
2138static bool CheckOneBackPointer(Map current_map, Object target) {
2139  return !target.IsMap() || Map::cast(target).GetBackPointer() == current_map;
2140}
2141
2142bool TransitionsAccessor::IsConsistentWithBackPointers() {
2143  int num_transitions = NumberOfTransitions();
2144  for (int i = 0; i < num_transitions; i++) {
2145    Map target = GetTarget(i);
2146    if (!CheckOneBackPointer(map_, target)) return false;
2147  }
2148  return true;
2149}
2150
2151#undef USE_TORQUE_VERIFIER
2152
2153#endif  // DEBUG
2154
2155}  // namespace internal
2156}  // namespace v8
2157