1 // Copyright 2010 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 "objects-visiting.h" 34 35 namespace v8 { 36 namespace internal { 37 38 #ifdef DEBUG 39 40 void MaybeObject::Verify() { 41 Object* this_as_object; 42 if (ToObject(&this_as_object)) { 43 if (this_as_object->IsSmi()) { 44 Smi::cast(this_as_object)->SmiVerify(); 45 } else { 46 HeapObject::cast(this_as_object)->HeapObjectVerify(); 47 } 48 } else { 49 Failure::cast(this)->FailureVerify(); 50 } 51 } 52 53 54 void Object::VerifyPointer(Object* p) { 55 if (p->IsHeapObject()) { 56 HeapObject::VerifyHeapPointer(p); 57 } else { 58 ASSERT(p->IsSmi()); 59 } 60 } 61 62 63 void Smi::SmiVerify() { 64 ASSERT(IsSmi()); 65 } 66 67 68 void Failure::FailureVerify() { 69 ASSERT(IsFailure()); 70 } 71 72 73 void HeapObject::HeapObjectVerify() { 74 InstanceType instance_type = map()->instance_type(); 75 76 if (instance_type < FIRST_NONSTRING_TYPE) { 77 String::cast(this)->StringVerify(); 78 return; 79 } 80 81 switch (instance_type) { 82 case MAP_TYPE: 83 Map::cast(this)->MapVerify(); 84 break; 85 case HEAP_NUMBER_TYPE: 86 HeapNumber::cast(this)->HeapNumberVerify(); 87 break; 88 case FIXED_ARRAY_TYPE: 89 FixedArray::cast(this)->FixedArrayVerify(); 90 break; 91 case BYTE_ARRAY_TYPE: 92 ByteArray::cast(this)->ByteArrayVerify(); 93 break; 94 case EXTERNAL_PIXEL_ARRAY_TYPE: 95 ExternalPixelArray::cast(this)->ExternalPixelArrayVerify(); 96 break; 97 case EXTERNAL_BYTE_ARRAY_TYPE: 98 ExternalByteArray::cast(this)->ExternalByteArrayVerify(); 99 break; 100 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 101 ExternalUnsignedByteArray::cast(this)->ExternalUnsignedByteArrayVerify(); 102 break; 103 case EXTERNAL_SHORT_ARRAY_TYPE: 104 ExternalShortArray::cast(this)->ExternalShortArrayVerify(); 105 break; 106 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: 107 ExternalUnsignedShortArray::cast(this)-> 108 ExternalUnsignedShortArrayVerify(); 109 break; 110 case EXTERNAL_INT_ARRAY_TYPE: 111 ExternalIntArray::cast(this)->ExternalIntArrayVerify(); 112 break; 113 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: 114 ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayVerify(); 115 break; 116 case EXTERNAL_FLOAT_ARRAY_TYPE: 117 ExternalFloatArray::cast(this)->ExternalFloatArrayVerify(); 118 break; 119 case CODE_TYPE: 120 Code::cast(this)->CodeVerify(); 121 break; 122 case ODDBALL_TYPE: 123 Oddball::cast(this)->OddballVerify(); 124 break; 125 case JS_OBJECT_TYPE: 126 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 127 JSObject::cast(this)->JSObjectVerify(); 128 break; 129 case JS_VALUE_TYPE: 130 JSValue::cast(this)->JSValueVerify(); 131 break; 132 case JS_FUNCTION_TYPE: 133 JSFunction::cast(this)->JSFunctionVerify(); 134 break; 135 case JS_GLOBAL_PROXY_TYPE: 136 JSGlobalProxy::cast(this)->JSGlobalProxyVerify(); 137 break; 138 case JS_GLOBAL_OBJECT_TYPE: 139 JSGlobalObject::cast(this)->JSGlobalObjectVerify(); 140 break; 141 case JS_BUILTINS_OBJECT_TYPE: 142 JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify(); 143 break; 144 case JS_GLOBAL_PROPERTY_CELL_TYPE: 145 JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellVerify(); 146 break; 147 case JS_ARRAY_TYPE: 148 JSArray::cast(this)->JSArrayVerify(); 149 break; 150 case JS_REGEXP_TYPE: 151 JSRegExp::cast(this)->JSRegExpVerify(); 152 break; 153 case FILLER_TYPE: 154 break; 155 case PROXY_TYPE: 156 Proxy::cast(this)->ProxyVerify(); 157 break; 158 case SHARED_FUNCTION_INFO_TYPE: 159 SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify(); 160 break; 161 case JS_MESSAGE_OBJECT_TYPE: 162 JSMessageObject::cast(this)->JSMessageObjectVerify(); 163 break; 164 165 #define MAKE_STRUCT_CASE(NAME, Name, name) \ 166 case NAME##_TYPE: \ 167 Name::cast(this)->Name##Verify(); \ 168 break; 169 STRUCT_LIST(MAKE_STRUCT_CASE) 170 #undef MAKE_STRUCT_CASE 171 172 default: 173 UNREACHABLE(); 174 break; 175 } 176 } 177 178 179 void HeapObject::VerifyHeapPointer(Object* p) { 180 ASSERT(p->IsHeapObject()); 181 ASSERT(HEAP->Contains(HeapObject::cast(p))); 182 } 183 184 185 void HeapNumber::HeapNumberVerify() { 186 ASSERT(IsHeapNumber()); 187 } 188 189 190 void ByteArray::ByteArrayVerify() { 191 ASSERT(IsByteArray()); 192 } 193 194 195 void ExternalPixelArray::ExternalPixelArrayVerify() { 196 ASSERT(IsExternalPixelArray()); 197 } 198 199 200 void ExternalByteArray::ExternalByteArrayVerify() { 201 ASSERT(IsExternalByteArray()); 202 } 203 204 205 void ExternalUnsignedByteArray::ExternalUnsignedByteArrayVerify() { 206 ASSERT(IsExternalUnsignedByteArray()); 207 } 208 209 210 void ExternalShortArray::ExternalShortArrayVerify() { 211 ASSERT(IsExternalShortArray()); 212 } 213 214 215 void ExternalUnsignedShortArray::ExternalUnsignedShortArrayVerify() { 216 ASSERT(IsExternalUnsignedShortArray()); 217 } 218 219 220 void ExternalIntArray::ExternalIntArrayVerify() { 221 ASSERT(IsExternalIntArray()); 222 } 223 224 225 void ExternalUnsignedIntArray::ExternalUnsignedIntArrayVerify() { 226 ASSERT(IsExternalUnsignedIntArray()); 227 } 228 229 230 void ExternalFloatArray::ExternalFloatArrayVerify() { 231 ASSERT(IsExternalFloatArray()); 232 } 233 234 235 void JSObject::JSObjectVerify() { 236 VerifyHeapPointer(properties()); 237 VerifyHeapPointer(elements()); 238 if (HasFastProperties()) { 239 CHECK_EQ(map()->unused_property_fields(), 240 (map()->inobject_properties() + properties()->length() - 241 map()->NextFreePropertyIndex())); 242 } 243 ASSERT(map()->has_fast_elements() == 244 (elements()->map() == GetHeap()->fixed_array_map() || 245 elements()->map() == GetHeap()->fixed_cow_array_map())); 246 ASSERT(map()->has_fast_elements() == HasFastElements()); 247 } 248 249 250 void Map::MapVerify() { 251 ASSERT(!HEAP->InNewSpace(this)); 252 ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE); 253 ASSERT(instance_size() == kVariableSizeSentinel || 254 (kPointerSize <= instance_size() && 255 instance_size() < HEAP->Capacity())); 256 VerifyHeapPointer(prototype()); 257 VerifyHeapPointer(instance_descriptors()); 258 } 259 260 261 void Map::SharedMapVerify() { 262 MapVerify(); 263 ASSERT(is_shared()); 264 ASSERT_EQ(GetHeap()->empty_descriptor_array(), instance_descriptors()); 265 ASSERT_EQ(0, pre_allocated_property_fields()); 266 ASSERT_EQ(0, unused_property_fields()); 267 ASSERT_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()), 268 visitor_id()); 269 } 270 271 272 void CodeCache::CodeCacheVerify() { 273 VerifyHeapPointer(default_cache()); 274 VerifyHeapPointer(normal_type_cache()); 275 ASSERT(default_cache()->IsFixedArray()); 276 ASSERT(normal_type_cache()->IsUndefined() 277 || normal_type_cache()->IsCodeCacheHashTable()); 278 } 279 280 281 void FixedArray::FixedArrayVerify() { 282 for (int i = 0; i < length(); i++) { 283 Object* e = get(i); 284 if (e->IsHeapObject()) { 285 VerifyHeapPointer(e); 286 } else { 287 e->Verify(); 288 } 289 } 290 } 291 292 293 void JSValue::JSValueVerify() { 294 Object* v = value(); 295 if (v->IsHeapObject()) { 296 VerifyHeapPointer(v); 297 } 298 } 299 300 301 void JSMessageObject::JSMessageObjectVerify() { 302 CHECK(IsJSMessageObject()); 303 CHECK(type()->IsString()); 304 CHECK(arguments()->IsJSArray()); 305 VerifyObjectField(kStartPositionOffset); 306 VerifyObjectField(kEndPositionOffset); 307 VerifyObjectField(kArgumentsOffset); 308 VerifyObjectField(kScriptOffset); 309 VerifyObjectField(kStackTraceOffset); 310 VerifyObjectField(kStackFramesOffset); 311 } 312 313 314 void String::StringVerify() { 315 CHECK(IsString()); 316 CHECK(length() >= 0 && length() <= Smi::kMaxValue); 317 if (IsSymbol()) { 318 CHECK(!HEAP->InNewSpace(this)); 319 } 320 } 321 322 323 void JSFunction::JSFunctionVerify() { 324 CHECK(IsJSFunction()); 325 VerifyObjectField(kPrototypeOrInitialMapOffset); 326 VerifyObjectField(kNextFunctionLinkOffset); 327 CHECK(next_function_link()->IsUndefined() || 328 next_function_link()->IsJSFunction()); 329 } 330 331 332 void SharedFunctionInfo::SharedFunctionInfoVerify() { 333 CHECK(IsSharedFunctionInfo()); 334 VerifyObjectField(kNameOffset); 335 VerifyObjectField(kCodeOffset); 336 VerifyObjectField(kScopeInfoOffset); 337 VerifyObjectField(kInstanceClassNameOffset); 338 VerifyObjectField(kFunctionDataOffset); 339 VerifyObjectField(kScriptOffset); 340 VerifyObjectField(kDebugInfoOffset); 341 } 342 343 344 void JSGlobalProxy::JSGlobalProxyVerify() { 345 CHECK(IsJSGlobalProxy()); 346 JSObjectVerify(); 347 VerifyObjectField(JSGlobalProxy::kContextOffset); 348 // Make sure that this object has no properties, elements. 349 CHECK_EQ(0, properties()->length()); 350 CHECK(HasFastElements()); 351 CHECK_EQ(0, FixedArray::cast(elements())->length()); 352 } 353 354 355 void JSGlobalObject::JSGlobalObjectVerify() { 356 CHECK(IsJSGlobalObject()); 357 JSObjectVerify(); 358 for (int i = GlobalObject::kBuiltinsOffset; 359 i < JSGlobalObject::kSize; 360 i += kPointerSize) { 361 VerifyObjectField(i); 362 } 363 } 364 365 366 void JSBuiltinsObject::JSBuiltinsObjectVerify() { 367 CHECK(IsJSBuiltinsObject()); 368 JSObjectVerify(); 369 for (int i = GlobalObject::kBuiltinsOffset; 370 i < JSBuiltinsObject::kSize; 371 i += kPointerSize) { 372 VerifyObjectField(i); 373 } 374 } 375 376 377 void Oddball::OddballVerify() { 378 CHECK(IsOddball()); 379 VerifyHeapPointer(to_string()); 380 Object* number = to_number(); 381 if (number->IsHeapObject()) { 382 ASSERT(number == HEAP->nan_value()); 383 } else { 384 ASSERT(number->IsSmi()); 385 int value = Smi::cast(number)->value(); 386 // Hidden oddballs have negative smis. 387 const int kLeastHiddenOddballNumber = -4; 388 ASSERT(value <= 1); 389 ASSERT(value >= kLeastHiddenOddballNumber); 390 } 391 } 392 393 394 void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() { 395 CHECK(IsJSGlobalPropertyCell()); 396 VerifyObjectField(kValueOffset); 397 } 398 399 400 void Code::CodeVerify() { 401 CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()), 402 kCodeAlignment)); 403 Address last_gc_pc = NULL; 404 for (RelocIterator it(this); !it.done(); it.next()) { 405 it.rinfo()->Verify(); 406 // Ensure that GC will not iterate twice over the same pointer. 407 if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) { 408 CHECK(it.rinfo()->pc() != last_gc_pc); 409 last_gc_pc = it.rinfo()->pc(); 410 } 411 } 412 } 413 414 415 void JSArray::JSArrayVerify() { 416 JSObjectVerify(); 417 ASSERT(length()->IsNumber() || length()->IsUndefined()); 418 ASSERT(elements()->IsUndefined() || elements()->IsFixedArray()); 419 } 420 421 422 void JSRegExp::JSRegExpVerify() { 423 JSObjectVerify(); 424 ASSERT(data()->IsUndefined() || data()->IsFixedArray()); 425 switch (TypeTag()) { 426 case JSRegExp::ATOM: { 427 FixedArray* arr = FixedArray::cast(data()); 428 ASSERT(arr->get(JSRegExp::kAtomPatternIndex)->IsString()); 429 break; 430 } 431 case JSRegExp::IRREGEXP: { 432 bool is_native = RegExpImpl::UsesNativeRegExp(); 433 434 FixedArray* arr = FixedArray::cast(data()); 435 Object* ascii_data = arr->get(JSRegExp::kIrregexpASCIICodeIndex); 436 // TheHole : Not compiled yet. 437 // JSObject: Compilation error. 438 // Code/ByteArray: Compiled code. 439 ASSERT(ascii_data->IsTheHole() || ascii_data->IsJSObject() || 440 (is_native ? ascii_data->IsCode() : ascii_data->IsByteArray())); 441 Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex); 442 ASSERT(uc16_data->IsTheHole() || uc16_data->IsJSObject() || 443 (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray())); 444 ASSERT(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi()); 445 ASSERT(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi()); 446 break; 447 } 448 default: 449 ASSERT_EQ(JSRegExp::NOT_COMPILED, TypeTag()); 450 ASSERT(data()->IsUndefined()); 451 break; 452 } 453 } 454 455 456 void Proxy::ProxyVerify() { 457 ASSERT(IsProxy()); 458 } 459 460 461 void AccessorInfo::AccessorInfoVerify() { 462 CHECK(IsAccessorInfo()); 463 VerifyPointer(getter()); 464 VerifyPointer(setter()); 465 VerifyPointer(name()); 466 VerifyPointer(data()); 467 VerifyPointer(flag()); 468 } 469 470 471 void AccessCheckInfo::AccessCheckInfoVerify() { 472 CHECK(IsAccessCheckInfo()); 473 VerifyPointer(named_callback()); 474 VerifyPointer(indexed_callback()); 475 VerifyPointer(data()); 476 } 477 478 479 void InterceptorInfo::InterceptorInfoVerify() { 480 CHECK(IsInterceptorInfo()); 481 VerifyPointer(getter()); 482 VerifyPointer(setter()); 483 VerifyPointer(query()); 484 VerifyPointer(deleter()); 485 VerifyPointer(enumerator()); 486 VerifyPointer(data()); 487 } 488 489 490 void CallHandlerInfo::CallHandlerInfoVerify() { 491 CHECK(IsCallHandlerInfo()); 492 VerifyPointer(callback()); 493 VerifyPointer(data()); 494 } 495 496 497 void TemplateInfo::TemplateInfoVerify() { 498 VerifyPointer(tag()); 499 VerifyPointer(property_list()); 500 } 501 502 void FunctionTemplateInfo::FunctionTemplateInfoVerify() { 503 CHECK(IsFunctionTemplateInfo()); 504 TemplateInfoVerify(); 505 VerifyPointer(serial_number()); 506 VerifyPointer(call_code()); 507 VerifyPointer(property_accessors()); 508 VerifyPointer(prototype_template()); 509 VerifyPointer(parent_template()); 510 VerifyPointer(named_property_handler()); 511 VerifyPointer(indexed_property_handler()); 512 VerifyPointer(instance_template()); 513 VerifyPointer(signature()); 514 VerifyPointer(access_check_info()); 515 } 516 517 518 void ObjectTemplateInfo::ObjectTemplateInfoVerify() { 519 CHECK(IsObjectTemplateInfo()); 520 TemplateInfoVerify(); 521 VerifyPointer(constructor()); 522 VerifyPointer(internal_field_count()); 523 } 524 525 526 void SignatureInfo::SignatureInfoVerify() { 527 CHECK(IsSignatureInfo()); 528 VerifyPointer(receiver()); 529 VerifyPointer(args()); 530 } 531 532 533 void TypeSwitchInfo::TypeSwitchInfoVerify() { 534 CHECK(IsTypeSwitchInfo()); 535 VerifyPointer(types()); 536 } 537 538 539 void Script::ScriptVerify() { 540 CHECK(IsScript()); 541 VerifyPointer(source()); 542 VerifyPointer(name()); 543 line_offset()->SmiVerify(); 544 column_offset()->SmiVerify(); 545 VerifyPointer(data()); 546 VerifyPointer(wrapper()); 547 type()->SmiVerify(); 548 VerifyPointer(line_ends()); 549 VerifyPointer(id()); 550 } 551 552 553 #ifdef ENABLE_DEBUGGER_SUPPORT 554 void DebugInfo::DebugInfoVerify() { 555 CHECK(IsDebugInfo()); 556 VerifyPointer(shared()); 557 VerifyPointer(original_code()); 558 VerifyPointer(code()); 559 VerifyPointer(break_points()); 560 } 561 562 563 void BreakPointInfo::BreakPointInfoVerify() { 564 CHECK(IsBreakPointInfo()); 565 code_position()->SmiVerify(); 566 source_position()->SmiVerify(); 567 statement_position()->SmiVerify(); 568 VerifyPointer(break_point_objects()); 569 } 570 #endif // ENABLE_DEBUGGER_SUPPORT 571 572 573 void JSObject::IncrementSpillStatistics(SpillInformation* info) { 574 info->number_of_objects_++; 575 // Named properties 576 if (HasFastProperties()) { 577 info->number_of_objects_with_fast_properties_++; 578 info->number_of_fast_used_fields_ += map()->NextFreePropertyIndex(); 579 info->number_of_fast_unused_fields_ += map()->unused_property_fields(); 580 } else { 581 StringDictionary* dict = property_dictionary(); 582 info->number_of_slow_used_properties_ += dict->NumberOfElements(); 583 info->number_of_slow_unused_properties_ += 584 dict->Capacity() - dict->NumberOfElements(); 585 } 586 // Indexed properties 587 switch (GetElementsKind()) { 588 case FAST_ELEMENTS: { 589 info->number_of_objects_with_fast_elements_++; 590 int holes = 0; 591 FixedArray* e = FixedArray::cast(elements()); 592 int len = e->length(); 593 Heap* heap = HEAP; 594 for (int i = 0; i < len; i++) { 595 if (e->get(i) == heap->the_hole_value()) holes++; 596 } 597 info->number_of_fast_used_elements_ += len - holes; 598 info->number_of_fast_unused_elements_ += holes; 599 break; 600 } 601 case EXTERNAL_PIXEL_ELEMENTS: { 602 info->number_of_objects_with_fast_elements_++; 603 ExternalPixelArray* e = ExternalPixelArray::cast(elements()); 604 info->number_of_fast_used_elements_ += e->length(); 605 break; 606 } 607 case DICTIONARY_ELEMENTS: { 608 NumberDictionary* dict = element_dictionary(); 609 info->number_of_slow_used_elements_ += dict->NumberOfElements(); 610 info->number_of_slow_unused_elements_ += 611 dict->Capacity() - dict->NumberOfElements(); 612 break; 613 } 614 default: 615 UNREACHABLE(); 616 break; 617 } 618 } 619 620 621 void JSObject::SpillInformation::Clear() { 622 number_of_objects_ = 0; 623 number_of_objects_with_fast_properties_ = 0; 624 number_of_objects_with_fast_elements_ = 0; 625 number_of_fast_used_fields_ = 0; 626 number_of_fast_unused_fields_ = 0; 627 number_of_slow_used_properties_ = 0; 628 number_of_slow_unused_properties_ = 0; 629 number_of_fast_used_elements_ = 0; 630 number_of_fast_unused_elements_ = 0; 631 number_of_slow_used_elements_ = 0; 632 number_of_slow_unused_elements_ = 0; 633 } 634 635 void JSObject::SpillInformation::Print() { 636 PrintF("\n JSObject Spill Statistics (#%d):\n", number_of_objects_); 637 638 PrintF(" - fast properties (#%d): %d (used) %d (unused)\n", 639 number_of_objects_with_fast_properties_, 640 number_of_fast_used_fields_, number_of_fast_unused_fields_); 641 642 PrintF(" - slow properties (#%d): %d (used) %d (unused)\n", 643 number_of_objects_ - number_of_objects_with_fast_properties_, 644 number_of_slow_used_properties_, number_of_slow_unused_properties_); 645 646 PrintF(" - fast elements (#%d): %d (used) %d (unused)\n", 647 number_of_objects_with_fast_elements_, 648 number_of_fast_used_elements_, number_of_fast_unused_elements_); 649 650 PrintF(" - slow elements (#%d): %d (used) %d (unused)\n", 651 number_of_objects_ - number_of_objects_with_fast_elements_, 652 number_of_slow_used_elements_, number_of_slow_unused_elements_); 653 654 PrintF("\n"); 655 } 656 657 658 bool DescriptorArray::IsSortedNoDuplicates() { 659 String* current_key = NULL; 660 uint32_t current = 0; 661 for (int i = 0; i < number_of_descriptors(); i++) { 662 String* key = GetKey(i); 663 if (key == current_key) { 664 PrintDescriptors(); 665 return false; 666 } 667 current_key = key; 668 uint32_t hash = GetKey(i)->Hash(); 669 if (hash < current) { 670 PrintDescriptors(); 671 return false; 672 } 673 current = hash; 674 } 675 return true; 676 } 677 678 679 void JSFunctionResultCache::JSFunctionResultCacheVerify() { 680 JSFunction::cast(get(kFactoryIndex))->Verify(); 681 682 int size = Smi::cast(get(kCacheSizeIndex))->value(); 683 ASSERT(kEntriesIndex <= size); 684 ASSERT(size <= length()); 685 ASSERT_EQ(0, size % kEntrySize); 686 687 int finger = Smi::cast(get(kFingerIndex))->value(); 688 ASSERT(kEntriesIndex <= finger); 689 ASSERT((finger < size) || (finger == kEntriesIndex && finger == size)); 690 ASSERT_EQ(0, finger % kEntrySize); 691 692 if (FLAG_enable_slow_asserts) { 693 for (int i = kEntriesIndex; i < size; i++) { 694 ASSERT(!get(i)->IsTheHole()); 695 get(i)->Verify(); 696 } 697 for (int i = size; i < length(); i++) { 698 ASSERT(get(i)->IsTheHole()); 699 get(i)->Verify(); 700 } 701 } 702 } 703 704 705 void NormalizedMapCache::NormalizedMapCacheVerify() { 706 FixedArray::cast(this)->Verify(); 707 if (FLAG_enable_slow_asserts) { 708 for (int i = 0; i < length(); i++) { 709 Object* e = get(i); 710 if (e->IsMap()) { 711 Map::cast(e)->SharedMapVerify(); 712 } else { 713 ASSERT(e->IsUndefined()); 714 } 715 } 716 } 717 } 718 719 720 #endif // DEBUG 721 722 } } // namespace v8::internal 723