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/objects.h" 6 7 #include "src/assembler-inl.h" 8 #include "src/bootstrapper.h" 9 #include "src/disasm.h" 10 #include "src/disassembler.h" 11 #include "src/field-type.h" 12 #include "src/layout-descriptor.h" 13 #include "src/macro-assembler.h" 14 #include "src/objects-inl.h" 15 #include "src/objects/literal-objects.h" 16 #include "src/objects/module-info.h" 17 #include "src/ostreams.h" 18 #include "src/regexp/jsregexp.h" 19 #include "src/transitions.h" 20 21 namespace v8 { 22 namespace internal { 23 24 #ifdef VERIFY_HEAP 25 26 void Object::ObjectVerify() { 27 if (IsSmi()) { 28 Smi::cast(this)->SmiVerify(); 29 } else { 30 HeapObject::cast(this)->HeapObjectVerify(); 31 } 32 CHECK(!IsConstructor() || IsCallable()); 33 } 34 35 36 void Object::VerifyPointer(Object* p) { 37 if (p->IsHeapObject()) { 38 HeapObject::VerifyHeapPointer(p); 39 } else { 40 CHECK(p->IsSmi()); 41 } 42 } 43 44 45 void Smi::SmiVerify() { 46 CHECK(IsSmi()); 47 CHECK(!IsCallable()); 48 CHECK(!IsConstructor()); 49 } 50 51 52 void HeapObject::HeapObjectVerify() { 53 VerifyHeapPointer(map()); 54 CHECK(map()->IsMap()); 55 InstanceType instance_type = map()->instance_type(); 56 57 if (instance_type < FIRST_NONSTRING_TYPE) { 58 String::cast(this)->StringVerify(); 59 return; 60 } 61 62 switch (instance_type) { 63 case SYMBOL_TYPE: 64 Symbol::cast(this)->SymbolVerify(); 65 break; 66 case MAP_TYPE: 67 Map::cast(this)->MapVerify(); 68 break; 69 case HEAP_NUMBER_TYPE: 70 case MUTABLE_HEAP_NUMBER_TYPE: 71 HeapNumber::cast(this)->HeapNumberVerify(); 72 break; 73 case FIXED_ARRAY_TYPE: 74 FixedArray::cast(this)->FixedArrayVerify(); 75 break; 76 case FIXED_DOUBLE_ARRAY_TYPE: 77 FixedDoubleArray::cast(this)->FixedDoubleArrayVerify(); 78 break; 79 case BYTE_ARRAY_TYPE: 80 ByteArray::cast(this)->ByteArrayVerify(); 81 break; 82 case BYTECODE_ARRAY_TYPE: 83 BytecodeArray::cast(this)->BytecodeArrayVerify(); 84 break; 85 case TRANSITION_ARRAY_TYPE: 86 TransitionArray::cast(this)->TransitionArrayVerify(); 87 break; 88 case FREE_SPACE_TYPE: 89 FreeSpace::cast(this)->FreeSpaceVerify(); 90 break; 91 92 #define VERIFY_TYPED_ARRAY(Type, type, TYPE, ctype, size) \ 93 case FIXED_##TYPE##_ARRAY_TYPE: \ 94 Fixed##Type##Array::cast(this)->FixedTypedArrayVerify(); \ 95 break; 96 97 TYPED_ARRAYS(VERIFY_TYPED_ARRAY) 98 #undef VERIFY_TYPED_ARRAY 99 100 case CODE_TYPE: 101 Code::cast(this)->CodeVerify(); 102 break; 103 case ODDBALL_TYPE: 104 Oddball::cast(this)->OddballVerify(); 105 break; 106 case JS_OBJECT_TYPE: 107 case JS_ERROR_TYPE: 108 case JS_ARGUMENTS_TYPE: 109 case JS_API_OBJECT_TYPE: 110 case JS_SPECIAL_API_OBJECT_TYPE: 111 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 112 JSObject::cast(this)->JSObjectVerify(); 113 break; 114 case JS_GENERATOR_OBJECT_TYPE: 115 JSGeneratorObject::cast(this)->JSGeneratorObjectVerify(); 116 break; 117 case JS_VALUE_TYPE: 118 JSValue::cast(this)->JSValueVerify(); 119 break; 120 case JS_DATE_TYPE: 121 JSDate::cast(this)->JSDateVerify(); 122 break; 123 case JS_BOUND_FUNCTION_TYPE: 124 JSBoundFunction::cast(this)->JSBoundFunctionVerify(); 125 break; 126 case JS_FUNCTION_TYPE: 127 JSFunction::cast(this)->JSFunctionVerify(); 128 break; 129 case JS_GLOBAL_PROXY_TYPE: 130 JSGlobalProxy::cast(this)->JSGlobalProxyVerify(); 131 break; 132 case JS_GLOBAL_OBJECT_TYPE: 133 JSGlobalObject::cast(this)->JSGlobalObjectVerify(); 134 break; 135 case CELL_TYPE: 136 Cell::cast(this)->CellVerify(); 137 break; 138 case PROPERTY_CELL_TYPE: 139 PropertyCell::cast(this)->PropertyCellVerify(); 140 break; 141 case WEAK_CELL_TYPE: 142 WeakCell::cast(this)->WeakCellVerify(); 143 break; 144 case JS_ARRAY_TYPE: 145 JSArray::cast(this)->JSArrayVerify(); 146 break; 147 case JS_MODULE_NAMESPACE_TYPE: 148 JSModuleNamespace::cast(this)->JSModuleNamespaceVerify(); 149 break; 150 case JS_SET_TYPE: 151 JSSet::cast(this)->JSSetVerify(); 152 break; 153 case JS_MAP_TYPE: 154 JSMap::cast(this)->JSMapVerify(); 155 break; 156 case JS_SET_ITERATOR_TYPE: 157 JSSetIterator::cast(this)->JSSetIteratorVerify(); 158 break; 159 case JS_MAP_ITERATOR_TYPE: 160 JSMapIterator::cast(this)->JSMapIteratorVerify(); 161 break; 162 case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE: 163 case JS_FAST_ARRAY_KEY_ITERATOR_TYPE: 164 case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE: 165 case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE: 166 case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE: 167 case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE: 168 case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE: 169 case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: 170 case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: 171 case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: 172 case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE: 173 case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE: 174 case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE: 175 case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE: 176 case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE: 177 case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE: 178 case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE: 179 case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE: 180 case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE: 181 case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE: 182 case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE: 183 case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE: 184 case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE: 185 case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE: 186 case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE: 187 case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE: 188 case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE: 189 case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE: 190 case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE: 191 case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE: 192 case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE: 193 case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE: 194 case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE: 195 case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE: 196 case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE: 197 JSArrayIterator::cast(this)->JSArrayIteratorVerify(); 198 break; 199 200 case JS_STRING_ITERATOR_TYPE: 201 JSStringIterator::cast(this)->JSStringIteratorVerify(); 202 break; 203 case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE: 204 JSAsyncFromSyncIterator::cast(this)->JSAsyncFromSyncIteratorVerify(); 205 break; 206 case JS_WEAK_MAP_TYPE: 207 JSWeakMap::cast(this)->JSWeakMapVerify(); 208 break; 209 case JS_WEAK_SET_TYPE: 210 JSWeakSet::cast(this)->JSWeakSetVerify(); 211 break; 212 case JS_PROMISE_CAPABILITY_TYPE: 213 JSPromiseCapability::cast(this)->JSPromiseCapabilityVerify(); 214 break; 215 case JS_PROMISE_TYPE: 216 JSPromise::cast(this)->JSPromiseVerify(); 217 break; 218 case JS_REGEXP_TYPE: 219 JSRegExp::cast(this)->JSRegExpVerify(); 220 break; 221 case FILLER_TYPE: 222 break; 223 case JS_PROXY_TYPE: 224 JSProxy::cast(this)->JSProxyVerify(); 225 break; 226 case FOREIGN_TYPE: 227 Foreign::cast(this)->ForeignVerify(); 228 break; 229 case SHARED_FUNCTION_INFO_TYPE: 230 SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify(); 231 break; 232 case JS_MESSAGE_OBJECT_TYPE: 233 JSMessageObject::cast(this)->JSMessageObjectVerify(); 234 break; 235 case JS_ARRAY_BUFFER_TYPE: 236 JSArrayBuffer::cast(this)->JSArrayBufferVerify(); 237 break; 238 case JS_TYPED_ARRAY_TYPE: 239 JSTypedArray::cast(this)->JSTypedArrayVerify(); 240 break; 241 case JS_DATA_VIEW_TYPE: 242 JSDataView::cast(this)->JSDataViewVerify(); 243 break; 244 245 #define MAKE_STRUCT_CASE(NAME, Name, name) \ 246 case NAME##_TYPE: \ 247 Name::cast(this)->Name##Verify(); \ 248 break; 249 STRUCT_LIST(MAKE_STRUCT_CASE) 250 #undef MAKE_STRUCT_CASE 251 252 default: 253 UNREACHABLE(); 254 break; 255 } 256 } 257 258 259 void HeapObject::VerifyHeapPointer(Object* p) { 260 CHECK(p->IsHeapObject()); 261 HeapObject* ho = HeapObject::cast(p); 262 CHECK(ho->GetHeap()->Contains(ho)); 263 } 264 265 266 void Symbol::SymbolVerify() { 267 CHECK(IsSymbol()); 268 CHECK(HasHashCode()); 269 CHECK(Hash() > 0u); 270 CHECK(name()->IsUndefined(GetIsolate()) || name()->IsString()); 271 } 272 273 274 void HeapNumber::HeapNumberVerify() { 275 CHECK(IsHeapNumber() || IsMutableHeapNumber()); 276 } 277 278 void ByteArray::ByteArrayVerify() { 279 CHECK(IsByteArray()); 280 } 281 282 283 void BytecodeArray::BytecodeArrayVerify() { 284 // TODO(oth): Walk bytecodes and immediate values to validate sanity. 285 // - All bytecodes are known and well formed. 286 // - Jumps must go to new instructions starts. 287 // - No Illegal bytecodes. 288 // - No consecutive sequences of prefix Wide / ExtraWide. 289 CHECK(IsBytecodeArray()); 290 CHECK(constant_pool()->IsFixedArray()); 291 VerifyHeapPointer(constant_pool()); 292 } 293 294 295 void FreeSpace::FreeSpaceVerify() { 296 CHECK(IsFreeSpace()); 297 } 298 299 300 template <class Traits> 301 void FixedTypedArray<Traits>::FixedTypedArrayVerify() { 302 CHECK(IsHeapObject() && 303 HeapObject::cast(this)->map()->instance_type() == 304 Traits::kInstanceType); 305 if (base_pointer() == this) { 306 CHECK(external_pointer() == 307 ExternalReference::fixed_typed_array_base_data_offset().address()); 308 } else { 309 CHECK(base_pointer() == nullptr); 310 } 311 } 312 313 314 bool JSObject::ElementsAreSafeToExamine() { 315 // If a GC was caused while constructing this object, the elements 316 // pointer may point to a one pointer filler map. 317 return reinterpret_cast<Map*>(elements()) != 318 GetHeap()->one_pointer_filler_map(); 319 } 320 321 322 void JSObject::JSObjectVerify() { 323 VerifyHeapPointer(properties()); 324 VerifyHeapPointer(elements()); 325 326 if (HasSloppyArgumentsElements()) { 327 CHECK(this->elements()->IsFixedArray()); 328 CHECK_GE(this->elements()->length(), 2); 329 } 330 331 if (HasFastProperties()) { 332 int actual_unused_property_fields = map()->GetInObjectProperties() + 333 properties()->length() - 334 map()->NextFreePropertyIndex(); 335 if (map()->unused_property_fields() != actual_unused_property_fields) { 336 // This could actually happen in the middle of StoreTransitionStub 337 // when the new extended backing store is already set into the object and 338 // the allocation of the MutableHeapNumber triggers GC (in this case map 339 // is not updated yet). 340 CHECK_EQ(map()->unused_property_fields(), 341 actual_unused_property_fields - JSObject::kFieldsAdded); 342 } 343 DescriptorArray* descriptors = map()->instance_descriptors(); 344 Isolate* isolate = GetIsolate(); 345 for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) { 346 PropertyDetails details = descriptors->GetDetails(i); 347 if (details.location() == kField) { 348 DCHECK_EQ(kData, details.kind()); 349 Representation r = descriptors->GetDetails(i).representation(); 350 FieldIndex index = FieldIndex::ForDescriptor(map(), i); 351 if (IsUnboxedDoubleField(index)) { 352 DCHECK(r.IsDouble()); 353 continue; 354 } 355 Object* value = RawFastPropertyAt(index); 356 if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber()); 357 if (value->IsUninitialized(isolate)) continue; 358 if (r.IsSmi()) DCHECK(value->IsSmi()); 359 if (r.IsHeapObject()) DCHECK(value->IsHeapObject()); 360 FieldType* field_type = descriptors->GetFieldType(i); 361 bool type_is_none = field_type->IsNone(); 362 bool type_is_any = field_type->IsAny(); 363 if (r.IsNone()) { 364 CHECK(type_is_none); 365 } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) { 366 // If allocation folding is off then GC could happen during inner 367 // object literal creation and we will end up having and undefined 368 // value that does not match the field type. 369 CHECK(!field_type->NowStable() || field_type->NowContains(value) || 370 (!FLAG_use_allocation_folding && value->IsUndefined(isolate))); 371 } 372 } 373 } 374 } 375 376 // If a GC was caused while constructing this object, the elements 377 // pointer may point to a one pointer filler map. 378 if (ElementsAreSafeToExamine()) { 379 CHECK_EQ((map()->has_fast_smi_or_object_elements() || 380 (elements() == GetHeap()->empty_fixed_array()) || 381 HasFastStringWrapperElements()), 382 (elements()->map() == GetHeap()->fixed_array_map() || 383 elements()->map() == GetHeap()->fixed_cow_array_map())); 384 CHECK(map()->has_fast_object_elements() == HasFastObjectElements()); 385 } 386 } 387 388 389 void Map::MapVerify() { 390 Heap* heap = GetHeap(); 391 CHECK(!heap->InNewSpace(this)); 392 CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE); 393 CHECK(instance_size() == kVariableSizeSentinel || 394 (kPointerSize <= instance_size() && 395 static_cast<size_t>(instance_size()) < heap->Capacity())); 396 CHECK(GetBackPointer()->IsUndefined(heap->isolate()) || 397 !Map::cast(GetBackPointer())->is_stable()); 398 VerifyHeapPointer(prototype()); 399 VerifyHeapPointer(instance_descriptors()); 400 SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates()); 401 SLOW_DCHECK(TransitionArray::IsSortedNoDuplicates(this)); 402 SLOW_DCHECK(TransitionArray::IsConsistentWithBackPointers(this)); 403 // TODO(ishell): turn it back to SLOW_DCHECK. 404 CHECK(!FLAG_unbox_double_fields || 405 layout_descriptor()->IsConsistentWithMap(this)); 406 } 407 408 409 void Map::DictionaryMapVerify() { 410 MapVerify(); 411 CHECK(is_dictionary_map()); 412 CHECK(instance_descriptors()->IsEmpty()); 413 CHECK_EQ(0, unused_property_fields()); 414 CHECK_EQ(Heap::GetStaticVisitorIdForMap(this), visitor_id()); 415 } 416 417 418 void Map::VerifyOmittedMapChecks() { 419 if (!FLAG_omit_map_checks_for_leaf_maps) return; 420 if (!is_stable() || 421 is_deprecated() || 422 is_dictionary_map()) { 423 CHECK(dependent_code()->IsEmpty(DependentCode::kPrototypeCheckGroup)); 424 } 425 } 426 427 428 void TypeFeedbackInfo::TypeFeedbackInfoVerify() { 429 VerifyObjectField(kStorage1Offset); 430 VerifyObjectField(kStorage2Offset); 431 VerifyObjectField(kStorage3Offset); 432 } 433 434 435 void AliasedArgumentsEntry::AliasedArgumentsEntryVerify() { 436 VerifySmiField(kAliasedContextSlot); 437 } 438 439 440 void FixedArray::FixedArrayVerify() { 441 for (int i = 0; i < length(); i++) { 442 Object* e = get(i); 443 VerifyPointer(e); 444 } 445 } 446 447 448 void FixedDoubleArray::FixedDoubleArrayVerify() { 449 for (int i = 0; i < length(); i++) { 450 if (!is_the_hole(i)) { 451 uint64_t value = get_representation(i); 452 uint64_t unexpected = 453 bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN()) & 454 V8_UINT64_C(0x7FF8000000000000); 455 // Create implementation specific sNaN by inverting relevant bit. 456 unexpected ^= V8_UINT64_C(0x0008000000000000); 457 CHECK((value & V8_UINT64_C(0x7FF8000000000000)) != unexpected || 458 (value & V8_UINT64_C(0x0007FFFFFFFFFFFF)) == V8_UINT64_C(0)); 459 } 460 } 461 } 462 463 464 void TransitionArray::TransitionArrayVerify() { 465 for (int i = 0; i < length(); i++) { 466 Object* e = get(i); 467 VerifyPointer(e); 468 } 469 CHECK_LE(LengthFor(number_of_transitions()), length()); 470 CHECK(next_link()->IsUndefined(GetIsolate()) || next_link()->IsSmi() || 471 next_link()->IsTransitionArray()); 472 } 473 474 475 void JSGeneratorObject::JSGeneratorObjectVerify() { 476 // In an expression like "new g()", there can be a point where a generator 477 // object is allocated but its fields are all undefined, as it hasn't yet been 478 // initialized by the generator. Hence these weak checks. 479 VerifyObjectField(kFunctionOffset); 480 VerifyObjectField(kContextOffset); 481 VerifyObjectField(kReceiverOffset); 482 VerifyObjectField(kRegisterFileOffset); 483 VerifyObjectField(kContinuationOffset); 484 } 485 486 487 void JSValue::JSValueVerify() { 488 Object* v = value(); 489 if (v->IsHeapObject()) { 490 VerifyHeapPointer(v); 491 } 492 } 493 494 495 void JSDate::JSDateVerify() { 496 if (value()->IsHeapObject()) { 497 VerifyHeapPointer(value()); 498 } 499 Isolate* isolate = GetIsolate(); 500 CHECK(value()->IsUndefined(isolate) || value()->IsSmi() || 501 value()->IsHeapNumber()); 502 CHECK(year()->IsUndefined(isolate) || year()->IsSmi() || year()->IsNaN()); 503 CHECK(month()->IsUndefined(isolate) || month()->IsSmi() || month()->IsNaN()); 504 CHECK(day()->IsUndefined(isolate) || day()->IsSmi() || day()->IsNaN()); 505 CHECK(weekday()->IsUndefined(isolate) || weekday()->IsSmi() || 506 weekday()->IsNaN()); 507 CHECK(hour()->IsUndefined(isolate) || hour()->IsSmi() || hour()->IsNaN()); 508 CHECK(min()->IsUndefined(isolate) || min()->IsSmi() || min()->IsNaN()); 509 CHECK(sec()->IsUndefined(isolate) || sec()->IsSmi() || sec()->IsNaN()); 510 CHECK(cache_stamp()->IsUndefined(isolate) || cache_stamp()->IsSmi() || 511 cache_stamp()->IsNaN()); 512 513 if (month()->IsSmi()) { 514 int month = Smi::cast(this->month())->value(); 515 CHECK(0 <= month && month <= 11); 516 } 517 if (day()->IsSmi()) { 518 int day = Smi::cast(this->day())->value(); 519 CHECK(1 <= day && day <= 31); 520 } 521 if (hour()->IsSmi()) { 522 int hour = Smi::cast(this->hour())->value(); 523 CHECK(0 <= hour && hour <= 23); 524 } 525 if (min()->IsSmi()) { 526 int min = Smi::cast(this->min())->value(); 527 CHECK(0 <= min && min <= 59); 528 } 529 if (sec()->IsSmi()) { 530 int sec = Smi::cast(this->sec())->value(); 531 CHECK(0 <= sec && sec <= 59); 532 } 533 if (weekday()->IsSmi()) { 534 int weekday = Smi::cast(this->weekday())->value(); 535 CHECK(0 <= weekday && weekday <= 6); 536 } 537 if (cache_stamp()->IsSmi()) { 538 CHECK(Smi::cast(cache_stamp())->value() <= 539 Smi::cast(isolate->date_cache()->stamp())->value()); 540 } 541 } 542 543 544 void JSMessageObject::JSMessageObjectVerify() { 545 CHECK(IsJSMessageObject()); 546 VerifyObjectField(kStartPositionOffset); 547 VerifyObjectField(kEndPositionOffset); 548 VerifyObjectField(kArgumentsOffset); 549 VerifyObjectField(kScriptOffset); 550 VerifyObjectField(kStackFramesOffset); 551 } 552 553 554 void String::StringVerify() { 555 CHECK(IsString()); 556 CHECK(length() >= 0 && length() <= Smi::kMaxValue); 557 CHECK_IMPLIES(length() == 0, this == GetHeap()->empty_string()); 558 if (IsInternalizedString()) { 559 CHECK(!GetHeap()->InNewSpace(this)); 560 } 561 if (IsConsString()) { 562 ConsString::cast(this)->ConsStringVerify(); 563 } else if (IsSlicedString()) { 564 SlicedString::cast(this)->SlicedStringVerify(); 565 } else if (IsThinString()) { 566 ThinString::cast(this)->ThinStringVerify(); 567 } 568 } 569 570 571 void ConsString::ConsStringVerify() { 572 CHECK(this->first()->IsString()); 573 CHECK(this->second() == GetHeap()->empty_string() || 574 this->second()->IsString()); 575 CHECK(this->length() >= ConsString::kMinLength); 576 CHECK(this->length() == this->first()->length() + this->second()->length()); 577 if (this->IsFlat()) { 578 // A flat cons can only be created by String::SlowFlatten. 579 // Afterwards, the first part may be externalized or internalized. 580 CHECK(this->first()->IsSeqString() || this->first()->IsExternalString() || 581 this->first()->IsThinString()); 582 } 583 } 584 585 void ThinString::ThinStringVerify() { 586 CHECK(this->actual()->IsInternalizedString()); 587 CHECK(this->actual()->IsSeqString() || this->actual()->IsExternalString()); 588 } 589 590 void SlicedString::SlicedStringVerify() { 591 CHECK(!this->parent()->IsConsString()); 592 CHECK(!this->parent()->IsSlicedString()); 593 CHECK(this->length() >= SlicedString::kMinLength); 594 } 595 596 597 void JSBoundFunction::JSBoundFunctionVerify() { 598 CHECK(IsJSBoundFunction()); 599 JSObjectVerify(); 600 VerifyObjectField(kBoundThisOffset); 601 VerifyObjectField(kBoundTargetFunctionOffset); 602 VerifyObjectField(kBoundArgumentsOffset); 603 CHECK(bound_target_function()->IsCallable()); 604 CHECK(IsCallable()); 605 CHECK_EQ(IsConstructor(), bound_target_function()->IsConstructor()); 606 } 607 608 609 void JSFunction::JSFunctionVerify() { 610 CHECK(IsJSFunction()); 611 VerifyObjectField(kPrototypeOrInitialMapOffset); 612 VerifyObjectField(kNextFunctionLinkOffset); 613 CHECK(code()->IsCode()); 614 CHECK(next_function_link() == NULL || 615 next_function_link()->IsUndefined(GetIsolate()) || 616 next_function_link()->IsJSFunction()); 617 CHECK(map()->is_callable()); 618 } 619 620 621 void SharedFunctionInfo::SharedFunctionInfoVerify() { 622 CHECK(IsSharedFunctionInfo()); 623 624 VerifyObjectField(kCodeOffset); 625 VerifyObjectField(kDebugInfoOffset); 626 VerifyObjectField(kFeedbackMetadataOffset); 627 VerifyObjectField(kFunctionDataOffset); 628 VerifyObjectField(kFunctionIdentifierOffset); 629 VerifyObjectField(kInstanceClassNameOffset); 630 VerifyObjectField(kNameOffset); 631 VerifyObjectField(kOptimizedCodeMapOffset); 632 VerifyObjectField(kOuterScopeInfoOffset); 633 VerifyObjectField(kScopeInfoOffset); 634 VerifyObjectField(kScriptOffset); 635 636 CHECK(function_data()->IsUndefined(GetIsolate()) || IsApiFunction() || 637 HasBytecodeArray() || HasAsmWasmData()); 638 639 CHECK(function_identifier()->IsUndefined(GetIsolate()) || 640 HasBuiltinFunctionId() || HasInferredName()); 641 642 if (scope_info()->length() > 0) { 643 CHECK(kind() == scope_info()->function_kind()); 644 CHECK_EQ(kind() == kModule, scope_info()->scope_type() == MODULE_SCOPE); 645 } 646 } 647 648 649 void JSGlobalProxy::JSGlobalProxyVerify() { 650 CHECK(IsJSGlobalProxy()); 651 JSObjectVerify(); 652 VerifyObjectField(JSGlobalProxy::kNativeContextOffset); 653 // Make sure that this object has no properties, elements. 654 CHECK_EQ(0, properties()->length()); 655 CHECK_EQ(0, FixedArray::cast(elements())->length()); 656 } 657 658 659 void JSGlobalObject::JSGlobalObjectVerify() { 660 CHECK(IsJSGlobalObject()); 661 // Do not check the dummy global object for the builtins. 662 if (GlobalDictionary::cast(properties())->NumberOfElements() == 0 && 663 elements()->length() == 0) { 664 return; 665 } 666 JSObjectVerify(); 667 } 668 669 670 void Oddball::OddballVerify() { 671 CHECK(IsOddball()); 672 Heap* heap = GetHeap(); 673 VerifyHeapPointer(to_string()); 674 Object* number = to_number(); 675 if (number->IsHeapObject()) { 676 CHECK(number == heap->nan_value() || 677 number == heap->hole_nan_value()); 678 } else { 679 CHECK(number->IsSmi()); 680 int value = Smi::cast(number)->value(); 681 // Hidden oddballs have negative smis. 682 const int kLeastHiddenOddballNumber = -7; 683 CHECK_LE(value, 1); 684 CHECK(value >= kLeastHiddenOddballNumber); 685 } 686 if (map() == heap->undefined_map()) { 687 CHECK(this == heap->undefined_value()); 688 } else if (map() == heap->the_hole_map()) { 689 CHECK(this == heap->the_hole_value()); 690 } else if (map() == heap->null_map()) { 691 CHECK(this == heap->null_value()); 692 } else if (map() == heap->boolean_map()) { 693 CHECK(this == heap->true_value() || 694 this == heap->false_value()); 695 } else if (map() == heap->uninitialized_map()) { 696 CHECK(this == heap->uninitialized_value()); 697 } else if (map() == heap->no_interceptor_result_sentinel_map()) { 698 CHECK(this == heap->no_interceptor_result_sentinel()); 699 } else if (map() == heap->arguments_marker_map()) { 700 CHECK(this == heap->arguments_marker()); 701 } else if (map() == heap->termination_exception_map()) { 702 CHECK(this == heap->termination_exception()); 703 } else if (map() == heap->exception_map()) { 704 CHECK(this == heap->exception()); 705 } else if (map() == heap->optimized_out_map()) { 706 CHECK(this == heap->optimized_out()); 707 } else if (map() == heap->stale_register_map()) { 708 CHECK(this == heap->stale_register()); 709 } else { 710 UNREACHABLE(); 711 } 712 } 713 714 715 void Cell::CellVerify() { 716 CHECK(IsCell()); 717 VerifyObjectField(kValueOffset); 718 } 719 720 721 void PropertyCell::PropertyCellVerify() { 722 CHECK(IsPropertyCell()); 723 VerifyObjectField(kValueOffset); 724 } 725 726 727 void WeakCell::WeakCellVerify() { 728 CHECK(IsWeakCell()); 729 VerifyObjectField(kValueOffset); 730 VerifyObjectField(kNextOffset); 731 } 732 733 734 void Code::CodeVerify() { 735 CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()), 736 kCodeAlignment)); 737 relocation_info()->ObjectVerify(); 738 Address last_gc_pc = NULL; 739 Isolate* isolate = GetIsolate(); 740 for (RelocIterator it(this); !it.done(); it.next()) { 741 it.rinfo()->Verify(isolate); 742 // Ensure that GC will not iterate twice over the same pointer. 743 if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) { 744 CHECK(it.rinfo()->pc() != last_gc_pc); 745 last_gc_pc = it.rinfo()->pc(); 746 } 747 } 748 CHECK(raw_type_feedback_info() == Smi::kZero || 749 raw_type_feedback_info()->IsSmi() == IsCodeStubOrIC()); 750 } 751 752 753 void Code::VerifyEmbeddedObjectsDependency() { 754 if (!CanContainWeakObjects()) return; 755 WeakCell* cell = CachedWeakCell(); 756 DisallowHeapAllocation no_gc; 757 Isolate* isolate = GetIsolate(); 758 HandleScope scope(isolate); 759 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); 760 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { 761 Object* obj = it.rinfo()->target_object(); 762 if (IsWeakObject(obj)) { 763 if (obj->IsMap()) { 764 Map* map = Map::cast(obj); 765 CHECK(map->dependent_code()->Contains(DependentCode::kWeakCodeGroup, 766 cell)); 767 } else if (obj->IsJSObject()) { 768 if (isolate->heap()->InNewSpace(obj)) { 769 ArrayList* list = 770 GetIsolate()->heap()->weak_new_space_object_to_code_list(); 771 bool found = false; 772 for (int i = 0; i < list->Length(); i += 2) { 773 WeakCell* obj_cell = WeakCell::cast(list->Get(i)); 774 if (!obj_cell->cleared() && obj_cell->value() == obj && 775 WeakCell::cast(list->Get(i + 1)) == cell) { 776 found = true; 777 break; 778 } 779 } 780 CHECK(found); 781 } else { 782 Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate); 783 DependentCode* dep = 784 GetIsolate()->heap()->LookupWeakObjectToCodeDependency(key_obj); 785 dep->Contains(DependentCode::kWeakCodeGroup, cell); 786 } 787 } 788 } 789 } 790 } 791 792 793 void JSArray::JSArrayVerify() { 794 JSObjectVerify(); 795 Isolate* isolate = GetIsolate(); 796 CHECK(length()->IsNumber() || length()->IsUndefined(isolate)); 797 // If a GC was caused while constructing this array, the elements 798 // pointer may point to a one pointer filler map. 799 if (!ElementsAreSafeToExamine()) return; 800 if (elements()->IsUndefined(isolate)) return; 801 CHECK(elements()->IsFixedArray() || elements()->IsFixedDoubleArray()); 802 if (!length()->IsNumber()) return; 803 // Verify that the length and the elements backing store are in sync. 804 if (length()->IsSmi() && HasFastElements()) { 805 int size = Smi::cast(length())->value(); 806 // Holey / Packed backing stores might have slack or might have not been 807 // properly initialized yet. 808 CHECK(size <= elements()->length() || 809 elements() == isolate->heap()->empty_fixed_array()); 810 } else { 811 CHECK(HasDictionaryElements()); 812 uint32_t array_length; 813 CHECK(length()->ToArrayLength(&array_length)); 814 if (array_length == 0xffffffff) { 815 CHECK(length()->ToArrayLength(&array_length)); 816 } 817 if (array_length != 0) { 818 SeededNumberDictionary* dict = SeededNumberDictionary::cast(elements()); 819 // The dictionary can never have more elements than the array length + 1. 820 // If the backing store grows the verification might be triggered with 821 // the old length in place. 822 uint32_t nof_elements = static_cast<uint32_t>(dict->NumberOfElements()); 823 if (nof_elements != 0) nof_elements--; 824 CHECK_LE(nof_elements, array_length); 825 } 826 } 827 } 828 829 830 void JSSet::JSSetVerify() { 831 CHECK(IsJSSet()); 832 JSObjectVerify(); 833 VerifyHeapPointer(table()); 834 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate())); 835 // TODO(arv): Verify OrderedHashTable too. 836 } 837 838 839 void JSMap::JSMapVerify() { 840 CHECK(IsJSMap()); 841 JSObjectVerify(); 842 VerifyHeapPointer(table()); 843 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate())); 844 // TODO(arv): Verify OrderedHashTable too. 845 } 846 847 848 void JSSetIterator::JSSetIteratorVerify() { 849 CHECK(IsJSSetIterator()); 850 JSObjectVerify(); 851 VerifyHeapPointer(table()); 852 Isolate* isolate = GetIsolate(); 853 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate)); 854 CHECK(index()->IsSmi() || index()->IsUndefined(isolate)); 855 CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate)); 856 } 857 858 859 void JSMapIterator::JSMapIteratorVerify() { 860 CHECK(IsJSMapIterator()); 861 JSObjectVerify(); 862 VerifyHeapPointer(table()); 863 Isolate* isolate = GetIsolate(); 864 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate)); 865 CHECK(index()->IsSmi() || index()->IsUndefined(isolate)); 866 CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate)); 867 } 868 869 870 void JSWeakMap::JSWeakMapVerify() { 871 CHECK(IsJSWeakMap()); 872 JSObjectVerify(); 873 VerifyHeapPointer(table()); 874 CHECK(table()->IsHashTable() || table()->IsUndefined(GetIsolate())); 875 } 876 877 void JSArrayIterator::JSArrayIteratorVerify() { 878 CHECK(IsJSArrayIterator()); 879 JSObjectVerify(); 880 CHECK(object()->IsJSReceiver() || object()->IsUndefined(GetIsolate())); 881 882 CHECK_GE(index()->Number(), 0); 883 CHECK_LE(index()->Number(), kMaxSafeInteger); 884 CHECK(object_map()->IsMap() || object_map()->IsUndefined(GetIsolate())); 885 } 886 887 void JSStringIterator::JSStringIteratorVerify() { 888 CHECK(IsJSStringIterator()); 889 JSObjectVerify(); 890 CHECK(string()->IsString()); 891 892 CHECK_GE(index(), 0); 893 CHECK_LE(index(), String::kMaxLength); 894 } 895 896 void JSAsyncFromSyncIterator::JSAsyncFromSyncIteratorVerify() { 897 CHECK(IsJSAsyncFromSyncIterator()); 898 JSObjectVerify(); 899 VerifyHeapPointer(sync_iterator()); 900 } 901 902 void JSWeakSet::JSWeakSetVerify() { 903 CHECK(IsJSWeakSet()); 904 JSObjectVerify(); 905 VerifyHeapPointer(table()); 906 CHECK(table()->IsHashTable() || table()->IsUndefined(GetIsolate())); 907 } 908 909 void JSPromiseCapability::JSPromiseCapabilityVerify() { 910 CHECK(IsJSPromiseCapability()); 911 JSObjectVerify(); 912 VerifyPointer(promise()); 913 VerifyPointer(resolve()); 914 VerifyPointer(reject()); 915 } 916 917 void JSPromise::JSPromiseVerify() { 918 CHECK(IsJSPromise()); 919 JSObjectVerify(); 920 Isolate* isolate = GetIsolate(); 921 VerifySmiField(kStatusOffset); 922 CHECK(result()->IsUndefined(isolate) || result()->IsObject()); 923 CHECK(deferred_promise()->IsUndefined(isolate) || 924 deferred_promise()->IsJSReceiver() || 925 deferred_promise()->IsFixedArray()); 926 CHECK(deferred_on_resolve()->IsUndefined(isolate) || 927 deferred_on_resolve()->IsCallable() || 928 deferred_on_resolve()->IsFixedArray()); 929 CHECK(deferred_on_reject()->IsUndefined(isolate) || 930 deferred_on_reject()->IsCallable() || 931 deferred_on_reject()->IsFixedArray()); 932 CHECK(fulfill_reactions()->IsUndefined(isolate) || 933 fulfill_reactions()->IsCallable() || fulfill_reactions()->IsSymbol() || 934 fulfill_reactions()->IsFixedArray()); 935 CHECK(reject_reactions()->IsUndefined(isolate) || 936 reject_reactions()->IsSymbol() || reject_reactions()->IsCallable() || 937 reject_reactions()->IsFixedArray()); 938 } 939 940 void JSRegExp::JSRegExpVerify() { 941 JSObjectVerify(); 942 Isolate* isolate = GetIsolate(); 943 CHECK(data()->IsUndefined(isolate) || data()->IsFixedArray()); 944 switch (TypeTag()) { 945 case JSRegExp::ATOM: { 946 FixedArray* arr = FixedArray::cast(data()); 947 CHECK(arr->get(JSRegExp::kAtomPatternIndex)->IsString()); 948 break; 949 } 950 case JSRegExp::IRREGEXP: { 951 bool is_native = RegExpImpl::UsesNativeRegExp(); 952 953 FixedArray* arr = FixedArray::cast(data()); 954 Object* one_byte_data = arr->get(JSRegExp::kIrregexpLatin1CodeIndex); 955 // Smi : Not compiled yet (-1) or code prepared for flushing. 956 // JSObject: Compilation error. 957 // Code/ByteArray: Compiled code. 958 CHECK( 959 one_byte_data->IsSmi() || 960 (is_native ? one_byte_data->IsCode() : one_byte_data->IsByteArray())); 961 Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex); 962 CHECK(uc16_data->IsSmi() || 963 (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray())); 964 965 Object* one_byte_saved = 966 arr->get(JSRegExp::kIrregexpLatin1CodeSavedIndex); 967 CHECK(one_byte_saved->IsSmi() || one_byte_saved->IsString() || 968 one_byte_saved->IsCode()); 969 Object* uc16_saved = arr->get(JSRegExp::kIrregexpUC16CodeSavedIndex); 970 CHECK(uc16_saved->IsSmi() || uc16_saved->IsString() || 971 uc16_saved->IsCode()); 972 973 CHECK(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi()); 974 CHECK(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi()); 975 break; 976 } 977 default: 978 CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag()); 979 CHECK(data()->IsUndefined(isolate)); 980 break; 981 } 982 } 983 984 void JSProxy::JSProxyVerify() { 985 CHECK(IsJSProxy()); 986 VerifyPointer(target()); 987 VerifyPointer(handler()); 988 Isolate* isolate = GetIsolate(); 989 CHECK_EQ(target()->IsCallable(), map()->is_callable()); 990 CHECK_EQ(target()->IsConstructor(), map()->is_constructor()); 991 CHECK(hash()->IsSmi() || hash()->IsUndefined(isolate)); 992 CHECK(map()->prototype()->IsNull(isolate)); 993 // There should be no properties on a Proxy. 994 CHECK_EQ(0, map()->NumberOfOwnDescriptors()); 995 } 996 997 998 void JSArrayBuffer::JSArrayBufferVerify() { 999 CHECK(IsJSArrayBuffer()); 1000 JSObjectVerify(); 1001 VerifyPointer(byte_length()); 1002 CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber() || 1003 byte_length()->IsUndefined(GetIsolate())); 1004 } 1005 1006 1007 void JSArrayBufferView::JSArrayBufferViewVerify() { 1008 CHECK(IsJSArrayBufferView()); 1009 JSObjectVerify(); 1010 VerifyPointer(buffer()); 1011 Isolate* isolate = GetIsolate(); 1012 CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined(isolate) || 1013 buffer() == Smi::kZero); 1014 1015 VerifyPointer(raw_byte_offset()); 1016 CHECK(raw_byte_offset()->IsSmi() || raw_byte_offset()->IsHeapNumber() || 1017 raw_byte_offset()->IsUndefined(isolate)); 1018 1019 VerifyPointer(raw_byte_length()); 1020 CHECK(raw_byte_length()->IsSmi() || raw_byte_length()->IsHeapNumber() || 1021 raw_byte_length()->IsUndefined(isolate)); 1022 } 1023 1024 1025 void JSTypedArray::JSTypedArrayVerify() { 1026 CHECK(IsJSTypedArray()); 1027 JSArrayBufferViewVerify(); 1028 VerifyPointer(raw_length()); 1029 CHECK(raw_length()->IsSmi() || raw_length()->IsUndefined(GetIsolate())); 1030 VerifyPointer(elements()); 1031 } 1032 1033 1034 void JSDataView::JSDataViewVerify() { 1035 CHECK(IsJSDataView()); 1036 JSArrayBufferViewVerify(); 1037 } 1038 1039 1040 void Foreign::ForeignVerify() { 1041 CHECK(IsForeign()); 1042 } 1043 1044 1045 void PromiseResolveThenableJobInfo::PromiseResolveThenableJobInfoVerify() { 1046 CHECK(IsPromiseResolveThenableJobInfo()); 1047 CHECK(thenable()->IsJSReceiver()); 1048 CHECK(then()->IsJSReceiver()); 1049 CHECK(resolve()->IsJSFunction()); 1050 CHECK(reject()->IsJSFunction()); 1051 CHECK(context()->IsContext()); 1052 } 1053 1054 void PromiseReactionJobInfo::PromiseReactionJobInfoVerify() { 1055 Isolate* isolate = GetIsolate(); 1056 CHECK(IsPromiseReactionJobInfo()); 1057 CHECK(value()->IsObject()); 1058 CHECK(tasks()->IsFixedArray() || tasks()->IsCallable() || 1059 tasks()->IsSymbol()); 1060 CHECK(deferred_promise()->IsUndefined(isolate) || 1061 deferred_promise()->IsJSReceiver() || 1062 deferred_promise()->IsFixedArray()); 1063 CHECK(deferred_on_resolve()->IsUndefined(isolate) || 1064 deferred_on_resolve()->IsCallable() || 1065 deferred_on_resolve()->IsFixedArray()); 1066 CHECK(deferred_on_reject()->IsUndefined(isolate) || 1067 deferred_on_reject()->IsCallable() || 1068 deferred_on_reject()->IsFixedArray()); 1069 CHECK(context()->IsContext()); 1070 } 1071 1072 void JSModuleNamespace::JSModuleNamespaceVerify() { 1073 CHECK(IsJSModuleNamespace()); 1074 VerifyPointer(module()); 1075 } 1076 1077 void ModuleInfoEntry::ModuleInfoEntryVerify() { 1078 Isolate* isolate = GetIsolate(); 1079 CHECK(IsModuleInfoEntry()); 1080 1081 CHECK(export_name()->IsUndefined(isolate) || export_name()->IsString()); 1082 CHECK(local_name()->IsUndefined(isolate) || local_name()->IsString()); 1083 CHECK(import_name()->IsUndefined(isolate) || import_name()->IsString()); 1084 1085 VerifySmiField(kModuleRequestOffset); 1086 VerifySmiField(kCellIndexOffset); 1087 VerifySmiField(kBegPosOffset); 1088 VerifySmiField(kEndPosOffset); 1089 1090 CHECK_IMPLIES(import_name()->IsString(), module_request() >= 0); 1091 CHECK_IMPLIES(export_name()->IsString() && import_name()->IsString(), 1092 local_name()->IsUndefined(isolate)); 1093 } 1094 1095 void Module::ModuleVerify() { 1096 CHECK(IsModule()); 1097 1098 VerifyPointer(code()); 1099 VerifyPointer(exports()); 1100 VerifyPointer(module_namespace()); 1101 VerifyPointer(requested_modules()); 1102 VerifySmiField(kHashOffset); 1103 1104 CHECK((!instantiated() && code()->IsSharedFunctionInfo()) || 1105 (instantiated() && !evaluated() && code()->IsJSFunction()) || 1106 (instantiated() && evaluated() && code()->IsModuleInfo())); 1107 1108 CHECK(module_namespace()->IsUndefined(GetIsolate()) || 1109 module_namespace()->IsJSModuleNamespace()); 1110 if (module_namespace()->IsJSModuleNamespace()) { 1111 CHECK_EQ(JSModuleNamespace::cast(module_namespace())->module(), this); 1112 } 1113 1114 CHECK_EQ(requested_modules()->length(), info()->module_requests()->length()); 1115 1116 CHECK_NE(hash(), 0); 1117 } 1118 1119 void PrototypeInfo::PrototypeInfoVerify() { 1120 CHECK(IsPrototypeInfo()); 1121 CHECK(weak_cell()->IsWeakCell() || weak_cell()->IsUndefined(GetIsolate())); 1122 if (prototype_users()->IsWeakFixedArray()) { 1123 WeakFixedArray::cast(prototype_users())->FixedArrayVerify(); 1124 } else { 1125 CHECK(prototype_users()->IsSmi()); 1126 } 1127 CHECK(validity_cell()->IsCell() || validity_cell()->IsSmi()); 1128 } 1129 1130 void Tuple2::Tuple2Verify() { 1131 CHECK(IsTuple2()); 1132 VerifyObjectField(kValue1Offset); 1133 VerifyObjectField(kValue2Offset); 1134 } 1135 1136 void Tuple3::Tuple3Verify() { 1137 CHECK(IsTuple3()); 1138 VerifyObjectField(kValue1Offset); 1139 VerifyObjectField(kValue2Offset); 1140 VerifyObjectField(kValue3Offset); 1141 } 1142 1143 void ContextExtension::ContextExtensionVerify() { 1144 CHECK(IsContextExtension()); 1145 VerifyObjectField(kScopeInfoOffset); 1146 VerifyObjectField(kExtensionOffset); 1147 } 1148 1149 void ConstantElementsPair::ConstantElementsPairVerify() { 1150 CHECK(IsConstantElementsPair()); 1151 VerifySmiField(kElementsKindOffset); 1152 VerifyObjectField(kConstantValuesOffset); 1153 } 1154 1155 void AccessorInfo::AccessorInfoVerify() { 1156 CHECK(IsAccessorInfo()); 1157 VerifyPointer(name()); 1158 VerifyPointer(expected_receiver_type()); 1159 VerifyPointer(getter()); 1160 VerifyPointer(setter()); 1161 VerifyPointer(js_getter()); 1162 VerifyPointer(data()); 1163 } 1164 1165 1166 void AccessorPair::AccessorPairVerify() { 1167 CHECK(IsAccessorPair()); 1168 VerifyPointer(getter()); 1169 VerifyPointer(setter()); 1170 } 1171 1172 1173 void AccessCheckInfo::AccessCheckInfoVerify() { 1174 CHECK(IsAccessCheckInfo()); 1175 VerifyPointer(callback()); 1176 VerifyPointer(named_interceptor()); 1177 VerifyPointer(indexed_interceptor()); 1178 VerifyPointer(data()); 1179 } 1180 1181 1182 void InterceptorInfo::InterceptorInfoVerify() { 1183 CHECK(IsInterceptorInfo()); 1184 VerifyPointer(getter()); 1185 VerifyPointer(setter()); 1186 VerifyPointer(query()); 1187 VerifyPointer(deleter()); 1188 VerifyPointer(enumerator()); 1189 VerifyPointer(data()); 1190 VerifySmiField(kFlagsOffset); 1191 } 1192 1193 1194 void CallHandlerInfo::CallHandlerInfoVerify() { 1195 CHECK(IsCallHandlerInfo()); 1196 VerifyPointer(callback()); 1197 VerifyPointer(data()); 1198 } 1199 1200 1201 void TemplateInfo::TemplateInfoVerify() { 1202 VerifyPointer(tag()); 1203 VerifyPointer(property_list()); 1204 VerifyPointer(property_accessors()); 1205 } 1206 1207 1208 void FunctionTemplateInfo::FunctionTemplateInfoVerify() { 1209 CHECK(IsFunctionTemplateInfo()); 1210 TemplateInfoVerify(); 1211 VerifyPointer(serial_number()); 1212 VerifyPointer(call_code()); 1213 VerifyPointer(prototype_template()); 1214 VerifyPointer(parent_template()); 1215 VerifyPointer(named_property_handler()); 1216 VerifyPointer(indexed_property_handler()); 1217 VerifyPointer(instance_template()); 1218 VerifyPointer(signature()); 1219 VerifyPointer(access_check_info()); 1220 VerifyPointer(cached_property_name()); 1221 } 1222 1223 1224 void ObjectTemplateInfo::ObjectTemplateInfoVerify() { 1225 CHECK(IsObjectTemplateInfo()); 1226 TemplateInfoVerify(); 1227 VerifyPointer(constructor()); 1228 VerifyPointer(data()); 1229 } 1230 1231 1232 void AllocationSite::AllocationSiteVerify() { 1233 CHECK(IsAllocationSite()); 1234 } 1235 1236 1237 void AllocationMemento::AllocationMementoVerify() { 1238 CHECK(IsAllocationMemento()); 1239 VerifyHeapPointer(allocation_site()); 1240 CHECK(!IsValid() || GetAllocationSite()->IsAllocationSite()); 1241 } 1242 1243 1244 void Script::ScriptVerify() { 1245 CHECK(IsScript()); 1246 VerifyPointer(source()); 1247 VerifyPointer(name()); 1248 VerifyPointer(wrapper()); 1249 VerifyPointer(line_ends()); 1250 } 1251 1252 1253 void NormalizedMapCache::NormalizedMapCacheVerify() { 1254 FixedArray::cast(this)->FixedArrayVerify(); 1255 if (FLAG_enable_slow_asserts) { 1256 Isolate* isolate = GetIsolate(); 1257 for (int i = 0; i < length(); i++) { 1258 Object* e = FixedArray::get(i); 1259 if (e->IsMap()) { 1260 Map::cast(e)->DictionaryMapVerify(); 1261 } else { 1262 CHECK(e->IsUndefined(isolate)); 1263 } 1264 } 1265 } 1266 } 1267 1268 1269 void DebugInfo::DebugInfoVerify() { 1270 CHECK(IsDebugInfo()); 1271 VerifyPointer(shared()); 1272 VerifyPointer(debug_bytecode_array()); 1273 VerifyPointer(break_points()); 1274 } 1275 1276 1277 void BreakPointInfo::BreakPointInfoVerify() { 1278 CHECK(IsBreakPointInfo()); 1279 VerifyPointer(break_point_objects()); 1280 } 1281 #endif // VERIFY_HEAP 1282 1283 #ifdef DEBUG 1284 1285 void JSObject::IncrementSpillStatistics(SpillInformation* info) { 1286 info->number_of_objects_++; 1287 // Named properties 1288 if (HasFastProperties()) { 1289 info->number_of_objects_with_fast_properties_++; 1290 info->number_of_fast_used_fields_ += map()->NextFreePropertyIndex(); 1291 info->number_of_fast_unused_fields_ += map()->unused_property_fields(); 1292 } else if (IsJSGlobalObject()) { 1293 GlobalDictionary* dict = global_dictionary(); 1294 info->number_of_slow_used_properties_ += dict->NumberOfElements(); 1295 info->number_of_slow_unused_properties_ += 1296 dict->Capacity() - dict->NumberOfElements(); 1297 } else { 1298 NameDictionary* dict = property_dictionary(); 1299 info->number_of_slow_used_properties_ += dict->NumberOfElements(); 1300 info->number_of_slow_unused_properties_ += 1301 dict->Capacity() - dict->NumberOfElements(); 1302 } 1303 // Indexed properties 1304 switch (GetElementsKind()) { 1305 case FAST_HOLEY_SMI_ELEMENTS: 1306 case FAST_SMI_ELEMENTS: 1307 case FAST_HOLEY_DOUBLE_ELEMENTS: 1308 case FAST_DOUBLE_ELEMENTS: 1309 case FAST_HOLEY_ELEMENTS: 1310 case FAST_ELEMENTS: 1311 case FAST_STRING_WRAPPER_ELEMENTS: { 1312 info->number_of_objects_with_fast_elements_++; 1313 int holes = 0; 1314 FixedArray* e = FixedArray::cast(elements()); 1315 int len = e->length(); 1316 Isolate* isolate = GetIsolate(); 1317 for (int i = 0; i < len; i++) { 1318 if (e->get(i)->IsTheHole(isolate)) holes++; 1319 } 1320 info->number_of_fast_used_elements_ += len - holes; 1321 info->number_of_fast_unused_elements_ += holes; 1322 break; 1323 } 1324 1325 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 1326 case TYPE##_ELEMENTS: 1327 1328 TYPED_ARRAYS(TYPED_ARRAY_CASE) 1329 #undef TYPED_ARRAY_CASE 1330 { info->number_of_objects_with_fast_elements_++; 1331 FixedArrayBase* e = FixedArrayBase::cast(elements()); 1332 info->number_of_fast_used_elements_ += e->length(); 1333 break; 1334 } 1335 case DICTIONARY_ELEMENTS: 1336 case SLOW_STRING_WRAPPER_ELEMENTS: { 1337 SeededNumberDictionary* dict = element_dictionary(); 1338 info->number_of_slow_used_elements_ += dict->NumberOfElements(); 1339 info->number_of_slow_unused_elements_ += 1340 dict->Capacity() - dict->NumberOfElements(); 1341 break; 1342 } 1343 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 1344 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: 1345 case NO_ELEMENTS: 1346 break; 1347 } 1348 } 1349 1350 1351 void JSObject::SpillInformation::Clear() { 1352 number_of_objects_ = 0; 1353 number_of_objects_with_fast_properties_ = 0; 1354 number_of_objects_with_fast_elements_ = 0; 1355 number_of_fast_used_fields_ = 0; 1356 number_of_fast_unused_fields_ = 0; 1357 number_of_slow_used_properties_ = 0; 1358 number_of_slow_unused_properties_ = 0; 1359 number_of_fast_used_elements_ = 0; 1360 number_of_fast_unused_elements_ = 0; 1361 number_of_slow_used_elements_ = 0; 1362 number_of_slow_unused_elements_ = 0; 1363 } 1364 1365 1366 void JSObject::SpillInformation::Print() { 1367 PrintF("\n JSObject Spill Statistics (#%d):\n", number_of_objects_); 1368 1369 PrintF(" - fast properties (#%d): %d (used) %d (unused)\n", 1370 number_of_objects_with_fast_properties_, 1371 number_of_fast_used_fields_, number_of_fast_unused_fields_); 1372 1373 PrintF(" - slow properties (#%d): %d (used) %d (unused)\n", 1374 number_of_objects_ - number_of_objects_with_fast_properties_, 1375 number_of_slow_used_properties_, number_of_slow_unused_properties_); 1376 1377 PrintF(" - fast elements (#%d): %d (used) %d (unused)\n", 1378 number_of_objects_with_fast_elements_, 1379 number_of_fast_used_elements_, number_of_fast_unused_elements_); 1380 1381 PrintF(" - slow elements (#%d): %d (used) %d (unused)\n", 1382 number_of_objects_ - number_of_objects_with_fast_elements_, 1383 number_of_slow_used_elements_, number_of_slow_unused_elements_); 1384 1385 PrintF("\n"); 1386 } 1387 1388 1389 bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) { 1390 if (valid_entries == -1) valid_entries = number_of_descriptors(); 1391 Name* current_key = NULL; 1392 uint32_t current = 0; 1393 for (int i = 0; i < number_of_descriptors(); i++) { 1394 Name* key = GetSortedKey(i); 1395 if (key == current_key) { 1396 Print(); 1397 return false; 1398 } 1399 current_key = key; 1400 uint32_t hash = GetSortedKey(i)->Hash(); 1401 if (hash < current) { 1402 Print(); 1403 return false; 1404 } 1405 current = hash; 1406 } 1407 return true; 1408 } 1409 1410 1411 bool TransitionArray::IsSortedNoDuplicates(int valid_entries) { 1412 DCHECK(valid_entries == -1); 1413 Name* prev_key = NULL; 1414 PropertyKind prev_kind = kData; 1415 PropertyAttributes prev_attributes = NONE; 1416 uint32_t prev_hash = 0; 1417 for (int i = 0; i < number_of_transitions(); i++) { 1418 Name* key = GetSortedKey(i); 1419 uint32_t hash = key->Hash(); 1420 PropertyKind kind = kData; 1421 PropertyAttributes attributes = NONE; 1422 if (!IsSpecialTransition(key)) { 1423 Map* target = GetTarget(i); 1424 PropertyDetails details = GetTargetDetails(key, target); 1425 kind = details.kind(); 1426 attributes = details.attributes(); 1427 } else { 1428 // Duplicate entries are not allowed for non-property transitions. 1429 CHECK_NE(prev_key, key); 1430 } 1431 1432 int cmp = CompareKeys(prev_key, prev_hash, prev_kind, prev_attributes, key, 1433 hash, kind, attributes); 1434 if (cmp >= 0) { 1435 Print(); 1436 return false; 1437 } 1438 prev_key = key; 1439 prev_hash = hash; 1440 prev_attributes = attributes; 1441 prev_kind = kind; 1442 } 1443 return true; 1444 } 1445 1446 1447 // static 1448 bool TransitionArray::IsSortedNoDuplicates(Map* map) { 1449 Object* raw_transitions = map->raw_transitions(); 1450 if (IsFullTransitionArray(raw_transitions)) { 1451 return TransitionArray::cast(raw_transitions)->IsSortedNoDuplicates(); 1452 } 1453 // Simple and non-existent transitions are always sorted. 1454 return true; 1455 } 1456 1457 1458 static bool CheckOneBackPointer(Map* current_map, Object* target) { 1459 return !target->IsMap() || Map::cast(target)->GetBackPointer() == current_map; 1460 } 1461 1462 1463 // static 1464 bool TransitionArray::IsConsistentWithBackPointers(Map* map) { 1465 Object* transitions = map->raw_transitions(); 1466 for (int i = 0; i < TransitionArray::NumberOfTransitions(transitions); ++i) { 1467 Map* target = TransitionArray::GetTarget(transitions, i); 1468 if (!CheckOneBackPointer(map, target)) return false; 1469 } 1470 return true; 1471 } 1472 1473 1474 // Estimates if there is a path from the object to a context. 1475 // This function is not precise, and can return false even if 1476 // there is a path to a context. 1477 bool CanLeak(Object* obj, Heap* heap, bool skip_weak_cell) { 1478 if (!obj->IsHeapObject()) return false; 1479 if (obj->IsWeakCell()) { 1480 if (skip_weak_cell) return false; 1481 return CanLeak(WeakCell::cast(obj)->value(), heap, skip_weak_cell); 1482 } 1483 if (obj->IsCell()) { 1484 return CanLeak(Cell::cast(obj)->value(), heap, skip_weak_cell); 1485 } 1486 if (obj->IsPropertyCell()) { 1487 return CanLeak(PropertyCell::cast(obj)->value(), heap, skip_weak_cell); 1488 } 1489 if (obj->IsContext()) return true; 1490 if (obj->IsMap()) { 1491 Map* map = Map::cast(obj); 1492 for (int i = 0; i < Heap::kStrongRootListLength; i++) { 1493 Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i); 1494 if (map == heap->root(root_index)) return false; 1495 } 1496 return true; 1497 } 1498 return CanLeak(HeapObject::cast(obj)->map(), heap, skip_weak_cell); 1499 } 1500 1501 1502 void Code::VerifyEmbeddedObjects(VerifyMode mode) { 1503 if (kind() == OPTIMIZED_FUNCTION) return; 1504 Heap* heap = GetIsolate()->heap(); 1505 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | 1506 RelocInfo::ModeMask(RelocInfo::CELL); 1507 bool skip_weak_cell = (mode == kNoContextSpecificPointers) ? false : true; 1508 for (RelocIterator it(this, mask); !it.done(); it.next()) { 1509 Object* target = it.rinfo()->rmode() == RelocInfo::CELL 1510 ? it.rinfo()->target_cell() 1511 : it.rinfo()->target_object(); 1512 CHECK(!CanLeak(target, heap, skip_weak_cell)); 1513 } 1514 } 1515 1516 1517 // Verify that the debugger can redirect old code to the new code. 1518 void Code::VerifyRecompiledCode(Code* old_code, Code* new_code) { 1519 if (old_code->kind() != FUNCTION) return; 1520 if (new_code->kind() != FUNCTION) return; 1521 Isolate* isolate = old_code->GetIsolate(); 1522 // Do not verify during bootstrapping. We may replace code using %SetCode. 1523 if (isolate->bootstrapper()->IsActive()) return; 1524 1525 static const int mask = RelocInfo::kCodeTargetMask; 1526 RelocIterator old_it(old_code, mask); 1527 RelocIterator new_it(new_code, mask); 1528 Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck); 1529 1530 while (!old_it.done()) { 1531 RelocInfo* rinfo = old_it.rinfo(); 1532 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); 1533 CHECK(!target->is_handler() && !target->is_inline_cache_stub()); 1534 if (target == stack_check) break; 1535 old_it.next(); 1536 } 1537 1538 while (!new_it.done()) { 1539 RelocInfo* rinfo = new_it.rinfo(); 1540 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); 1541 CHECK(!target->is_handler() && !target->is_inline_cache_stub()); 1542 if (target == stack_check) break; 1543 new_it.next(); 1544 } 1545 1546 // Either both are done because there is no stack check. 1547 // Or we are past the prologue for both. 1548 CHECK_EQ(new_it.done(), old_it.done()); 1549 1550 // After the prologue, each call in the old code has a corresponding call 1551 // in the new code. 1552 while (!old_it.done() && !new_it.done()) { 1553 Code* old_target = 1554 Code::GetCodeFromTargetAddress(old_it.rinfo()->target_address()); 1555 Code* new_target = 1556 Code::GetCodeFromTargetAddress(new_it.rinfo()->target_address()); 1557 CHECK_EQ(old_target->kind(), new_target->kind()); 1558 // Check call target for equality unless it's an IC or an interrupt check. 1559 // In both cases they may be patched to be something else. 1560 if (!old_target->is_handler() && !old_target->is_inline_cache_stub() && 1561 new_target != isolate->builtins()->builtin(Builtins::kInterruptCheck)) { 1562 CHECK_EQ(old_target, new_target); 1563 } 1564 old_it.next(); 1565 new_it.next(); 1566 } 1567 1568 // Both are done at the same time. 1569 CHECK_EQ(new_it.done(), old_it.done()); 1570 } 1571 1572 1573 #endif // DEBUG 1574 1575 } // namespace internal 1576 } // namespace v8 1577