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