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/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