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