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 "objects-visiting.h" 34 35namespace v8 { 36namespace internal { 37 38#ifdef DEBUG 39 40void 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 54void Object::VerifyPointer(Object* p) { 55 if (p->IsHeapObject()) { 56 HeapObject::VerifyHeapPointer(p); 57 } else { 58 ASSERT(p->IsSmi()); 59 } 60} 61 62 63void Smi::SmiVerify() { 64 ASSERT(IsSmi()); 65} 66 67 68void Failure::FailureVerify() { 69 ASSERT(IsFailure()); 70} 71 72 73void 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 FIXED_DOUBLE_ARRAY_TYPE: 92 FixedDoubleArray::cast(this)->FixedDoubleArrayVerify(); 93 break; 94 case BYTE_ARRAY_TYPE: 95 ByteArray::cast(this)->ByteArrayVerify(); 96 break; 97 case FREE_SPACE_TYPE: 98 FreeSpace::cast(this)->FreeSpaceVerify(); 99 break; 100 case EXTERNAL_PIXEL_ARRAY_TYPE: 101 ExternalPixelArray::cast(this)->ExternalPixelArrayVerify(); 102 break; 103 case EXTERNAL_BYTE_ARRAY_TYPE: 104 ExternalByteArray::cast(this)->ExternalByteArrayVerify(); 105 break; 106 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 107 ExternalUnsignedByteArray::cast(this)->ExternalUnsignedByteArrayVerify(); 108 break; 109 case EXTERNAL_SHORT_ARRAY_TYPE: 110 ExternalShortArray::cast(this)->ExternalShortArrayVerify(); 111 break; 112 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: 113 ExternalUnsignedShortArray::cast(this)-> 114 ExternalUnsignedShortArrayVerify(); 115 break; 116 case EXTERNAL_INT_ARRAY_TYPE: 117 ExternalIntArray::cast(this)->ExternalIntArrayVerify(); 118 break; 119 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: 120 ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayVerify(); 121 break; 122 case EXTERNAL_FLOAT_ARRAY_TYPE: 123 ExternalFloatArray::cast(this)->ExternalFloatArrayVerify(); 124 break; 125 case EXTERNAL_DOUBLE_ARRAY_TYPE: 126 ExternalDoubleArray::cast(this)->ExternalDoubleArrayVerify(); 127 break; 128 case CODE_TYPE: 129 Code::cast(this)->CodeVerify(); 130 break; 131 case ODDBALL_TYPE: 132 Oddball::cast(this)->OddballVerify(); 133 break; 134 case JS_OBJECT_TYPE: 135 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 136 JSObject::cast(this)->JSObjectVerify(); 137 break; 138 case JS_VALUE_TYPE: 139 JSValue::cast(this)->JSValueVerify(); 140 break; 141 case JS_DATE_TYPE: 142 JSDate::cast(this)->JSDateVerify(); 143 break; 144 case JS_FUNCTION_TYPE: 145 JSFunction::cast(this)->JSFunctionVerify(); 146 break; 147 case JS_GLOBAL_PROXY_TYPE: 148 JSGlobalProxy::cast(this)->JSGlobalProxyVerify(); 149 break; 150 case JS_GLOBAL_OBJECT_TYPE: 151 JSGlobalObject::cast(this)->JSGlobalObjectVerify(); 152 break; 153 case JS_BUILTINS_OBJECT_TYPE: 154 JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify(); 155 break; 156 case JS_GLOBAL_PROPERTY_CELL_TYPE: 157 JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellVerify(); 158 break; 159 case JS_ARRAY_TYPE: 160 JSArray::cast(this)->JSArrayVerify(); 161 break; 162 case JS_SET_TYPE: 163 JSSet::cast(this)->JSSetVerify(); 164 break; 165 case JS_MAP_TYPE: 166 JSMap::cast(this)->JSMapVerify(); 167 break; 168 case JS_WEAK_MAP_TYPE: 169 JSWeakMap::cast(this)->JSWeakMapVerify(); 170 break; 171 case JS_REGEXP_TYPE: 172 JSRegExp::cast(this)->JSRegExpVerify(); 173 break; 174 case FILLER_TYPE: 175 break; 176 case JS_PROXY_TYPE: 177 JSProxy::cast(this)->JSProxyVerify(); 178 break; 179 case JS_FUNCTION_PROXY_TYPE: 180 JSFunctionProxy::cast(this)->JSFunctionProxyVerify(); 181 break; 182 case FOREIGN_TYPE: 183 Foreign::cast(this)->ForeignVerify(); 184 break; 185 case SHARED_FUNCTION_INFO_TYPE: 186 SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify(); 187 break; 188 case JS_MESSAGE_OBJECT_TYPE: 189 JSMessageObject::cast(this)->JSMessageObjectVerify(); 190 break; 191 192#define MAKE_STRUCT_CASE(NAME, Name, name) \ 193 case NAME##_TYPE: \ 194 Name::cast(this)->Name##Verify(); \ 195 break; 196 STRUCT_LIST(MAKE_STRUCT_CASE) 197#undef MAKE_STRUCT_CASE 198 199 default: 200 UNREACHABLE(); 201 break; 202 } 203} 204 205 206void HeapObject::VerifyHeapPointer(Object* p) { 207 ASSERT(p->IsHeapObject()); 208 ASSERT(HEAP->Contains(HeapObject::cast(p))); 209} 210 211 212void HeapNumber::HeapNumberVerify() { 213 ASSERT(IsHeapNumber()); 214} 215 216 217void ByteArray::ByteArrayVerify() { 218 ASSERT(IsByteArray()); 219} 220 221 222void FreeSpace::FreeSpaceVerify() { 223 ASSERT(IsFreeSpace()); 224} 225 226 227void ExternalPixelArray::ExternalPixelArrayVerify() { 228 ASSERT(IsExternalPixelArray()); 229} 230 231 232void ExternalByteArray::ExternalByteArrayVerify() { 233 ASSERT(IsExternalByteArray()); 234} 235 236 237void ExternalUnsignedByteArray::ExternalUnsignedByteArrayVerify() { 238 ASSERT(IsExternalUnsignedByteArray()); 239} 240 241 242void ExternalShortArray::ExternalShortArrayVerify() { 243 ASSERT(IsExternalShortArray()); 244} 245 246 247void ExternalUnsignedShortArray::ExternalUnsignedShortArrayVerify() { 248 ASSERT(IsExternalUnsignedShortArray()); 249} 250 251 252void ExternalIntArray::ExternalIntArrayVerify() { 253 ASSERT(IsExternalIntArray()); 254} 255 256 257void ExternalUnsignedIntArray::ExternalUnsignedIntArrayVerify() { 258 ASSERT(IsExternalUnsignedIntArray()); 259} 260 261 262void ExternalFloatArray::ExternalFloatArrayVerify() { 263 ASSERT(IsExternalFloatArray()); 264} 265 266 267void ExternalDoubleArray::ExternalDoubleArrayVerify() { 268 ASSERT(IsExternalDoubleArray()); 269} 270 271 272void JSObject::JSObjectVerify() { 273 VerifyHeapPointer(properties()); 274 VerifyHeapPointer(elements()); 275 276 if (GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS) { 277 ASSERT(this->elements()->IsFixedArray()); 278 ASSERT(this->elements()->length() >= 2); 279 } 280 281 if (HasFastProperties()) { 282 CHECK_EQ(map()->unused_property_fields(), 283 (map()->inobject_properties() + properties()->length() - 284 map()->NextFreePropertyIndex())); 285 } 286 ASSERT_EQ((map()->has_fast_elements() || 287 map()->has_fast_smi_only_elements() || 288 (elements() == GetHeap()->empty_fixed_array())), 289 (elements()->map() == GetHeap()->fixed_array_map() || 290 elements()->map() == GetHeap()->fixed_cow_array_map())); 291 ASSERT(map()->has_fast_elements() == HasFastElements()); 292} 293 294 295void Map::MapVerify() { 296 ASSERT(!HEAP->InNewSpace(this)); 297 ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE); 298 ASSERT(instance_size() == kVariableSizeSentinel || 299 (kPointerSize <= instance_size() && 300 instance_size() < HEAP->Capacity())); 301 VerifyHeapPointer(prototype()); 302 VerifyHeapPointer(instance_descriptors()); 303} 304 305 306void Map::SharedMapVerify() { 307 MapVerify(); 308 ASSERT(is_shared()); 309 ASSERT(instance_descriptors()->IsEmpty()); 310 ASSERT_EQ(0, pre_allocated_property_fields()); 311 ASSERT_EQ(0, unused_property_fields()); 312 ASSERT_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()), 313 visitor_id()); 314} 315 316 317void CodeCache::CodeCacheVerify() { 318 VerifyHeapPointer(default_cache()); 319 VerifyHeapPointer(normal_type_cache()); 320 ASSERT(default_cache()->IsFixedArray()); 321 ASSERT(normal_type_cache()->IsUndefined() 322 || normal_type_cache()->IsCodeCacheHashTable()); 323} 324 325 326void PolymorphicCodeCache::PolymorphicCodeCacheVerify() { 327 VerifyHeapPointer(cache()); 328 ASSERT(cache()->IsUndefined() || cache()->IsPolymorphicCodeCacheHashTable()); 329} 330 331 332void TypeFeedbackInfo::TypeFeedbackInfoVerify() { 333 VerifyObjectField(kIcTotalCountOffset); 334 VerifyObjectField(kIcWithTypeinfoCountOffset); 335 VerifyHeapPointer(type_feedback_cells()); 336} 337 338 339void AliasedArgumentsEntry::AliasedArgumentsEntryVerify() { 340 VerifySmiField(kAliasedContextSlot); 341} 342 343 344void FixedArray::FixedArrayVerify() { 345 for (int i = 0; i < length(); i++) { 346 Object* e = get(i); 347 if (e->IsHeapObject()) { 348 VerifyHeapPointer(e); 349 } else { 350 e->Verify(); 351 } 352 } 353} 354 355 356void FixedDoubleArray::FixedDoubleArrayVerify() { 357 for (int i = 0; i < length(); i++) { 358 if (!is_the_hole(i)) { 359 double value = get_scalar(i); 360 ASSERT(!isnan(value) || 361 (BitCast<uint64_t>(value) == 362 BitCast<uint64_t>(canonical_not_the_hole_nan_as_double())) || 363 ((BitCast<uint64_t>(value) & Double::kSignMask) != 0)); 364 } 365 } 366} 367 368 369void JSValue::JSValueVerify() { 370 Object* v = value(); 371 if (v->IsHeapObject()) { 372 VerifyHeapPointer(v); 373 } 374} 375 376 377void JSDate::JSDateVerify() { 378 if (value()->IsHeapObject()) { 379 VerifyHeapPointer(value()); 380 } 381 CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber()); 382 CHECK(year()->IsUndefined() || year()->IsSmi() || year()->IsNaN()); 383 CHECK(month()->IsUndefined() || month()->IsSmi() || month()->IsNaN()); 384 CHECK(day()->IsUndefined() || day()->IsSmi() || day()->IsNaN()); 385 CHECK(weekday()->IsUndefined() || weekday()->IsSmi() || weekday()->IsNaN()); 386 CHECK(hour()->IsUndefined() || hour()->IsSmi() || hour()->IsNaN()); 387 CHECK(min()->IsUndefined() || min()->IsSmi() || min()->IsNaN()); 388 CHECK(sec()->IsUndefined() || sec()->IsSmi() || sec()->IsNaN()); 389 CHECK(cache_stamp()->IsUndefined() || 390 cache_stamp()->IsSmi() || 391 cache_stamp()->IsNaN()); 392 393 if (month()->IsSmi()) { 394 int month = Smi::cast(this->month())->value(); 395 CHECK(0 <= month && month <= 11); 396 } 397 if (day()->IsSmi()) { 398 int day = Smi::cast(this->day())->value(); 399 CHECK(1 <= day && day <= 31); 400 } 401 if (hour()->IsSmi()) { 402 int hour = Smi::cast(this->hour())->value(); 403 CHECK(0 <= hour && hour <= 23); 404 } 405 if (min()->IsSmi()) { 406 int min = Smi::cast(this->min())->value(); 407 CHECK(0 <= min && min <= 59); 408 } 409 if (sec()->IsSmi()) { 410 int sec = Smi::cast(this->sec())->value(); 411 CHECK(0 <= sec && sec <= 59); 412 } 413 if (weekday()->IsSmi()) { 414 int weekday = Smi::cast(this->weekday())->value(); 415 CHECK(0 <= weekday && weekday <= 6); 416 } 417 if (cache_stamp()->IsSmi()) { 418 CHECK(Smi::cast(cache_stamp())->value() <= 419 Smi::cast(Isolate::Current()->date_cache()->stamp())->value()); 420 } 421} 422 423 424void JSMessageObject::JSMessageObjectVerify() { 425 CHECK(IsJSMessageObject()); 426 CHECK(type()->IsString()); 427 CHECK(arguments()->IsJSArray()); 428 VerifyObjectField(kStartPositionOffset); 429 VerifyObjectField(kEndPositionOffset); 430 VerifyObjectField(kArgumentsOffset); 431 VerifyObjectField(kScriptOffset); 432 VerifyObjectField(kStackTraceOffset); 433 VerifyObjectField(kStackFramesOffset); 434} 435 436 437void String::StringVerify() { 438 CHECK(IsString()); 439 CHECK(length() >= 0 && length() <= Smi::kMaxValue); 440 if (IsSymbol()) { 441 CHECK(!HEAP->InNewSpace(this)); 442 } 443 if (IsConsString()) { 444 ConsString::cast(this)->ConsStringVerify(); 445 } else if (IsSlicedString()) { 446 SlicedString::cast(this)->SlicedStringVerify(); 447 } 448} 449 450 451void ConsString::ConsStringVerify() { 452 CHECK(this->first()->IsString()); 453 CHECK(this->second() == GetHeap()->empty_string() || 454 this->second()->IsString()); 455 CHECK(this->length() >= ConsString::kMinLength); 456 if (this->IsFlat()) { 457 // A flat cons can only be created by String::SlowTryFlatten. 458 // Afterwards, the first part may be externalized. 459 CHECK(this->first()->IsSeqString() || this->first()->IsExternalString()); 460 } 461} 462 463 464void SlicedString::SlicedStringVerify() { 465 CHECK(!this->parent()->IsConsString()); 466 CHECK(!this->parent()->IsSlicedString()); 467 CHECK(this->length() >= SlicedString::kMinLength); 468} 469 470 471void JSFunction::JSFunctionVerify() { 472 CHECK(IsJSFunction()); 473 VerifyObjectField(kPrototypeOrInitialMapOffset); 474 VerifyObjectField(kNextFunctionLinkOffset); 475 CHECK(code()->IsCode()); 476 CHECK(next_function_link()->IsUndefined() || 477 next_function_link()->IsJSFunction()); 478} 479 480 481void SharedFunctionInfo::SharedFunctionInfoVerify() { 482 CHECK(IsSharedFunctionInfo()); 483 VerifyObjectField(kNameOffset); 484 VerifyObjectField(kCodeOffset); 485 VerifyObjectField(kScopeInfoOffset); 486 VerifyObjectField(kInstanceClassNameOffset); 487 VerifyObjectField(kFunctionDataOffset); 488 VerifyObjectField(kScriptOffset); 489 VerifyObjectField(kDebugInfoOffset); 490} 491 492 493void JSGlobalProxy::JSGlobalProxyVerify() { 494 CHECK(IsJSGlobalProxy()); 495 JSObjectVerify(); 496 VerifyObjectField(JSGlobalProxy::kContextOffset); 497 // Make sure that this object has no properties, elements. 498 CHECK_EQ(0, properties()->length()); 499 CHECK(HasFastElements()); 500 CHECK_EQ(0, FixedArray::cast(elements())->length()); 501} 502 503 504void JSGlobalObject::JSGlobalObjectVerify() { 505 CHECK(IsJSGlobalObject()); 506 JSObjectVerify(); 507 for (int i = GlobalObject::kBuiltinsOffset; 508 i < JSGlobalObject::kSize; 509 i += kPointerSize) { 510 VerifyObjectField(i); 511 } 512} 513 514 515void JSBuiltinsObject::JSBuiltinsObjectVerify() { 516 CHECK(IsJSBuiltinsObject()); 517 JSObjectVerify(); 518 for (int i = GlobalObject::kBuiltinsOffset; 519 i < JSBuiltinsObject::kSize; 520 i += kPointerSize) { 521 VerifyObjectField(i); 522 } 523} 524 525 526void Oddball::OddballVerify() { 527 CHECK(IsOddball()); 528 VerifyHeapPointer(to_string()); 529 Object* number = to_number(); 530 if (number->IsHeapObject()) { 531 ASSERT(number == HEAP->nan_value()); 532 } else { 533 ASSERT(number->IsSmi()); 534 int value = Smi::cast(number)->value(); 535 // Hidden oddballs have negative smis. 536 const int kLeastHiddenOddballNumber = -4; 537 ASSERT(value <= 1); 538 ASSERT(value >= kLeastHiddenOddballNumber); 539 } 540} 541 542 543void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() { 544 CHECK(IsJSGlobalPropertyCell()); 545 VerifyObjectField(kValueOffset); 546} 547 548 549void Code::CodeVerify() { 550 CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()), 551 kCodeAlignment)); 552 relocation_info()->Verify(); 553 Address last_gc_pc = NULL; 554 for (RelocIterator it(this); !it.done(); it.next()) { 555 it.rinfo()->Verify(); 556 // Ensure that GC will not iterate twice over the same pointer. 557 if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) { 558 CHECK(it.rinfo()->pc() != last_gc_pc); 559 last_gc_pc = it.rinfo()->pc(); 560 } 561 } 562} 563 564 565void JSArray::JSArrayVerify() { 566 JSObjectVerify(); 567 ASSERT(length()->IsNumber() || length()->IsUndefined()); 568 ASSERT(elements()->IsUndefined() || 569 elements()->IsFixedArray() || 570 elements()->IsFixedDoubleArray()); 571} 572 573 574void JSSet::JSSetVerify() { 575 CHECK(IsJSSet()); 576 JSObjectVerify(); 577 VerifyHeapPointer(table()); 578 ASSERT(table()->IsHashTable() || table()->IsUndefined()); 579} 580 581 582void JSMap::JSMapVerify() { 583 CHECK(IsJSMap()); 584 JSObjectVerify(); 585 VerifyHeapPointer(table()); 586 ASSERT(table()->IsHashTable() || table()->IsUndefined()); 587} 588 589 590void JSWeakMap::JSWeakMapVerify() { 591 CHECK(IsJSWeakMap()); 592 JSObjectVerify(); 593 VerifyHeapPointer(table()); 594 ASSERT(table()->IsHashTable() || table()->IsUndefined()); 595} 596 597 598void JSRegExp::JSRegExpVerify() { 599 JSObjectVerify(); 600 ASSERT(data()->IsUndefined() || data()->IsFixedArray()); 601 switch (TypeTag()) { 602 case JSRegExp::ATOM: { 603 FixedArray* arr = FixedArray::cast(data()); 604 ASSERT(arr->get(JSRegExp::kAtomPatternIndex)->IsString()); 605 break; 606 } 607 case JSRegExp::IRREGEXP: { 608 bool is_native = RegExpImpl::UsesNativeRegExp(); 609 610 FixedArray* arr = FixedArray::cast(data()); 611 Object* ascii_data = arr->get(JSRegExp::kIrregexpASCIICodeIndex); 612 // Smi : Not compiled yet (-1) or code prepared for flushing. 613 // JSObject: Compilation error. 614 // Code/ByteArray: Compiled code. 615 ASSERT(ascii_data->IsSmi() || 616 (is_native ? ascii_data->IsCode() : ascii_data->IsByteArray())); 617 Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex); 618 ASSERT(uc16_data->IsSmi() || 619 (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray())); 620 621 Object* ascii_saved = arr->get(JSRegExp::kIrregexpASCIICodeSavedIndex); 622 ASSERT(ascii_saved->IsSmi() || ascii_saved->IsString() || 623 ascii_saved->IsCode()); 624 Object* uc16_saved = arr->get(JSRegExp::kIrregexpUC16CodeSavedIndex); 625 ASSERT(uc16_saved->IsSmi() || uc16_saved->IsString() || 626 uc16_saved->IsCode()); 627 628 ASSERT(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi()); 629 ASSERT(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi()); 630 break; 631 } 632 default: 633 ASSERT_EQ(JSRegExp::NOT_COMPILED, TypeTag()); 634 ASSERT(data()->IsUndefined()); 635 break; 636 } 637} 638 639 640void JSProxy::JSProxyVerify() { 641 CHECK(IsJSProxy()); 642 VerifyPointer(handler()); 643 ASSERT(hash()->IsSmi() || hash()->IsUndefined()); 644} 645 646 647void JSFunctionProxy::JSFunctionProxyVerify() { 648 CHECK(IsJSFunctionProxy()); 649 JSProxyVerify(); 650 VerifyPointer(call_trap()); 651 VerifyPointer(construct_trap()); 652} 653 654 655void Foreign::ForeignVerify() { 656 ASSERT(IsForeign()); 657} 658 659 660void AccessorInfo::AccessorInfoVerify() { 661 CHECK(IsAccessorInfo()); 662 VerifyPointer(getter()); 663 VerifyPointer(setter()); 664 VerifyPointer(name()); 665 VerifyPointer(data()); 666 VerifyPointer(flag()); 667} 668 669 670void AccessorPair::AccessorPairVerify() { 671 CHECK(IsAccessorPair()); 672 VerifyPointer(getter()); 673 VerifyPointer(setter()); 674} 675 676 677void AccessCheckInfo::AccessCheckInfoVerify() { 678 CHECK(IsAccessCheckInfo()); 679 VerifyPointer(named_callback()); 680 VerifyPointer(indexed_callback()); 681 VerifyPointer(data()); 682} 683 684 685void InterceptorInfo::InterceptorInfoVerify() { 686 CHECK(IsInterceptorInfo()); 687 VerifyPointer(getter()); 688 VerifyPointer(setter()); 689 VerifyPointer(query()); 690 VerifyPointer(deleter()); 691 VerifyPointer(enumerator()); 692 VerifyPointer(data()); 693} 694 695 696void CallHandlerInfo::CallHandlerInfoVerify() { 697 CHECK(IsCallHandlerInfo()); 698 VerifyPointer(callback()); 699 VerifyPointer(data()); 700} 701 702 703void TemplateInfo::TemplateInfoVerify() { 704 VerifyPointer(tag()); 705 VerifyPointer(property_list()); 706} 707 708void FunctionTemplateInfo::FunctionTemplateInfoVerify() { 709 CHECK(IsFunctionTemplateInfo()); 710 TemplateInfoVerify(); 711 VerifyPointer(serial_number()); 712 VerifyPointer(call_code()); 713 VerifyPointer(property_accessors()); 714 VerifyPointer(prototype_template()); 715 VerifyPointer(parent_template()); 716 VerifyPointer(named_property_handler()); 717 VerifyPointer(indexed_property_handler()); 718 VerifyPointer(instance_template()); 719 VerifyPointer(signature()); 720 VerifyPointer(access_check_info()); 721} 722 723 724void ObjectTemplateInfo::ObjectTemplateInfoVerify() { 725 CHECK(IsObjectTemplateInfo()); 726 TemplateInfoVerify(); 727 VerifyPointer(constructor()); 728 VerifyPointer(internal_field_count()); 729} 730 731 732void SignatureInfo::SignatureInfoVerify() { 733 CHECK(IsSignatureInfo()); 734 VerifyPointer(receiver()); 735 VerifyPointer(args()); 736} 737 738 739void TypeSwitchInfo::TypeSwitchInfoVerify() { 740 CHECK(IsTypeSwitchInfo()); 741 VerifyPointer(types()); 742} 743 744 745void Script::ScriptVerify() { 746 CHECK(IsScript()); 747 VerifyPointer(source()); 748 VerifyPointer(name()); 749 line_offset()->SmiVerify(); 750 column_offset()->SmiVerify(); 751 VerifyPointer(data()); 752 VerifyPointer(wrapper()); 753 type()->SmiVerify(); 754 VerifyPointer(line_ends()); 755 VerifyPointer(id()); 756} 757 758 759#ifdef ENABLE_DEBUGGER_SUPPORT 760void DebugInfo::DebugInfoVerify() { 761 CHECK(IsDebugInfo()); 762 VerifyPointer(shared()); 763 VerifyPointer(original_code()); 764 VerifyPointer(code()); 765 VerifyPointer(break_points()); 766} 767 768 769void BreakPointInfo::BreakPointInfoVerify() { 770 CHECK(IsBreakPointInfo()); 771 code_position()->SmiVerify(); 772 source_position()->SmiVerify(); 773 statement_position()->SmiVerify(); 774 VerifyPointer(break_point_objects()); 775} 776#endif // ENABLE_DEBUGGER_SUPPORT 777 778 779void JSObject::IncrementSpillStatistics(SpillInformation* info) { 780 info->number_of_objects_++; 781 // Named properties 782 if (HasFastProperties()) { 783 info->number_of_objects_with_fast_properties_++; 784 info->number_of_fast_used_fields_ += map()->NextFreePropertyIndex(); 785 info->number_of_fast_unused_fields_ += map()->unused_property_fields(); 786 } else { 787 StringDictionary* dict = property_dictionary(); 788 info->number_of_slow_used_properties_ += dict->NumberOfElements(); 789 info->number_of_slow_unused_properties_ += 790 dict->Capacity() - dict->NumberOfElements(); 791 } 792 // Indexed properties 793 switch (GetElementsKind()) { 794 case FAST_ELEMENTS: { 795 info->number_of_objects_with_fast_elements_++; 796 int holes = 0; 797 FixedArray* e = FixedArray::cast(elements()); 798 int len = e->length(); 799 Heap* heap = HEAP; 800 for (int i = 0; i < len; i++) { 801 if (e->get(i) == heap->the_hole_value()) holes++; 802 } 803 info->number_of_fast_used_elements_ += len - holes; 804 info->number_of_fast_unused_elements_ += holes; 805 break; 806 } 807 case EXTERNAL_PIXEL_ELEMENTS: { 808 info->number_of_objects_with_fast_elements_++; 809 ExternalPixelArray* e = ExternalPixelArray::cast(elements()); 810 info->number_of_fast_used_elements_ += e->length(); 811 break; 812 } 813 case DICTIONARY_ELEMENTS: { 814 SeededNumberDictionary* dict = element_dictionary(); 815 info->number_of_slow_used_elements_ += dict->NumberOfElements(); 816 info->number_of_slow_unused_elements_ += 817 dict->Capacity() - dict->NumberOfElements(); 818 break; 819 } 820 default: 821 UNREACHABLE(); 822 break; 823 } 824} 825 826 827void JSObject::SpillInformation::Clear() { 828 number_of_objects_ = 0; 829 number_of_objects_with_fast_properties_ = 0; 830 number_of_objects_with_fast_elements_ = 0; 831 number_of_fast_used_fields_ = 0; 832 number_of_fast_unused_fields_ = 0; 833 number_of_slow_used_properties_ = 0; 834 number_of_slow_unused_properties_ = 0; 835 number_of_fast_used_elements_ = 0; 836 number_of_fast_unused_elements_ = 0; 837 number_of_slow_used_elements_ = 0; 838 number_of_slow_unused_elements_ = 0; 839} 840 841void JSObject::SpillInformation::Print() { 842 PrintF("\n JSObject Spill Statistics (#%d):\n", number_of_objects_); 843 844 PrintF(" - fast properties (#%d): %d (used) %d (unused)\n", 845 number_of_objects_with_fast_properties_, 846 number_of_fast_used_fields_, number_of_fast_unused_fields_); 847 848 PrintF(" - slow properties (#%d): %d (used) %d (unused)\n", 849 number_of_objects_ - number_of_objects_with_fast_properties_, 850 number_of_slow_used_properties_, number_of_slow_unused_properties_); 851 852 PrintF(" - fast elements (#%d): %d (used) %d (unused)\n", 853 number_of_objects_with_fast_elements_, 854 number_of_fast_used_elements_, number_of_fast_unused_elements_); 855 856 PrintF(" - slow elements (#%d): %d (used) %d (unused)\n", 857 number_of_objects_ - number_of_objects_with_fast_elements_, 858 number_of_slow_used_elements_, number_of_slow_unused_elements_); 859 860 PrintF("\n"); 861} 862 863 864bool DescriptorArray::IsSortedNoDuplicates() { 865 String* current_key = NULL; 866 uint32_t current = 0; 867 for (int i = 0; i < number_of_descriptors(); i++) { 868 String* key = GetKey(i); 869 if (key == current_key) { 870 PrintDescriptors(); 871 return false; 872 } 873 current_key = key; 874 uint32_t hash = GetKey(i)->Hash(); 875 if (hash < current) { 876 PrintDescriptors(); 877 return false; 878 } 879 current = hash; 880 } 881 return true; 882} 883 884 885void JSFunctionResultCache::JSFunctionResultCacheVerify() { 886 JSFunction::cast(get(kFactoryIndex))->Verify(); 887 888 int size = Smi::cast(get(kCacheSizeIndex))->value(); 889 ASSERT(kEntriesIndex <= size); 890 ASSERT(size <= length()); 891 ASSERT_EQ(0, size % kEntrySize); 892 893 int finger = Smi::cast(get(kFingerIndex))->value(); 894 ASSERT(kEntriesIndex <= finger); 895 ASSERT((finger < size) || (finger == kEntriesIndex && finger == size)); 896 ASSERT_EQ(0, finger % kEntrySize); 897 898 if (FLAG_enable_slow_asserts) { 899 for (int i = kEntriesIndex; i < size; i++) { 900 ASSERT(!get(i)->IsTheHole()); 901 get(i)->Verify(); 902 } 903 for (int i = size; i < length(); i++) { 904 ASSERT(get(i)->IsTheHole()); 905 get(i)->Verify(); 906 } 907 } 908} 909 910 911void NormalizedMapCache::NormalizedMapCacheVerify() { 912 FixedArray::cast(this)->Verify(); 913 if (FLAG_enable_slow_asserts) { 914 for (int i = 0; i < length(); i++) { 915 Object* e = get(i); 916 if (e->IsMap()) { 917 Map::cast(e)->SharedMapVerify(); 918 } else { 919 ASSERT(e->IsUndefined()); 920 } 921 } 922 } 923} 924 925 926#endif // DEBUG 927 928} } // namespace v8::internal 929