1// Copyright 2012 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include "v8.h" 29 30#include "disassembler.h" 31#include "disasm.h" 32#include "jsregexp.h" 33#include "macro-assembler.h" 34#include "objects-visiting.h" 35 36namespace v8 { 37namespace internal { 38 39#ifdef VERIFY_HEAP 40 41void MaybeObject::Verify() { 42 Object* this_as_object; 43 if (ToObject(&this_as_object)) { 44 if (this_as_object->IsSmi()) { 45 Smi::cast(this_as_object)->SmiVerify(); 46 } else { 47 HeapObject::cast(this_as_object)->HeapObjectVerify(); 48 } 49 } else { 50 Failure::cast(this)->FailureVerify(); 51 } 52} 53 54 55void Object::VerifyPointer(Object* p) { 56 if (p->IsHeapObject()) { 57 HeapObject::VerifyHeapPointer(p); 58 } else { 59 CHECK(p->IsSmi()); 60 } 61} 62 63 64void Smi::SmiVerify() { 65 CHECK(IsSmi()); 66} 67 68 69void Failure::FailureVerify() { 70 CHECK(IsFailure()); 71} 72 73 74void HeapObject::HeapObjectVerify() { 75 InstanceType instance_type = map()->instance_type(); 76 77 if (instance_type < FIRST_NONSTRING_TYPE) { 78 String::cast(this)->StringVerify(); 79 return; 80 } 81 82 switch (instance_type) { 83 case SYMBOL_TYPE: 84 Symbol::cast(this)->SymbolVerify(); 85 break; 86 case MAP_TYPE: 87 Map::cast(this)->MapVerify(); 88 break; 89 case HEAP_NUMBER_TYPE: 90 HeapNumber::cast(this)->HeapNumberVerify(); 91 break; 92 case FIXED_ARRAY_TYPE: 93 FixedArray::cast(this)->FixedArrayVerify(); 94 break; 95 case FIXED_DOUBLE_ARRAY_TYPE: 96 FixedDoubleArray::cast(this)->FixedDoubleArrayVerify(); 97 break; 98 case CONSTANT_POOL_ARRAY_TYPE: 99 ConstantPoolArray::cast(this)->ConstantPoolArrayVerify(); 100 break; 101 case BYTE_ARRAY_TYPE: 102 ByteArray::cast(this)->ByteArrayVerify(); 103 break; 104 case FREE_SPACE_TYPE: 105 FreeSpace::cast(this)->FreeSpaceVerify(); 106 break; 107 case EXTERNAL_PIXEL_ARRAY_TYPE: 108 ExternalPixelArray::cast(this)->ExternalPixelArrayVerify(); 109 break; 110 case EXTERNAL_BYTE_ARRAY_TYPE: 111 ExternalByteArray::cast(this)->ExternalByteArrayVerify(); 112 break; 113 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 114 ExternalUnsignedByteArray::cast(this)->ExternalUnsignedByteArrayVerify(); 115 break; 116 case EXTERNAL_SHORT_ARRAY_TYPE: 117 ExternalShortArray::cast(this)->ExternalShortArrayVerify(); 118 break; 119 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: 120 ExternalUnsignedShortArray::cast(this)-> 121 ExternalUnsignedShortArrayVerify(); 122 break; 123 case EXTERNAL_INT_ARRAY_TYPE: 124 ExternalIntArray::cast(this)->ExternalIntArrayVerify(); 125 break; 126 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: 127 ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayVerify(); 128 break; 129 case EXTERNAL_FLOAT_ARRAY_TYPE: 130 ExternalFloatArray::cast(this)->ExternalFloatArrayVerify(); 131 break; 132 case EXTERNAL_DOUBLE_ARRAY_TYPE: 133 ExternalDoubleArray::cast(this)->ExternalDoubleArrayVerify(); 134 break; 135 case CODE_TYPE: 136 Code::cast(this)->CodeVerify(); 137 break; 138 case ODDBALL_TYPE: 139 Oddball::cast(this)->OddballVerify(); 140 break; 141 case JS_OBJECT_TYPE: 142 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 143 JSObject::cast(this)->JSObjectVerify(); 144 break; 145 case JS_GENERATOR_OBJECT_TYPE: 146 JSGeneratorObject::cast(this)->JSGeneratorObjectVerify(); 147 break; 148 case JS_MODULE_TYPE: 149 JSModule::cast(this)->JSModuleVerify(); 150 break; 151 case JS_VALUE_TYPE: 152 JSValue::cast(this)->JSValueVerify(); 153 break; 154 case JS_DATE_TYPE: 155 JSDate::cast(this)->JSDateVerify(); 156 break; 157 case JS_FUNCTION_TYPE: 158 JSFunction::cast(this)->JSFunctionVerify(); 159 break; 160 case JS_GLOBAL_PROXY_TYPE: 161 JSGlobalProxy::cast(this)->JSGlobalProxyVerify(); 162 break; 163 case JS_GLOBAL_OBJECT_TYPE: 164 JSGlobalObject::cast(this)->JSGlobalObjectVerify(); 165 break; 166 case JS_BUILTINS_OBJECT_TYPE: 167 JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify(); 168 break; 169 case CELL_TYPE: 170 Cell::cast(this)->CellVerify(); 171 break; 172 case PROPERTY_CELL_TYPE: 173 PropertyCell::cast(this)->PropertyCellVerify(); 174 break; 175 case JS_ARRAY_TYPE: 176 JSArray::cast(this)->JSArrayVerify(); 177 break; 178 case JS_SET_TYPE: 179 JSSet::cast(this)->JSSetVerify(); 180 break; 181 case JS_MAP_TYPE: 182 JSMap::cast(this)->JSMapVerify(); 183 break; 184 case JS_WEAK_MAP_TYPE: 185 JSWeakMap::cast(this)->JSWeakMapVerify(); 186 break; 187 case JS_WEAK_SET_TYPE: 188 JSWeakSet::cast(this)->JSWeakSetVerify(); 189 break; 190 case JS_REGEXP_TYPE: 191 JSRegExp::cast(this)->JSRegExpVerify(); 192 break; 193 case FILLER_TYPE: 194 break; 195 case JS_PROXY_TYPE: 196 JSProxy::cast(this)->JSProxyVerify(); 197 break; 198 case JS_FUNCTION_PROXY_TYPE: 199 JSFunctionProxy::cast(this)->JSFunctionProxyVerify(); 200 break; 201 case FOREIGN_TYPE: 202 Foreign::cast(this)->ForeignVerify(); 203 break; 204 case SHARED_FUNCTION_INFO_TYPE: 205 SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify(); 206 break; 207 case JS_MESSAGE_OBJECT_TYPE: 208 JSMessageObject::cast(this)->JSMessageObjectVerify(); 209 break; 210 case JS_ARRAY_BUFFER_TYPE: 211 JSArrayBuffer::cast(this)->JSArrayBufferVerify(); 212 break; 213 case JS_TYPED_ARRAY_TYPE: 214 JSTypedArray::cast(this)->JSTypedArrayVerify(); 215 break; 216 case JS_DATA_VIEW_TYPE: 217 JSDataView::cast(this)->JSDataViewVerify(); 218 break; 219 220#define MAKE_STRUCT_CASE(NAME, Name, name) \ 221 case NAME##_TYPE: \ 222 Name::cast(this)->Name##Verify(); \ 223 break; 224 STRUCT_LIST(MAKE_STRUCT_CASE) 225#undef MAKE_STRUCT_CASE 226 227 default: 228 UNREACHABLE(); 229 break; 230 } 231} 232 233 234void HeapObject::VerifyHeapPointer(Object* p) { 235 CHECK(p->IsHeapObject()); 236 HeapObject* ho = HeapObject::cast(p); 237 CHECK(ho->GetHeap()->Contains(ho)); 238} 239 240 241void Symbol::SymbolVerify() { 242 CHECK(IsSymbol()); 243 CHECK(HasHashCode()); 244 CHECK_GT(Hash(), 0); 245 CHECK(name()->IsUndefined() || name()->IsString()); 246 CHECK(flags()->IsSmi()); 247} 248 249 250void HeapNumber::HeapNumberVerify() { 251 CHECK(IsHeapNumber()); 252} 253 254 255void ByteArray::ByteArrayVerify() { 256 CHECK(IsByteArray()); 257} 258 259 260void FreeSpace::FreeSpaceVerify() { 261 CHECK(IsFreeSpace()); 262} 263 264 265void ExternalPixelArray::ExternalPixelArrayVerify() { 266 CHECK(IsExternalPixelArray()); 267} 268 269 270void ExternalByteArray::ExternalByteArrayVerify() { 271 CHECK(IsExternalByteArray()); 272} 273 274 275void ExternalUnsignedByteArray::ExternalUnsignedByteArrayVerify() { 276 CHECK(IsExternalUnsignedByteArray()); 277} 278 279 280void ExternalShortArray::ExternalShortArrayVerify() { 281 CHECK(IsExternalShortArray()); 282} 283 284 285void ExternalUnsignedShortArray::ExternalUnsignedShortArrayVerify() { 286 CHECK(IsExternalUnsignedShortArray()); 287} 288 289 290void ExternalIntArray::ExternalIntArrayVerify() { 291 CHECK(IsExternalIntArray()); 292} 293 294 295void ExternalUnsignedIntArray::ExternalUnsignedIntArrayVerify() { 296 CHECK(IsExternalUnsignedIntArray()); 297} 298 299 300void ExternalFloatArray::ExternalFloatArrayVerify() { 301 CHECK(IsExternalFloatArray()); 302} 303 304 305void ExternalDoubleArray::ExternalDoubleArrayVerify() { 306 CHECK(IsExternalDoubleArray()); 307} 308 309 310bool JSObject::ElementsAreSafeToExamine() { 311 return (FLAG_use_gvn && FLAG_use_allocation_folding) || 312 reinterpret_cast<Map*>(elements()) != 313 GetHeap()->one_pointer_filler_map(); 314} 315 316 317void JSObject::JSObjectVerify() { 318 VerifyHeapPointer(properties()); 319 VerifyHeapPointer(elements()); 320 321 if (GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS) { 322 CHECK(this->elements()->IsFixedArray()); 323 CHECK_GE(this->elements()->length(), 2); 324 } 325 326 if (HasFastProperties()) { 327 CHECK_EQ(map()->unused_property_fields(), 328 (map()->inobject_properties() + properties()->length() - 329 map()->NextFreePropertyIndex())); 330 DescriptorArray* descriptors = map()->instance_descriptors(); 331 for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) { 332 if (descriptors->GetDetails(i).type() == FIELD) { 333 Representation r = descriptors->GetDetails(i).representation(); 334 int field = descriptors->GetFieldIndex(i); 335 Object* value = RawFastPropertyAt(field); 336 if (r.IsDouble()) ASSERT(value->IsHeapNumber()); 337 if (value->IsUninitialized()) continue; 338 if (r.IsSmi()) ASSERT(value->IsSmi()); 339 if (r.IsHeapObject()) ASSERT(value->IsHeapObject()); 340 } 341 } 342 } 343 344 // If a GC was caused while constructing this object, the elements 345 // pointer may point to a one pointer filler map. 346 if (ElementsAreSafeToExamine()) { 347 CHECK_EQ((map()->has_fast_smi_or_object_elements() || 348 (elements() == GetHeap()->empty_fixed_array())), 349 (elements()->map() == GetHeap()->fixed_array_map() || 350 elements()->map() == GetHeap()->fixed_cow_array_map())); 351 CHECK(map()->has_fast_object_elements() == HasFastObjectElements()); 352 } 353} 354 355 356void Map::MapVerify() { 357 Heap* heap = GetHeap(); 358 CHECK(!heap->InNewSpace(this)); 359 CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE); 360 CHECK(instance_size() == kVariableSizeSentinel || 361 (kPointerSize <= instance_size() && 362 instance_size() < heap->Capacity())); 363 VerifyHeapPointer(prototype()); 364 VerifyHeapPointer(instance_descriptors()); 365 SLOW_ASSERT(instance_descriptors()->IsSortedNoDuplicates()); 366 if (HasTransitionArray()) { 367 SLOW_ASSERT(transitions()->IsSortedNoDuplicates()); 368 SLOW_ASSERT(transitions()->IsConsistentWithBackPointers(this)); 369 } 370} 371 372 373void Map::SharedMapVerify() { 374 MapVerify(); 375 CHECK(is_shared()); 376 CHECK(instance_descriptors()->IsEmpty()); 377 CHECK_EQ(0, pre_allocated_property_fields()); 378 CHECK_EQ(0, unused_property_fields()); 379 CHECK_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()), 380 visitor_id()); 381} 382 383 384void Map::VerifyOmittedMapChecks() { 385 if (!FLAG_omit_map_checks_for_leaf_maps) return; 386 if (!is_stable() || 387 is_deprecated() || 388 HasTransitionArray() || 389 is_dictionary_map()) { 390 CHECK_EQ(0, dependent_code()->number_of_entries( 391 DependentCode::kPrototypeCheckGroup)); 392 } 393} 394 395 396void CodeCache::CodeCacheVerify() { 397 VerifyHeapPointer(default_cache()); 398 VerifyHeapPointer(normal_type_cache()); 399 CHECK(default_cache()->IsFixedArray()); 400 CHECK(normal_type_cache()->IsUndefined() 401 || normal_type_cache()->IsCodeCacheHashTable()); 402} 403 404 405void PolymorphicCodeCache::PolymorphicCodeCacheVerify() { 406 VerifyHeapPointer(cache()); 407 CHECK(cache()->IsUndefined() || cache()->IsPolymorphicCodeCacheHashTable()); 408} 409 410 411void TypeFeedbackInfo::TypeFeedbackInfoVerify() { 412 VerifyObjectField(kStorage1Offset); 413 VerifyObjectField(kStorage2Offset); 414 VerifyHeapPointer(type_feedback_cells()); 415} 416 417 418void AliasedArgumentsEntry::AliasedArgumentsEntryVerify() { 419 VerifySmiField(kAliasedContextSlot); 420} 421 422 423void FixedArray::FixedArrayVerify() { 424 for (int i = 0; i < length(); i++) { 425 Object* e = get(i); 426 if (e->IsHeapObject()) { 427 VerifyHeapPointer(e); 428 } else { 429 e->Verify(); 430 } 431 } 432} 433 434 435void FixedDoubleArray::FixedDoubleArrayVerify() { 436 for (int i = 0; i < length(); i++) { 437 if (!is_the_hole(i)) { 438 double value = get_scalar(i); 439 CHECK(!std::isnan(value) || 440 (BitCast<uint64_t>(value) == 441 BitCast<uint64_t>(canonical_not_the_hole_nan_as_double())) || 442 ((BitCast<uint64_t>(value) & Double::kSignMask) != 0)); 443 } 444 } 445} 446 447 448void ConstantPoolArray::ConstantPoolArrayVerify() { 449 CHECK(IsConstantPoolArray()); 450} 451 452 453void JSGeneratorObject::JSGeneratorObjectVerify() { 454 // In an expression like "new g()", there can be a point where a generator 455 // object is allocated but its fields are all undefined, as it hasn't yet been 456 // initialized by the generator. Hence these weak checks. 457 VerifyObjectField(kFunctionOffset); 458 VerifyObjectField(kContextOffset); 459 VerifyObjectField(kReceiverOffset); 460 VerifyObjectField(kOperandStackOffset); 461 VerifyObjectField(kContinuationOffset); 462 VerifyObjectField(kStackHandlerIndexOffset); 463} 464 465 466void JSModule::JSModuleVerify() { 467 VerifyObjectField(kContextOffset); 468 VerifyObjectField(kScopeInfoOffset); 469 CHECK(context()->IsUndefined() || 470 Context::cast(context())->IsModuleContext()); 471} 472 473 474void JSValue::JSValueVerify() { 475 Object* v = value(); 476 if (v->IsHeapObject()) { 477 VerifyHeapPointer(v); 478 } 479} 480 481 482void JSDate::JSDateVerify() { 483 if (value()->IsHeapObject()) { 484 VerifyHeapPointer(value()); 485 } 486 CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber()); 487 CHECK(year()->IsUndefined() || year()->IsSmi() || year()->IsNaN()); 488 CHECK(month()->IsUndefined() || month()->IsSmi() || month()->IsNaN()); 489 CHECK(day()->IsUndefined() || day()->IsSmi() || day()->IsNaN()); 490 CHECK(weekday()->IsUndefined() || weekday()->IsSmi() || weekday()->IsNaN()); 491 CHECK(hour()->IsUndefined() || hour()->IsSmi() || hour()->IsNaN()); 492 CHECK(min()->IsUndefined() || min()->IsSmi() || min()->IsNaN()); 493 CHECK(sec()->IsUndefined() || sec()->IsSmi() || sec()->IsNaN()); 494 CHECK(cache_stamp()->IsUndefined() || 495 cache_stamp()->IsSmi() || 496 cache_stamp()->IsNaN()); 497 498 if (month()->IsSmi()) { 499 int month = Smi::cast(this->month())->value(); 500 CHECK(0 <= month && month <= 11); 501 } 502 if (day()->IsSmi()) { 503 int day = Smi::cast(this->day())->value(); 504 CHECK(1 <= day && day <= 31); 505 } 506 if (hour()->IsSmi()) { 507 int hour = Smi::cast(this->hour())->value(); 508 CHECK(0 <= hour && hour <= 23); 509 } 510 if (min()->IsSmi()) { 511 int min = Smi::cast(this->min())->value(); 512 CHECK(0 <= min && min <= 59); 513 } 514 if (sec()->IsSmi()) { 515 int sec = Smi::cast(this->sec())->value(); 516 CHECK(0 <= sec && sec <= 59); 517 } 518 if (weekday()->IsSmi()) { 519 int weekday = Smi::cast(this->weekday())->value(); 520 CHECK(0 <= weekday && weekday <= 6); 521 } 522 if (cache_stamp()->IsSmi()) { 523 CHECK(Smi::cast(cache_stamp())->value() <= 524 Smi::cast(GetIsolate()->date_cache()->stamp())->value()); 525 } 526} 527 528 529void JSMessageObject::JSMessageObjectVerify() { 530 CHECK(IsJSMessageObject()); 531 CHECK(type()->IsString()); 532 CHECK(arguments()->IsJSArray()); 533 VerifyObjectField(kStartPositionOffset); 534 VerifyObjectField(kEndPositionOffset); 535 VerifyObjectField(kArgumentsOffset); 536 VerifyObjectField(kScriptOffset); 537 VerifyObjectField(kStackTraceOffset); 538 VerifyObjectField(kStackFramesOffset); 539} 540 541 542void String::StringVerify() { 543 CHECK(IsString()); 544 CHECK(length() >= 0 && length() <= Smi::kMaxValue); 545 if (IsInternalizedString()) { 546 CHECK(!GetHeap()->InNewSpace(this)); 547 } 548 if (IsConsString()) { 549 ConsString::cast(this)->ConsStringVerify(); 550 } else if (IsSlicedString()) { 551 SlicedString::cast(this)->SlicedStringVerify(); 552 } 553} 554 555 556void ConsString::ConsStringVerify() { 557 CHECK(this->first()->IsString()); 558 CHECK(this->second() == GetHeap()->empty_string() || 559 this->second()->IsString()); 560 CHECK(this->length() >= ConsString::kMinLength); 561 if (this->IsFlat()) { 562 // A flat cons can only be created by String::SlowTryFlatten. 563 // Afterwards, the first part may be externalized. 564 CHECK(this->first()->IsSeqString() || this->first()->IsExternalString()); 565 } 566} 567 568 569void SlicedString::SlicedStringVerify() { 570 CHECK(!this->parent()->IsConsString()); 571 CHECK(!this->parent()->IsSlicedString()); 572 CHECK(this->length() >= SlicedString::kMinLength); 573} 574 575 576void JSFunction::JSFunctionVerify() { 577 CHECK(IsJSFunction()); 578 VerifyObjectField(kPrototypeOrInitialMapOffset); 579 VerifyObjectField(kNextFunctionLinkOffset); 580 CHECK(code()->IsCode()); 581 CHECK(next_function_link() == NULL || 582 next_function_link()->IsUndefined() || 583 next_function_link()->IsJSFunction()); 584} 585 586 587void SharedFunctionInfo::SharedFunctionInfoVerify() { 588 CHECK(IsSharedFunctionInfo()); 589 VerifyObjectField(kNameOffset); 590 VerifyObjectField(kCodeOffset); 591 VerifyObjectField(kOptimizedCodeMapOffset); 592 VerifyObjectField(kScopeInfoOffset); 593 VerifyObjectField(kInstanceClassNameOffset); 594 VerifyObjectField(kFunctionDataOffset); 595 VerifyObjectField(kScriptOffset); 596 VerifyObjectField(kDebugInfoOffset); 597} 598 599 600void JSGlobalProxy::JSGlobalProxyVerify() { 601 CHECK(IsJSGlobalProxy()); 602 JSObjectVerify(); 603 VerifyObjectField(JSGlobalProxy::kNativeContextOffset); 604 // Make sure that this object has no properties, elements. 605 CHECK_EQ(0, properties()->length()); 606 CHECK(HasFastObjectElements()); 607 CHECK_EQ(0, FixedArray::cast(elements())->length()); 608} 609 610 611void JSGlobalObject::JSGlobalObjectVerify() { 612 CHECK(IsJSGlobalObject()); 613 JSObjectVerify(); 614 for (int i = GlobalObject::kBuiltinsOffset; 615 i < JSGlobalObject::kSize; 616 i += kPointerSize) { 617 VerifyObjectField(i); 618 } 619} 620 621 622void JSBuiltinsObject::JSBuiltinsObjectVerify() { 623 CHECK(IsJSBuiltinsObject()); 624 JSObjectVerify(); 625 for (int i = GlobalObject::kBuiltinsOffset; 626 i < JSBuiltinsObject::kSize; 627 i += kPointerSize) { 628 VerifyObjectField(i); 629 } 630} 631 632 633void Oddball::OddballVerify() { 634 CHECK(IsOddball()); 635 VerifyHeapPointer(to_string()); 636 Object* number = to_number(); 637 if (number->IsHeapObject()) { 638 CHECK(number == HeapObject::cast(number)->GetHeap()->nan_value()); 639 } else { 640 CHECK(number->IsSmi()); 641 int value = Smi::cast(number)->value(); 642 // Hidden oddballs have negative smis. 643 const int kLeastHiddenOddballNumber = -4; 644 CHECK_LE(value, 1); 645 CHECK(value >= kLeastHiddenOddballNumber); 646 } 647} 648 649 650void Cell::CellVerify() { 651 CHECK(IsCell()); 652 VerifyObjectField(kValueOffset); 653} 654 655 656void PropertyCell::PropertyCellVerify() { 657 CHECK(IsPropertyCell()); 658 VerifyObjectField(kValueOffset); 659 VerifyObjectField(kTypeOffset); 660} 661 662 663void Code::CodeVerify() { 664 CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()), 665 kCodeAlignment)); 666 relocation_info()->Verify(); 667 Address last_gc_pc = NULL; 668 for (RelocIterator it(this); !it.done(); it.next()) { 669 it.rinfo()->Verify(); 670 // Ensure that GC will not iterate twice over the same pointer. 671 if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) { 672 CHECK(it.rinfo()->pc() != last_gc_pc); 673 last_gc_pc = it.rinfo()->pc(); 674 } 675 } 676} 677 678 679void Code::VerifyEmbeddedObjectsDependency() { 680 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); 681 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { 682 Object* obj = it.rinfo()->target_object(); 683 if (IsWeakEmbeddedObject(kind(), obj)) { 684 if (obj->IsMap()) { 685 Map* map = Map::cast(obj); 686 CHECK(map->dependent_code()->Contains( 687 DependentCode::kWeaklyEmbeddedGroup, this)); 688 } else if (obj->IsJSObject()) { 689 Object* raw_table = GetIsolate()->heap()->weak_object_to_code_table(); 690 WeakHashTable* table = WeakHashTable::cast(raw_table); 691 CHECK(DependentCode::cast(table->Lookup(obj))->Contains( 692 DependentCode::kWeaklyEmbeddedGroup, this)); 693 } 694 } 695 } 696} 697 698 699void JSArray::JSArrayVerify() { 700 JSObjectVerify(); 701 CHECK(length()->IsNumber() || length()->IsUndefined()); 702 // If a GC was caused while constructing this array, the elements 703 // pointer may point to a one pointer filler map. 704 if (ElementsAreSafeToExamine()) { 705 CHECK(elements()->IsUndefined() || 706 elements()->IsFixedArray() || 707 elements()->IsFixedDoubleArray()); 708 } 709} 710 711 712void JSSet::JSSetVerify() { 713 CHECK(IsJSSet()); 714 JSObjectVerify(); 715 VerifyHeapPointer(table()); 716 CHECK(table()->IsHashTable() || table()->IsUndefined()); 717} 718 719 720void JSMap::JSMapVerify() { 721 CHECK(IsJSMap()); 722 JSObjectVerify(); 723 VerifyHeapPointer(table()); 724 CHECK(table()->IsHashTable() || table()->IsUndefined()); 725} 726 727 728void JSWeakMap::JSWeakMapVerify() { 729 CHECK(IsJSWeakMap()); 730 JSObjectVerify(); 731 VerifyHeapPointer(table()); 732 CHECK(table()->IsHashTable() || table()->IsUndefined()); 733} 734 735 736void JSWeakSet::JSWeakSetVerify() { 737 CHECK(IsJSWeakSet()); 738 JSObjectVerify(); 739 VerifyHeapPointer(table()); 740 CHECK(table()->IsHashTable() || table()->IsUndefined()); 741} 742 743 744void JSRegExp::JSRegExpVerify() { 745 JSObjectVerify(); 746 CHECK(data()->IsUndefined() || data()->IsFixedArray()); 747 switch (TypeTag()) { 748 case JSRegExp::ATOM: { 749 FixedArray* arr = FixedArray::cast(data()); 750 CHECK(arr->get(JSRegExp::kAtomPatternIndex)->IsString()); 751 break; 752 } 753 case JSRegExp::IRREGEXP: { 754 bool is_native = RegExpImpl::UsesNativeRegExp(); 755 756 FixedArray* arr = FixedArray::cast(data()); 757 Object* ascii_data = arr->get(JSRegExp::kIrregexpASCIICodeIndex); 758 // Smi : Not compiled yet (-1) or code prepared for flushing. 759 // JSObject: Compilation error. 760 // Code/ByteArray: Compiled code. 761 CHECK(ascii_data->IsSmi() || 762 (is_native ? ascii_data->IsCode() : ascii_data->IsByteArray())); 763 Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex); 764 CHECK(uc16_data->IsSmi() || 765 (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray())); 766 767 Object* ascii_saved = arr->get(JSRegExp::kIrregexpASCIICodeSavedIndex); 768 CHECK(ascii_saved->IsSmi() || ascii_saved->IsString() || 769 ascii_saved->IsCode()); 770 Object* uc16_saved = arr->get(JSRegExp::kIrregexpUC16CodeSavedIndex); 771 CHECK(uc16_saved->IsSmi() || uc16_saved->IsString() || 772 uc16_saved->IsCode()); 773 774 CHECK(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi()); 775 CHECK(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi()); 776 break; 777 } 778 default: 779 CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag()); 780 CHECK(data()->IsUndefined()); 781 break; 782 } 783} 784 785 786void JSProxy::JSProxyVerify() { 787 CHECK(IsJSProxy()); 788 VerifyPointer(handler()); 789 CHECK(hash()->IsSmi() || hash()->IsUndefined()); 790} 791 792 793void JSFunctionProxy::JSFunctionProxyVerify() { 794 CHECK(IsJSFunctionProxy()); 795 JSProxyVerify(); 796 VerifyPointer(call_trap()); 797 VerifyPointer(construct_trap()); 798} 799 800 801void JSArrayBuffer::JSArrayBufferVerify() { 802 CHECK(IsJSArrayBuffer()); 803 JSObjectVerify(); 804 VerifyPointer(byte_length()); 805 CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber() 806 || byte_length()->IsUndefined()); 807} 808 809 810void JSArrayBufferView::JSArrayBufferViewVerify() { 811 CHECK(IsJSArrayBufferView()); 812 JSObjectVerify(); 813 VerifyPointer(buffer()); 814 CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined()); 815 816 VerifyPointer(byte_offset()); 817 CHECK(byte_offset()->IsSmi() || byte_offset()->IsHeapNumber() 818 || byte_offset()->IsUndefined()); 819 820 VerifyPointer(byte_length()); 821 CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber() 822 || byte_length()->IsUndefined()); 823} 824 825 826void JSTypedArray::JSTypedArrayVerify() { 827 CHECK(IsJSTypedArray()); 828 JSArrayBufferViewVerify(); 829 VerifyPointer(length()); 830 CHECK(length()->IsSmi() || length()->IsHeapNumber() 831 || length()->IsUndefined()); 832 833 VerifyPointer(elements()); 834} 835 836 837void JSDataView::JSDataViewVerify() { 838 CHECK(IsJSDataView()); 839 JSArrayBufferViewVerify(); 840} 841 842 843void Foreign::ForeignVerify() { 844 CHECK(IsForeign()); 845} 846 847 848void Box::BoxVerify() { 849 CHECK(IsBox()); 850 value()->Verify(); 851} 852 853 854void AccessorInfo::AccessorInfoVerify() { 855 VerifyPointer(name()); 856 VerifyPointer(flag()); 857 VerifyPointer(expected_receiver_type()); 858} 859 860 861void ExecutableAccessorInfo::ExecutableAccessorInfoVerify() { 862 CHECK(IsExecutableAccessorInfo()); 863 AccessorInfoVerify(); 864 VerifyPointer(getter()); 865 VerifyPointer(setter()); 866 VerifyPointer(data()); 867} 868 869 870void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorVerify() { 871 CHECK(IsDeclaredAccessorDescriptor()); 872 VerifyPointer(serialized_data()); 873} 874 875 876void DeclaredAccessorInfo::DeclaredAccessorInfoVerify() { 877 CHECK(IsDeclaredAccessorInfo()); 878 AccessorInfoVerify(); 879 VerifyPointer(descriptor()); 880} 881 882 883void AccessorPair::AccessorPairVerify() { 884 CHECK(IsAccessorPair()); 885 VerifyPointer(getter()); 886 VerifyPointer(setter()); 887 VerifySmiField(kAccessFlagsOffset); 888} 889 890 891void AccessCheckInfo::AccessCheckInfoVerify() { 892 CHECK(IsAccessCheckInfo()); 893 VerifyPointer(named_callback()); 894 VerifyPointer(indexed_callback()); 895 VerifyPointer(data()); 896} 897 898 899void InterceptorInfo::InterceptorInfoVerify() { 900 CHECK(IsInterceptorInfo()); 901 VerifyPointer(getter()); 902 VerifyPointer(setter()); 903 VerifyPointer(query()); 904 VerifyPointer(deleter()); 905 VerifyPointer(enumerator()); 906 VerifyPointer(data()); 907} 908 909 910void CallHandlerInfo::CallHandlerInfoVerify() { 911 CHECK(IsCallHandlerInfo()); 912 VerifyPointer(callback()); 913 VerifyPointer(data()); 914} 915 916 917void TemplateInfo::TemplateInfoVerify() { 918 VerifyPointer(tag()); 919 VerifyPointer(property_list()); 920 VerifyPointer(property_accessors()); 921} 922 923 924void FunctionTemplateInfo::FunctionTemplateInfoVerify() { 925 CHECK(IsFunctionTemplateInfo()); 926 TemplateInfoVerify(); 927 VerifyPointer(serial_number()); 928 VerifyPointer(call_code()); 929 VerifyPointer(prototype_template()); 930 VerifyPointer(parent_template()); 931 VerifyPointer(named_property_handler()); 932 VerifyPointer(indexed_property_handler()); 933 VerifyPointer(instance_template()); 934 VerifyPointer(signature()); 935 VerifyPointer(access_check_info()); 936} 937 938 939void ObjectTemplateInfo::ObjectTemplateInfoVerify() { 940 CHECK(IsObjectTemplateInfo()); 941 TemplateInfoVerify(); 942 VerifyPointer(constructor()); 943 VerifyPointer(internal_field_count()); 944} 945 946 947void SignatureInfo::SignatureInfoVerify() { 948 CHECK(IsSignatureInfo()); 949 VerifyPointer(receiver()); 950 VerifyPointer(args()); 951} 952 953 954void TypeSwitchInfo::TypeSwitchInfoVerify() { 955 CHECK(IsTypeSwitchInfo()); 956 VerifyPointer(types()); 957} 958 959 960void AllocationSite::AllocationSiteVerify() { 961 CHECK(IsAllocationSite()); 962} 963 964 965void AllocationMemento::AllocationMementoVerify() { 966 CHECK(IsAllocationMemento()); 967 VerifyHeapPointer(allocation_site()); 968 CHECK(!IsValid() || GetAllocationSite()->IsAllocationSite()); 969} 970 971 972void Script::ScriptVerify() { 973 CHECK(IsScript()); 974 VerifyPointer(source()); 975 VerifyPointer(name()); 976 line_offset()->SmiVerify(); 977 column_offset()->SmiVerify(); 978 VerifyPointer(data()); 979 VerifyPointer(wrapper()); 980 type()->SmiVerify(); 981 VerifyPointer(line_ends()); 982 VerifyPointer(id()); 983} 984 985 986void JSFunctionResultCache::JSFunctionResultCacheVerify() { 987 JSFunction::cast(get(kFactoryIndex))->Verify(); 988 989 int size = Smi::cast(get(kCacheSizeIndex))->value(); 990 CHECK(kEntriesIndex <= size); 991 CHECK(size <= length()); 992 CHECK_EQ(0, size % kEntrySize); 993 994 int finger = Smi::cast(get(kFingerIndex))->value(); 995 CHECK(kEntriesIndex <= finger); 996 CHECK((finger < size) || (finger == kEntriesIndex && finger == size)); 997 CHECK_EQ(0, finger % kEntrySize); 998 999 if (FLAG_enable_slow_asserts) { 1000 for (int i = kEntriesIndex; i < size; i++) { 1001 CHECK(!get(i)->IsTheHole()); 1002 get(i)->Verify(); 1003 } 1004 for (int i = size; i < length(); i++) { 1005 CHECK(get(i)->IsTheHole()); 1006 get(i)->Verify(); 1007 } 1008 } 1009} 1010 1011 1012void NormalizedMapCache::NormalizedMapCacheVerify() { 1013 FixedArray::cast(this)->Verify(); 1014 if (FLAG_enable_slow_asserts) { 1015 for (int i = 0; i < length(); i++) { 1016 Object* e = get(i); 1017 if (e->IsMap()) { 1018 Map::cast(e)->SharedMapVerify(); 1019 } else { 1020 CHECK(e->IsUndefined()); 1021 } 1022 } 1023 } 1024} 1025 1026 1027#ifdef ENABLE_DEBUGGER_SUPPORT 1028void DebugInfo::DebugInfoVerify() { 1029 CHECK(IsDebugInfo()); 1030 VerifyPointer(shared()); 1031 VerifyPointer(original_code()); 1032 VerifyPointer(code()); 1033 VerifyPointer(break_points()); 1034} 1035 1036 1037void BreakPointInfo::BreakPointInfoVerify() { 1038 CHECK(IsBreakPointInfo()); 1039 code_position()->SmiVerify(); 1040 source_position()->SmiVerify(); 1041 statement_position()->SmiVerify(); 1042 VerifyPointer(break_point_objects()); 1043} 1044#endif // ENABLE_DEBUGGER_SUPPORT 1045#endif // VERIFY_HEAP 1046 1047#ifdef DEBUG 1048 1049void JSObject::IncrementSpillStatistics(SpillInformation* info) { 1050 info->number_of_objects_++; 1051 // Named properties 1052 if (HasFastProperties()) { 1053 info->number_of_objects_with_fast_properties_++; 1054 info->number_of_fast_used_fields_ += map()->NextFreePropertyIndex(); 1055 info->number_of_fast_unused_fields_ += map()->unused_property_fields(); 1056 } else { 1057 NameDictionary* dict = property_dictionary(); 1058 info->number_of_slow_used_properties_ += dict->NumberOfElements(); 1059 info->number_of_slow_unused_properties_ += 1060 dict->Capacity() - dict->NumberOfElements(); 1061 } 1062 // Indexed properties 1063 switch (GetElementsKind()) { 1064 case FAST_HOLEY_SMI_ELEMENTS: 1065 case FAST_SMI_ELEMENTS: 1066 case FAST_HOLEY_DOUBLE_ELEMENTS: 1067 case FAST_DOUBLE_ELEMENTS: 1068 case FAST_HOLEY_ELEMENTS: 1069 case FAST_ELEMENTS: { 1070 info->number_of_objects_with_fast_elements_++; 1071 int holes = 0; 1072 FixedArray* e = FixedArray::cast(elements()); 1073 int len = e->length(); 1074 Heap* heap = GetHeap(); 1075 for (int i = 0; i < len; i++) { 1076 if (e->get(i) == heap->the_hole_value()) holes++; 1077 } 1078 info->number_of_fast_used_elements_ += len - holes; 1079 info->number_of_fast_unused_elements_ += holes; 1080 break; 1081 } 1082 case EXTERNAL_BYTE_ELEMENTS: 1083 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 1084 case EXTERNAL_SHORT_ELEMENTS: 1085 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 1086 case EXTERNAL_INT_ELEMENTS: 1087 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 1088 case EXTERNAL_FLOAT_ELEMENTS: 1089 case EXTERNAL_DOUBLE_ELEMENTS: 1090 case EXTERNAL_PIXEL_ELEMENTS: { 1091 info->number_of_objects_with_fast_elements_++; 1092 ExternalPixelArray* e = ExternalPixelArray::cast(elements()); 1093 info->number_of_fast_used_elements_ += e->length(); 1094 break; 1095 } 1096 case DICTIONARY_ELEMENTS: { 1097 SeededNumberDictionary* dict = element_dictionary(); 1098 info->number_of_slow_used_elements_ += dict->NumberOfElements(); 1099 info->number_of_slow_unused_elements_ += 1100 dict->Capacity() - dict->NumberOfElements(); 1101 break; 1102 } 1103 case NON_STRICT_ARGUMENTS_ELEMENTS: 1104 break; 1105 } 1106} 1107 1108 1109void JSObject::SpillInformation::Clear() { 1110 number_of_objects_ = 0; 1111 number_of_objects_with_fast_properties_ = 0; 1112 number_of_objects_with_fast_elements_ = 0; 1113 number_of_fast_used_fields_ = 0; 1114 number_of_fast_unused_fields_ = 0; 1115 number_of_slow_used_properties_ = 0; 1116 number_of_slow_unused_properties_ = 0; 1117 number_of_fast_used_elements_ = 0; 1118 number_of_fast_unused_elements_ = 0; 1119 number_of_slow_used_elements_ = 0; 1120 number_of_slow_unused_elements_ = 0; 1121} 1122 1123 1124void JSObject::SpillInformation::Print() { 1125 PrintF("\n JSObject Spill Statistics (#%d):\n", number_of_objects_); 1126 1127 PrintF(" - fast properties (#%d): %d (used) %d (unused)\n", 1128 number_of_objects_with_fast_properties_, 1129 number_of_fast_used_fields_, number_of_fast_unused_fields_); 1130 1131 PrintF(" - slow properties (#%d): %d (used) %d (unused)\n", 1132 number_of_objects_ - number_of_objects_with_fast_properties_, 1133 number_of_slow_used_properties_, number_of_slow_unused_properties_); 1134 1135 PrintF(" - fast elements (#%d): %d (used) %d (unused)\n", 1136 number_of_objects_with_fast_elements_, 1137 number_of_fast_used_elements_, number_of_fast_unused_elements_); 1138 1139 PrintF(" - slow elements (#%d): %d (used) %d (unused)\n", 1140 number_of_objects_ - number_of_objects_with_fast_elements_, 1141 number_of_slow_used_elements_, number_of_slow_unused_elements_); 1142 1143 PrintF("\n"); 1144} 1145 1146 1147bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) { 1148 if (valid_entries == -1) valid_entries = number_of_descriptors(); 1149 Name* current_key = NULL; 1150 uint32_t current = 0; 1151 for (int i = 0; i < number_of_descriptors(); i++) { 1152 Name* key = GetSortedKey(i); 1153 if (key == current_key) { 1154 PrintDescriptors(); 1155 return false; 1156 } 1157 current_key = key; 1158 uint32_t hash = GetSortedKey(i)->Hash(); 1159 if (hash < current) { 1160 PrintDescriptors(); 1161 return false; 1162 } 1163 current = hash; 1164 } 1165 return true; 1166} 1167 1168 1169bool TransitionArray::IsSortedNoDuplicates(int valid_entries) { 1170 ASSERT(valid_entries == -1); 1171 Name* current_key = NULL; 1172 uint32_t current = 0; 1173 for (int i = 0; i < number_of_transitions(); i++) { 1174 Name* key = GetSortedKey(i); 1175 if (key == current_key) { 1176 PrintTransitions(); 1177 return false; 1178 } 1179 current_key = key; 1180 uint32_t hash = GetSortedKey(i)->Hash(); 1181 if (hash < current) { 1182 PrintTransitions(); 1183 return false; 1184 } 1185 current = hash; 1186 } 1187 return true; 1188} 1189 1190 1191static bool CheckOneBackPointer(Map* current_map, Object* target) { 1192 return !target->IsMap() || Map::cast(target)->GetBackPointer() == current_map; 1193} 1194 1195 1196bool TransitionArray::IsConsistentWithBackPointers(Map* current_map) { 1197 for (int i = 0; i < number_of_transitions(); ++i) { 1198 if (!CheckOneBackPointer(current_map, GetTarget(i))) return false; 1199 } 1200 return true; 1201} 1202 1203 1204#endif // DEBUG 1205 1206} } // namespace v8::internal 1207