• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
91 namespace v8 {
92 namespace 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 
ObjectVerify(Isolate * isolate)123 void 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 
VerifyPointer(Isolate * isolate,Object p)134 void Object::VerifyPointer(Isolate* isolate, Object p) {
135   if (p.IsHeapObject()) {
136     HeapObject::VerifyHeapPointer(isolate, p);
137   } else {
138     CHECK(p.IsSmi());
139   }
140 }
141 
VerifyAnyTagged(Isolate * isolate,Object p)142 void 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 
VerifyMaybeObjectPointer(Isolate * isolate,MaybeObject p)154 void 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 
SmiVerify(Isolate * isolate)163 void Smi::SmiVerify(Isolate* isolate) {
164   CHECK(IsSmi());
165   CHECK(!IsCallable());
166   CHECK(!IsConstructor());
167 }
168 
TaggedIndexVerify(Isolate * isolate)169 void TaggedIndex::TaggedIndexVerify(Isolate* isolate) {
170   CHECK(IsTaggedIndex());
171 }
172 
HeapObjectVerify(Isolate * isolate)173 void 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
VerifyHeapPointer(Isolate * isolate,Object p)322 void 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
VerifyCodePointer(Isolate * isolate,Object p)329 void 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 
SymbolVerify(Isolate * isolate)336 void 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 
BytecodeArrayVerify(Isolate * isolate)345 void 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 
ElementsAreSafeToExamine(PtrComprCageBase cage_base) const358 bool 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 
365 namespace {
366 
VerifyJSObjectElements(Isolate * isolate,JSObject object)367 void 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 
JSObjectVerify(Isolate * isolate)406 void 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 
MapVerify(Isolate * isolate)481 void 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 
DictionaryMapVerify(Isolate * isolate)566 void 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 
EmbedderDataArrayVerify(Isolate * isolate)576 void 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 
FixedArrayVerify(Isolate * isolate)586 void 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 
WeakFixedArrayVerify(Isolate * isolate)596 void 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 
ArrayListVerify(Isolate * isolate)603 void 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 
PropertyArrayVerify(Isolate * isolate)614 void 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 
FixedDoubleArrayVerify(Isolate * isolate)628 void 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 
ContextVerify(Isolate * isolate)644 void 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 
NativeContextVerify(Isolate * isolate)652 void 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 
FeedbackMetadataVerify(Isolate * isolate)659 void 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 
DescriptorArrayVerify(Isolate * isolate)673 void 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 
TransitionArrayVerify(Isolate * isolate)715 void TransitionArray::TransitionArrayVerify(Isolate* isolate) {
716   WeakFixedArrayVerify(isolate);
717   CHECK_LE(LengthFor(number_of_transitions()), length());
718 }
719 
720 namespace {
SloppyArgumentsElementsVerify(Isolate * isolate,SloppyArgumentsElements elements,JSObject holder)721 void 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 
JSArgumentsObjectVerify(Isolate * isolate)770 void 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 
JSAsyncFunctionObjectVerify(Isolate * isolate)789 void JSAsyncFunctionObject::JSAsyncFunctionObjectVerify(Isolate* isolate) {
790   TorqueGeneratedClassVerifiers::JSAsyncFunctionObjectVerify(*this, isolate);
791 }
792 
JSAsyncGeneratorObjectVerify(Isolate * isolate)793 void JSAsyncGeneratorObject::JSAsyncGeneratorObjectVerify(Isolate* isolate) {
794   TorqueGeneratedClassVerifiers::JSAsyncGeneratorObjectVerify(*this, isolate);
795 }
796 
JSDateVerify(Isolate * isolate)797 void 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 
StringVerify(Isolate * isolate)830 void 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 
ConsStringVerify(Isolate * isolate)839 void 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 
ThinStringVerify(Isolate * isolate)851 void ThinString::ThinStringVerify(Isolate* isolate) {
852   TorqueGeneratedClassVerifiers::ThinStringVerify(*this, isolate);
853   CHECK(actual().IsInternalizedString());
854   CHECK(actual().IsSeqString() || actual().IsExternalString());
855 }
856 
SlicedStringVerify(Isolate * isolate)857 void 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 
USE_TORQUE_VERIFIER(ExternalString)864 USE_TORQUE_VERIFIER(ExternalString)
865 
866 void JSBoundFunction::JSBoundFunctionVerify(Isolate* isolate) {
867   TorqueGeneratedClassVerifiers::JSBoundFunctionVerify(*this, isolate);
868   CHECK(IsCallable());
869   CHECK_EQ(IsConstructor(), bound_target_function().IsConstructor());
870 }
871 
JSFunctionVerify(Isolate * isolate)872 void 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 
SharedFunctionInfoVerify(Isolate * isolate)910 void SharedFunctionInfo::SharedFunctionInfoVerify(Isolate* isolate) {
911   // TODO(leszeks): Add a TorqueGeneratedClassVerifier for LocalIsolate.
912   this->SharedFunctionInfoVerify(ReadOnlyRoots(isolate));
913 }
914 
SharedFunctionInfoVerify(LocalIsolate * isolate)915 void SharedFunctionInfo::SharedFunctionInfoVerify(LocalIsolate* isolate) {
916   this->SharedFunctionInfoVerify(ReadOnlyRoots(isolate));
917 }
918 
SharedFunctionInfoVerify(ReadOnlyRoots roots)919 void 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 
JSGlobalProxyVerify(Isolate * isolate)975 void 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 
JSGlobalObjectVerify(Isolate * isolate)982 void 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 
OddballVerify(Isolate * isolate)992 void 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 
PropertyCellVerify(Isolate * isolate)1053 void PropertyCell::PropertyCellVerify(Isolate* isolate) {
1054   TorqueGeneratedClassVerifiers::PropertyCellVerify(*this, isolate);
1055   CHECK(name().IsUniqueName());
1056   CheckDataIsCompatible(property_details(), value());
1057 }
1058 
CodeDataContainerVerify(Isolate * isolate)1059 void 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 
CodeVerify(Isolate * isolate)1102 void 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 
JSArrayVerify(Isolate * isolate)1142 void 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 
JSSetVerify(Isolate * isolate)1184 void JSSet::JSSetVerify(Isolate* isolate) {
1185   TorqueGeneratedClassVerifiers::JSSetVerify(*this, isolate);
1186   CHECK(table().IsOrderedHashSet() || table().IsUndefined(isolate));
1187   // TODO(arv): Verify OrderedHashTable too.
1188 }
1189 
JSMapVerify(Isolate * isolate)1190 void JSMap::JSMapVerify(Isolate* isolate) {
1191   TorqueGeneratedClassVerifiers::JSMapVerify(*this, isolate);
1192   CHECK(table().IsOrderedHashMap() || table().IsUndefined(isolate));
1193   // TODO(arv): Verify OrderedHashTable too.
1194 }
1195 
JSSetIteratorVerify(Isolate * isolate)1196 void JSSetIterator::JSSetIteratorVerify(Isolate* isolate) {
1197   CHECK(IsJSSetIterator());
1198   JSCollectionIteratorVerify(isolate);
1199   CHECK(table().IsOrderedHashSet());
1200   CHECK(index().IsSmi());
1201 }
1202 
JSMapIteratorVerify(Isolate * isolate)1203 void JSMapIterator::JSMapIteratorVerify(Isolate* isolate) {
1204   CHECK(IsJSMapIterator());
1205   JSCollectionIteratorVerify(isolate);
1206   CHECK(table().IsOrderedHashMap());
1207   CHECK(index().IsSmi());
1208 }
1209 
1210 USE_TORQUE_VERIFIER(JSShadowRealm)
USE_TORQUE_VERIFIER(JSWrappedFunction)1211 USE_TORQUE_VERIFIER(JSWrappedFunction)
1212 
1213 void 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 
WeakCellVerify(Isolate * isolate)1240 void 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 
JSWeakRefVerify(Isolate * isolate)1268 void JSWeakRef::JSWeakRefVerify(Isolate* isolate) {
1269   CHECK(IsJSWeakRef());
1270   JSObjectVerify(isolate);
1271   CHECK(target().IsUndefined(isolate) || target().CanBeHeldWeakly());
1272 }
1273 
JSFinalizationRegistryVerify(Isolate * isolate)1274 void 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 
JSWeakMapVerify(Isolate * isolate)1284 void JSWeakMap::JSWeakMapVerify(Isolate* isolate) {
1285   TorqueGeneratedClassVerifiers::JSWeakMapVerify(*this, isolate);
1286   CHECK(table().IsEphemeronHashTable() || table().IsUndefined(isolate));
1287 }
1288 
JSArrayIteratorVerify(Isolate * isolate)1289 void 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 
JSStringIteratorVerify(Isolate * isolate)1305 void JSStringIterator::JSStringIteratorVerify(Isolate* isolate) {
1306   TorqueGeneratedClassVerifiers::JSStringIteratorVerify(*this, isolate);
1307   CHECK_GE(index(), 0);
1308   CHECK_LE(index(), String::kMaxLength);
1309 }
1310 
JSWeakSetVerify(Isolate * isolate)1311 void JSWeakSet::JSWeakSetVerify(Isolate* isolate) {
1312   TorqueGeneratedClassVerifiers::JSWeakSetVerify(*this, isolate);
1313   CHECK(table().IsEphemeronHashTable() || table().IsUndefined(isolate));
1314 }
1315 
CallableTaskVerify(Isolate * isolate)1316 void CallableTask::CallableTaskVerify(Isolate* isolate) {
1317   TorqueGeneratedClassVerifiers::CallableTaskVerify(*this, isolate);
1318   CHECK(callable().IsCallable());
1319 }
1320 
JSPromiseVerify(Isolate * isolate)1321 void JSPromise::JSPromiseVerify(Isolate* isolate) {
1322   TorqueGeneratedClassVerifiers::JSPromiseVerify(*this, isolate);
1323   if (status() == Promise::kPending) {
1324     CHECK(reactions().IsSmi() || reactions().IsPromiseReaction());
1325   }
1326 }
1327 
1328 template <typename Derived>
SmallOrderedHashTableVerify(Isolate * isolate)1329 void 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 
SmallOrderedHashMapVerify(Isolate * isolate)1367 void 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 
SmallOrderedHashSetVerify(Isolate * isolate)1380 void 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 
SmallOrderedNameDictionaryVerify(Isolate * isolate)1393 void 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 
SwissNameDictionaryVerify(Isolate * isolate)1408 void SwissNameDictionary::SwissNameDictionaryVerify(Isolate* isolate) {
1409   this->SwissNameDictionaryVerify(isolate, false);
1410 }
1411 
SwissNameDictionaryVerify(Isolate * isolate,bool slow_checks)1412 void 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 
JSRegExpVerify(Isolate * isolate)1483 void 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 
JSProxyVerify(Isolate * isolate)1569 void 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 
JSArrayBufferVerify(Isolate * isolate)1581 void 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 
JSArrayBufferViewVerify(Isolate * isolate)1590 void 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 
JSTypedArrayVerify(Isolate * isolate)1596 void JSTypedArray::JSTypedArrayVerify(Isolate* isolate) {
1597   TorqueGeneratedClassVerifiers::JSTypedArrayVerify(*this, isolate);
1598   CHECK_LE(GetLength(), JSTypedArray::kMaxLength);
1599 }
1600 
JSDataViewVerify(Isolate * isolate)1601 void 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 
AsyncGeneratorRequestVerify(Isolate * isolate)1611 void 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 
BigIntBaseVerify(Isolate * isolate)1617 void BigIntBase::BigIntBaseVerify(Isolate* isolate) {
1618   CHECK_GE(length(), 0);
1619   CHECK_IMPLIES(is_zero(), !sign());  // There is no -0n.
1620 }
1621 
SourceTextModuleInfoEntryVerify(Isolate * isolate)1622 void 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 
ModuleVerify(Isolate * isolate)1631 void 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 
ModuleRequestVerify(Isolate * isolate)1651 void 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 
SourceTextModuleVerify(Isolate * isolate)1664 void 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 
SyntheticModuleVerify(Isolate * isolate)1689 void 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 
PrototypeInfoVerify(Isolate * isolate)1697 void 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 
Verify(WeakArrayList array)1706 void 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 
EnumCacheVerify(Isolate * isolate)1738 void 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 
ObjectBoilerplateDescriptionVerify(Isolate * isolate)1747 void 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 
WasmInstanceObjectVerify(Isolate * isolate)1761 void 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 
WasmValueObjectVerify(Isolate * isolate)1774 void WasmValueObject::WasmValueObjectVerify(Isolate* isolate) {
1775   JSObjectVerify(isolate);
1776   CHECK(IsWasmValueObject());
1777 }
1778 
WasmExportedFunctionDataVerify(Isolate * isolate)1779 void 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 
DataHandlerVerify(Isolate * isolate)1792 void 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 
LoadHandlerVerify(Isolate * isolate)1819 void LoadHandler::LoadHandlerVerify(Isolate* isolate) {
1820   DataHandler::DataHandlerVerify(isolate);
1821   // TODO(ishell): check handler integrity
1822 }
1823 
StoreHandlerVerify(Isolate * isolate)1824 void StoreHandler::StoreHandlerVerify(Isolate* isolate) {
1825   DataHandler::DataHandlerVerify(isolate);
1826   // TODO(ishell): check handler integrity
1827 }
1828 
CallHandlerInfoVerify(Isolate * isolate)1829 void 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 
AllocationSiteVerify(Isolate * isolate)1838 void 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 
ScriptVerify(Isolate * isolate)1846 void 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 
NormalizedMapCacheVerify(Isolate * isolate)1863 void 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 
PreparseDataVerify(Isolate * isolate)1879 void 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 
CallSiteInfoVerify(Isolate * isolate)1891 void 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 
FunctionTemplateRareDataVerify(Isolate * isolate)1903 void FunctionTemplateRareData::FunctionTemplateRareDataVerify(
1904     Isolate* isolate) {
1905   CHECK(c_function_overloads().IsFixedArray() ||
1906         c_function_overloads().IsUndefined(isolate));
1907 }
1908 
StackFrameInfoVerify(Isolate * isolate)1909 void StackFrameInfo::StackFrameInfoVerify(Isolate* isolate) {
1910   TorqueGeneratedClassVerifiers::StackFrameInfoVerify(*this, isolate);
1911 }
1912 
ErrorStackDataVerify(Isolate * isolate)1913 void 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.
1920 class StringTableVerifier : public RootVisitor {
1921  public:
StringTableVerifier(Isolate * isolate)1922   explicit StringTableVerifier(Isolate* isolate) : isolate_(isolate) {}
1923 
VisitRootPointers(Root root,const char * description,FullObjectSlot start,FullObjectSlot end)1924   void VisitRootPointers(Root root, const char* description,
1925                          FullObjectSlot start, FullObjectSlot end) override {
1926     UNREACHABLE();
1927   }
VisitRootPointers(Root root,const char * description,OffHeapObjectSlot start,OffHeapObjectSlot end)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 
VerifyIfOwnedBy(Isolate * isolate)1947 void 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 
IncrementSpillStatistics(Isolate * isolate,SpillInformation * info)1958 void 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 
Clear()2037 void 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 
Print()2051 void 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 
IsSortedNoDuplicates()2073 bool 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 
IsSortedNoDuplicates()2094 bool 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 
IsSortedNoDuplicates()2132 bool TransitionsAccessor::IsSortedNoDuplicates() {
2133   // Simple and non-existent transitions are always sorted.
2134   if (encoding() != kFullTransitionArray) return true;
2135   return transitions().IsSortedNoDuplicates();
2136 }
2137 
CheckOneBackPointer(Map current_map,Object target)2138 static bool CheckOneBackPointer(Map current_map, Object target) {
2139   return !target.IsMap() || Map::cast(target).GetBackPointer() == current_map;
2140 }
2141 
IsConsistentWithBackPointers()2142 bool 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