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