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