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