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