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/v8.h"
      6 
      7 #include "src/disassembler.h"
      8 #include "src/disasm.h"
      9 #include "src/jsregexp.h"
     10 #include "src/macro-assembler.h"
     11 #include "src/objects-visiting.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 #ifdef VERIFY_HEAP
     17 
     18 void Object::ObjectVerify() {
     19   if (IsSmi()) {
     20     Smi::cast(this)->SmiVerify();
     21   } else {
     22     HeapObject::cast(this)->HeapObjectVerify();
     23   }
     24 }
     25 
     26 
     27 void Object::VerifyPointer(Object* p) {
     28   if (p->IsHeapObject()) {
     29     HeapObject::VerifyHeapPointer(p);
     30   } else {
     31     CHECK(p->IsSmi());
     32   }
     33 }
     34 
     35 
     36 void Smi::SmiVerify() {
     37   CHECK(IsSmi());
     38 }
     39 
     40 
     41 void HeapObject::HeapObjectVerify() {
     42   InstanceType instance_type = map()->instance_type();
     43 
     44   if (instance_type < FIRST_NONSTRING_TYPE) {
     45     String::cast(this)->StringVerify();
     46     return;
     47   }
     48 
     49   switch (instance_type) {
     50     case SYMBOL_TYPE:
     51       Symbol::cast(this)->SymbolVerify();
     52       break;
     53     case MAP_TYPE:
     54       Map::cast(this)->MapVerify();
     55       break;
     56     case HEAP_NUMBER_TYPE:
     57       HeapNumber::cast(this)->HeapNumberVerify();
     58       break;
     59     case FIXED_ARRAY_TYPE:
     60       FixedArray::cast(this)->FixedArrayVerify();
     61       break;
     62     case FIXED_DOUBLE_ARRAY_TYPE:
     63       FixedDoubleArray::cast(this)->FixedDoubleArrayVerify();
     64       break;
     65     case CONSTANT_POOL_ARRAY_TYPE:
     66       ConstantPoolArray::cast(this)->ConstantPoolArrayVerify();
     67       break;
     68     case BYTE_ARRAY_TYPE:
     69       ByteArray::cast(this)->ByteArrayVerify();
     70       break;
     71     case FREE_SPACE_TYPE:
     72       FreeSpace::cast(this)->FreeSpaceVerify();
     73       break;
     74 
     75 #define VERIFY_TYPED_ARRAY(Type, type, TYPE, ctype, size)                      \
     76     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
     77       External##Type##Array::cast(this)->External##Type##ArrayVerify();        \
     78       break;                                                                   \
     79     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
     80       Fixed##Type##Array::cast(this)->FixedTypedArrayVerify();                 \
     81       break;
     82 
     83     TYPED_ARRAYS(VERIFY_TYPED_ARRAY)
     84 #undef VERIFY_TYPED_ARRAY
     85 
     86     case CODE_TYPE:
     87       Code::cast(this)->CodeVerify();
     88       break;
     89     case ODDBALL_TYPE:
     90       Oddball::cast(this)->OddballVerify();
     91       break;
     92     case JS_OBJECT_TYPE:
     93     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
     94       JSObject::cast(this)->JSObjectVerify();
     95       break;
     96     case JS_GENERATOR_OBJECT_TYPE:
     97       JSGeneratorObject::cast(this)->JSGeneratorObjectVerify();
     98       break;
     99     case JS_MODULE_TYPE:
    100       JSModule::cast(this)->JSModuleVerify();
    101       break;
    102     case JS_VALUE_TYPE:
    103       JSValue::cast(this)->JSValueVerify();
    104       break;
    105     case JS_DATE_TYPE:
    106       JSDate::cast(this)->JSDateVerify();
    107       break;
    108     case JS_FUNCTION_TYPE:
    109       JSFunction::cast(this)->JSFunctionVerify();
    110       break;
    111     case JS_GLOBAL_PROXY_TYPE:
    112       JSGlobalProxy::cast(this)->JSGlobalProxyVerify();
    113       break;
    114     case JS_GLOBAL_OBJECT_TYPE:
    115       JSGlobalObject::cast(this)->JSGlobalObjectVerify();
    116       break;
    117     case JS_BUILTINS_OBJECT_TYPE:
    118       JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
    119       break;
    120     case CELL_TYPE:
    121       Cell::cast(this)->CellVerify();
    122       break;
    123     case PROPERTY_CELL_TYPE:
    124       PropertyCell::cast(this)->PropertyCellVerify();
    125       break;
    126     case JS_ARRAY_TYPE:
    127       JSArray::cast(this)->JSArrayVerify();
    128       break;
    129     case JS_SET_TYPE:
    130       JSSet::cast(this)->JSSetVerify();
    131       break;
    132     case JS_MAP_TYPE:
    133       JSMap::cast(this)->JSMapVerify();
    134       break;
    135     case JS_SET_ITERATOR_TYPE:
    136       JSSetIterator::cast(this)->JSSetIteratorVerify();
    137       break;
    138     case JS_MAP_ITERATOR_TYPE:
    139       JSMapIterator::cast(this)->JSMapIteratorVerify();
    140       break;
    141     case JS_WEAK_MAP_TYPE:
    142       JSWeakMap::cast(this)->JSWeakMapVerify();
    143       break;
    144     case JS_WEAK_SET_TYPE:
    145       JSWeakSet::cast(this)->JSWeakSetVerify();
    146       break;
    147     case JS_REGEXP_TYPE:
    148       JSRegExp::cast(this)->JSRegExpVerify();
    149       break;
    150     case FILLER_TYPE:
    151       break;
    152     case JS_PROXY_TYPE:
    153       JSProxy::cast(this)->JSProxyVerify();
    154       break;
    155     case JS_FUNCTION_PROXY_TYPE:
    156       JSFunctionProxy::cast(this)->JSFunctionProxyVerify();
    157       break;
    158     case FOREIGN_TYPE:
    159       Foreign::cast(this)->ForeignVerify();
    160       break;
    161     case SHARED_FUNCTION_INFO_TYPE:
    162       SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
    163       break;
    164     case JS_MESSAGE_OBJECT_TYPE:
    165       JSMessageObject::cast(this)->JSMessageObjectVerify();
    166       break;
    167     case JS_ARRAY_BUFFER_TYPE:
    168       JSArrayBuffer::cast(this)->JSArrayBufferVerify();
    169       break;
    170     case JS_TYPED_ARRAY_TYPE:
    171       JSTypedArray::cast(this)->JSTypedArrayVerify();
    172       break;
    173     case JS_DATA_VIEW_TYPE:
    174       JSDataView::cast(this)->JSDataViewVerify();
    175       break;
    176 
    177 #define MAKE_STRUCT_CASE(NAME, Name, name) \
    178   case NAME##_TYPE:                        \
    179     Name::cast(this)->Name##Verify();      \
    180     break;
    181     STRUCT_LIST(MAKE_STRUCT_CASE)
    182 #undef MAKE_STRUCT_CASE
    183 
    184     default:
    185       UNREACHABLE();
    186       break;
    187   }
    188 }
    189 
    190 
    191 void HeapObject::VerifyHeapPointer(Object* p) {
    192   CHECK(p->IsHeapObject());
    193   HeapObject* ho = HeapObject::cast(p);
    194   CHECK(ho->GetHeap()->Contains(ho));
    195 }
    196 
    197 
    198 void Symbol::SymbolVerify() {
    199   CHECK(IsSymbol());
    200   CHECK(HasHashCode());
    201   CHECK_GT(Hash(), 0);
    202   CHECK(name()->IsUndefined() || name()->IsString());
    203   CHECK(flags()->IsSmi());
    204 }
    205 
    206 
    207 void HeapNumber::HeapNumberVerify() {
    208   CHECK(IsHeapNumber());
    209 }
    210 
    211 
    212 void ByteArray::ByteArrayVerify() {
    213   CHECK(IsByteArray());
    214 }
    215 
    216 
    217 void FreeSpace::FreeSpaceVerify() {
    218   CHECK(IsFreeSpace());
    219 }
    220 
    221 
    222 #define EXTERNAL_ARRAY_VERIFY(Type, type, TYPE, ctype, size)                  \
    223   void External##Type##Array::External##Type##ArrayVerify() {                 \
    224     CHECK(IsExternal##Type##Array());                                         \
    225   }
    226 
    227 TYPED_ARRAYS(EXTERNAL_ARRAY_VERIFY)
    228 #undef EXTERNAL_ARRAY_VERIFY
    229 
    230 
    231 template <class Traits>
    232 void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
    233   CHECK(IsHeapObject() &&
    234         HeapObject::cast(this)->map()->instance_type() ==
    235             Traits::kInstanceType);
    236 }
    237 
    238 
    239 bool JSObject::ElementsAreSafeToExamine() {
    240   // If a GC was caused while constructing this object, the elements
    241   // pointer may point to a one pointer filler map.
    242   return reinterpret_cast<Map*>(elements()) !=
    243       GetHeap()->one_pointer_filler_map();
    244 }
    245 
    246 
    247 void JSObject::JSObjectVerify() {
    248   VerifyHeapPointer(properties());
    249   VerifyHeapPointer(elements());
    250 
    251   if (GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS) {
    252     CHECK(this->elements()->IsFixedArray());
    253     CHECK_GE(this->elements()->length(), 2);
    254   }
    255 
    256   if (HasFastProperties()) {
    257     CHECK_EQ(map()->unused_property_fields(),
    258              (map()->inobject_properties() + properties()->length() -
    259               map()->NextFreePropertyIndex()));
    260     DescriptorArray* descriptors = map()->instance_descriptors();
    261     for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
    262       if (descriptors->GetDetails(i).type() == FIELD) {
    263         Representation r = descriptors->GetDetails(i).representation();
    264         FieldIndex index = FieldIndex::ForDescriptor(map(), i);
    265         Object* value = RawFastPropertyAt(index);
    266         if (r.IsDouble()) ASSERT(value->IsHeapNumber());
    267         if (value->IsUninitialized()) continue;
    268         if (r.IsSmi()) ASSERT(value->IsSmi());
    269         if (r.IsHeapObject()) ASSERT(value->IsHeapObject());
    270         HeapType* field_type = descriptors->GetFieldType(i);
    271         if (r.IsNone()) {
    272           CHECK(field_type->Is(HeapType::None()));
    273         } else if (!HeapType::Any()->Is(field_type)) {
    274           CHECK(!field_type->NowStable() || field_type->NowContains(value));
    275         }
    276       }
    277     }
    278   }
    279 
    280   // If a GC was caused while constructing this object, the elements
    281   // pointer may point to a one pointer filler map.
    282   if (ElementsAreSafeToExamine()) {
    283     CHECK_EQ((map()->has_fast_smi_or_object_elements() ||
    284               (elements() == GetHeap()->empty_fixed_array())),
    285              (elements()->map() == GetHeap()->fixed_array_map() ||
    286               elements()->map() == GetHeap()->fixed_cow_array_map()));
    287     CHECK(map()->has_fast_object_elements() == HasFastObjectElements());
    288   }
    289 }
    290 
    291 
    292 void Map::MapVerify() {
    293   Heap* heap = GetHeap();
    294   CHECK(!heap->InNewSpace(this));
    295   CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
    296   CHECK(instance_size() == kVariableSizeSentinel ||
    297          (kPointerSize <= instance_size() &&
    298           instance_size() < heap->Capacity()));
    299   VerifyHeapPointer(prototype());
    300   VerifyHeapPointer(instance_descriptors());
    301   SLOW_ASSERT(instance_descriptors()->IsSortedNoDuplicates());
    302   if (HasTransitionArray()) {
    303     SLOW_ASSERT(transitions()->IsSortedNoDuplicates());
    304     SLOW_ASSERT(transitions()->IsConsistentWithBackPointers(this));
    305   }
    306 }
    307 
    308 
    309 void Map::SharedMapVerify() {
    310   MapVerify();
    311   CHECK(is_shared());
    312   CHECK(instance_descriptors()->IsEmpty());
    313   CHECK_EQ(0, pre_allocated_property_fields());
    314   CHECK_EQ(0, unused_property_fields());
    315   CHECK_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
    316       visitor_id());
    317 }
    318 
    319 
    320 void Map::VerifyOmittedMapChecks() {
    321   if (!FLAG_omit_map_checks_for_leaf_maps) return;
    322   if (!is_stable() ||
    323       is_deprecated() ||
    324       HasTransitionArray() ||
    325       is_dictionary_map()) {
    326     CHECK_EQ(0, dependent_code()->number_of_entries(
    327         DependentCode::kPrototypeCheckGroup));
    328   }
    329 }
    330 
    331 
    332 void CodeCache::CodeCacheVerify() {
    333   VerifyHeapPointer(default_cache());
    334   VerifyHeapPointer(normal_type_cache());
    335   CHECK(default_cache()->IsFixedArray());
    336   CHECK(normal_type_cache()->IsUndefined()
    337          || normal_type_cache()->IsCodeCacheHashTable());
    338 }
    339 
    340 
    341 void PolymorphicCodeCache::PolymorphicCodeCacheVerify() {
    342   VerifyHeapPointer(cache());
    343   CHECK(cache()->IsUndefined() || cache()->IsPolymorphicCodeCacheHashTable());
    344 }
    345 
    346 
    347 void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
    348   VerifyObjectField(kStorage1Offset);
    349   VerifyObjectField(kStorage2Offset);
    350 }
    351 
    352 
    353 void AliasedArgumentsEntry::AliasedArgumentsEntryVerify() {
    354   VerifySmiField(kAliasedContextSlot);
    355 }
    356 
    357 
    358 void FixedArray::FixedArrayVerify() {
    359   for (int i = 0; i < length(); i++) {
    360     Object* e = get(i);
    361     VerifyPointer(e);
    362   }
    363 }
    364 
    365 
    366 void FixedDoubleArray::FixedDoubleArrayVerify() {
    367   for (int i = 0; i < length(); i++) {
    368     if (!is_the_hole(i)) {
    369       double value = get_scalar(i);
    370       CHECK(!std::isnan(value) ||
    371              (BitCast<uint64_t>(value) ==
    372               BitCast<uint64_t>(canonical_not_the_hole_nan_as_double())) ||
    373              ((BitCast<uint64_t>(value) & Double::kSignMask) != 0));
    374     }
    375   }
    376 }
    377 
    378 
    379 void ConstantPoolArray::ConstantPoolArrayVerify() {
    380   CHECK(IsConstantPoolArray());
    381   ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR);
    382   while (!code_iter.is_finished()) {
    383     Address code_entry = get_code_ptr_entry(code_iter.next_index());
    384     VerifyPointer(Code::GetCodeFromTargetAddress(code_entry));
    385   }
    386   ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR);
    387   while (!heap_iter.is_finished()) {
    388     VerifyObjectField(OffsetOfElementAt(heap_iter.next_index()));
    389   }
    390 }
    391 
    392 
    393 void JSGeneratorObject::JSGeneratorObjectVerify() {
    394   // In an expression like "new g()", there can be a point where a generator
    395   // object is allocated but its fields are all undefined, as it hasn't yet been
    396   // initialized by the generator.  Hence these weak checks.
    397   VerifyObjectField(kFunctionOffset);
    398   VerifyObjectField(kContextOffset);
    399   VerifyObjectField(kReceiverOffset);
    400   VerifyObjectField(kOperandStackOffset);
    401   VerifyObjectField(kContinuationOffset);
    402   VerifyObjectField(kStackHandlerIndexOffset);
    403 }
    404 
    405 
    406 void JSModule::JSModuleVerify() {
    407   VerifyObjectField(kContextOffset);
    408   VerifyObjectField(kScopeInfoOffset);
    409   CHECK(context()->IsUndefined() ||
    410         Context::cast(context())->IsModuleContext());
    411 }
    412 
    413 
    414 void JSValue::JSValueVerify() {
    415   Object* v = value();
    416   if (v->IsHeapObject()) {
    417     VerifyHeapPointer(v);
    418   }
    419 }
    420 
    421 
    422 void JSDate::JSDateVerify() {
    423   if (value()->IsHeapObject()) {
    424     VerifyHeapPointer(value());
    425   }
    426   CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber());
    427   CHECK(year()->IsUndefined() || year()->IsSmi() || year()->IsNaN());
    428   CHECK(month()->IsUndefined() || month()->IsSmi() || month()->IsNaN());
    429   CHECK(day()->IsUndefined() || day()->IsSmi() || day()->IsNaN());
    430   CHECK(weekday()->IsUndefined() || weekday()->IsSmi() || weekday()->IsNaN());
    431   CHECK(hour()->IsUndefined() || hour()->IsSmi() || hour()->IsNaN());
    432   CHECK(min()->IsUndefined() || min()->IsSmi() || min()->IsNaN());
    433   CHECK(sec()->IsUndefined() || sec()->IsSmi() || sec()->IsNaN());
    434   CHECK(cache_stamp()->IsUndefined() ||
    435         cache_stamp()->IsSmi() ||
    436         cache_stamp()->IsNaN());
    437 
    438   if (month()->IsSmi()) {
    439     int month = Smi::cast(this->month())->value();
    440     CHECK(0 <= month && month <= 11);
    441   }
    442   if (day()->IsSmi()) {
    443     int day = Smi::cast(this->day())->value();
    444     CHECK(1 <= day && day <= 31);
    445   }
    446   if (hour()->IsSmi()) {
    447     int hour = Smi::cast(this->hour())->value();
    448     CHECK(0 <= hour && hour <= 23);
    449   }
    450   if (min()->IsSmi()) {
    451     int min = Smi::cast(this->min())->value();
    452     CHECK(0 <= min && min <= 59);
    453   }
    454   if (sec()->IsSmi()) {
    455     int sec = Smi::cast(this->sec())->value();
    456     CHECK(0 <= sec && sec <= 59);
    457   }
    458   if (weekday()->IsSmi()) {
    459     int weekday = Smi::cast(this->weekday())->value();
    460     CHECK(0 <= weekday && weekday <= 6);
    461   }
    462   if (cache_stamp()->IsSmi()) {
    463     CHECK(Smi::cast(cache_stamp())->value() <=
    464           Smi::cast(GetIsolate()->date_cache()->stamp())->value());
    465   }
    466 }
    467 
    468 
    469 void JSMessageObject::JSMessageObjectVerify() {
    470   CHECK(IsJSMessageObject());
    471   CHECK(type()->IsString());
    472   CHECK(arguments()->IsJSArray());
    473   VerifyObjectField(kStartPositionOffset);
    474   VerifyObjectField(kEndPositionOffset);
    475   VerifyObjectField(kArgumentsOffset);
    476   VerifyObjectField(kScriptOffset);
    477   VerifyObjectField(kStackFramesOffset);
    478 }
    479 
    480 
    481 void String::StringVerify() {
    482   CHECK(IsString());
    483   CHECK(length() >= 0 && length() <= Smi::kMaxValue);
    484   if (IsInternalizedString()) {
    485     CHECK(!GetHeap()->InNewSpace(this));
    486   }
    487   if (IsConsString()) {
    488     ConsString::cast(this)->ConsStringVerify();
    489   } else if (IsSlicedString()) {
    490     SlicedString::cast(this)->SlicedStringVerify();
    491   }
    492 }
    493 
    494 
    495 void ConsString::ConsStringVerify() {
    496   CHECK(this->first()->IsString());
    497   CHECK(this->second() == GetHeap()->empty_string() ||
    498         this->second()->IsString());
    499   CHECK(this->length() >= ConsString::kMinLength);
    500   CHECK(this->length() == this->first()->length() + this->second()->length());
    501   if (this->IsFlat()) {
    502     // A flat cons can only be created by String::SlowTryFlatten.
    503     // Afterwards, the first part may be externalized.
    504     CHECK(this->first()->IsSeqString() || this->first()->IsExternalString());
    505   }
    506 }
    507 
    508 
    509 void SlicedString::SlicedStringVerify() {
    510   CHECK(!this->parent()->IsConsString());
    511   CHECK(!this->parent()->IsSlicedString());
    512   CHECK(this->length() >= SlicedString::kMinLength);
    513 }
    514 
    515 
    516 void JSFunction::JSFunctionVerify() {
    517   CHECK(IsJSFunction());
    518   VerifyObjectField(kPrototypeOrInitialMapOffset);
    519   VerifyObjectField(kNextFunctionLinkOffset);
    520   CHECK(code()->IsCode());
    521   CHECK(next_function_link() == NULL ||
    522         next_function_link()->IsUndefined() ||
    523         next_function_link()->IsJSFunction());
    524 }
    525 
    526 
    527 void SharedFunctionInfo::SharedFunctionInfoVerify() {
    528   CHECK(IsSharedFunctionInfo());
    529   VerifyObjectField(kNameOffset);
    530   VerifyObjectField(kCodeOffset);
    531   VerifyObjectField(kOptimizedCodeMapOffset);
    532   VerifyObjectField(kFeedbackVectorOffset);
    533   VerifyObjectField(kScopeInfoOffset);
    534   VerifyObjectField(kInstanceClassNameOffset);
    535   VerifyObjectField(kFunctionDataOffset);
    536   VerifyObjectField(kScriptOffset);
    537   VerifyObjectField(kDebugInfoOffset);
    538 }
    539 
    540 
    541 void JSGlobalProxy::JSGlobalProxyVerify() {
    542   CHECK(IsJSGlobalProxy());
    543   JSObjectVerify();
    544   VerifyObjectField(JSGlobalProxy::kNativeContextOffset);
    545   // Make sure that this object has no properties, elements.
    546   CHECK_EQ(0, properties()->length());
    547   CHECK(HasFastSmiElements());
    548   CHECK_EQ(0, FixedArray::cast(elements())->length());
    549 }
    550 
    551 
    552 void JSGlobalObject::JSGlobalObjectVerify() {
    553   CHECK(IsJSGlobalObject());
    554   JSObjectVerify();
    555   for (int i = GlobalObject::kBuiltinsOffset;
    556        i < JSGlobalObject::kSize;
    557        i += kPointerSize) {
    558     VerifyObjectField(i);
    559   }
    560 }
    561 
    562 
    563 void JSBuiltinsObject::JSBuiltinsObjectVerify() {
    564   CHECK(IsJSBuiltinsObject());
    565   JSObjectVerify();
    566   for (int i = GlobalObject::kBuiltinsOffset;
    567        i < JSBuiltinsObject::kSize;
    568        i += kPointerSize) {
    569     VerifyObjectField(i);
    570   }
    571 }
    572 
    573 
    574 void Oddball::OddballVerify() {
    575   CHECK(IsOddball());
    576   Heap* heap = GetHeap();
    577   VerifyHeapPointer(to_string());
    578   Object* number = to_number();
    579   if (number->IsHeapObject()) {
    580     CHECK(number == heap->nan_value());
    581   } else {
    582     CHECK(number->IsSmi());
    583     int value = Smi::cast(number)->value();
    584     // Hidden oddballs have negative smis.
    585     const int kLeastHiddenOddballNumber = -5;
    586     CHECK_LE(value, 1);
    587     CHECK(value >= kLeastHiddenOddballNumber);
    588   }
    589   if (map() == heap->undefined_map()) {
    590     CHECK(this == heap->undefined_value());
    591   } else if (map() == heap->the_hole_map()) {
    592     CHECK(this == heap->the_hole_value());
    593   } else if (map() == heap->null_map()) {
    594     CHECK(this == heap->null_value());
    595   } else if (map() == heap->boolean_map()) {
    596     CHECK(this == heap->true_value() ||
    597           this == heap->false_value());
    598   } else if (map() == heap->uninitialized_map()) {
    599     CHECK(this == heap->uninitialized_value());
    600   } else if (map() == heap->no_interceptor_result_sentinel_map()) {
    601     CHECK(this == heap->no_interceptor_result_sentinel());
    602   } else if (map() == heap->arguments_marker_map()) {
    603     CHECK(this == heap->arguments_marker());
    604   } else if (map() == heap->termination_exception_map()) {
    605     CHECK(this == heap->termination_exception());
    606   } else if (map() == heap->exception_map()) {
    607     CHECK(this == heap->exception());
    608   } else {
    609     UNREACHABLE();
    610   }
    611 }
    612 
    613 
    614 void Cell::CellVerify() {
    615   CHECK(IsCell());
    616   VerifyObjectField(kValueOffset);
    617 }
    618 
    619 
    620 void PropertyCell::PropertyCellVerify() {
    621   CHECK(IsPropertyCell());
    622   VerifyObjectField(kValueOffset);
    623   VerifyObjectField(kTypeOffset);
    624 }
    625 
    626 
    627 void Code::CodeVerify() {
    628   CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
    629                   kCodeAlignment));
    630   relocation_info()->ObjectVerify();
    631   Address last_gc_pc = NULL;
    632   Isolate* isolate = GetIsolate();
    633   for (RelocIterator it(this); !it.done(); it.next()) {
    634     it.rinfo()->Verify(isolate);
    635     // Ensure that GC will not iterate twice over the same pointer.
    636     if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
    637       CHECK(it.rinfo()->pc() != last_gc_pc);
    638       last_gc_pc = it.rinfo()->pc();
    639     }
    640   }
    641 }
    642 
    643 
    644 void Code::VerifyEmbeddedObjectsDependency() {
    645   if (!CanContainWeakObjects()) return;
    646   DisallowHeapAllocation no_gc;
    647   Isolate* isolate = GetIsolate();
    648   HandleScope scope(isolate);
    649   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
    650   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
    651     Object* obj = it.rinfo()->target_object();
    652     if (IsWeakObject(obj)) {
    653       if (obj->IsMap()) {
    654         Map* map = Map::cast(obj);
    655         DependentCode::DependencyGroup group = is_optimized_code() ?
    656             DependentCode::kWeakCodeGroup : DependentCode::kWeakICGroup;
    657         CHECK(map->dependent_code()->Contains(group, this));
    658       } else if (obj->IsJSObject()) {
    659         Object* raw_table = GetIsolate()->heap()->weak_object_to_code_table();
    660         WeakHashTable* table = WeakHashTable::cast(raw_table);
    661         Handle<Object> key_obj(obj, isolate);
    662         CHECK(DependentCode::cast(table->Lookup(key_obj))->Contains(
    663             DependentCode::kWeakCodeGroup, this));
    664       }
    665     }
    666   }
    667 }
    668 
    669 
    670 void JSArray::JSArrayVerify() {
    671   JSObjectVerify();
    672   CHECK(length()->IsNumber() || length()->IsUndefined());
    673   // If a GC was caused while constructing this array, the elements
    674   // pointer may point to a one pointer filler map.
    675   if (ElementsAreSafeToExamine()) {
    676     CHECK(elements()->IsUndefined() ||
    677           elements()->IsFixedArray() ||
    678           elements()->IsFixedDoubleArray());
    679   }
    680 }
    681 
    682 
    683 void JSSet::JSSetVerify() {
    684   CHECK(IsJSSet());
    685   JSObjectVerify();
    686   VerifyHeapPointer(table());
    687   CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
    688   // TODO(arv): Verify OrderedHashTable too.
    689 }
    690 
    691 
    692 void JSMap::JSMapVerify() {
    693   CHECK(IsJSMap());
    694   JSObjectVerify();
    695   VerifyHeapPointer(table());
    696   CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
    697   // TODO(arv): Verify OrderedHashTable too.
    698 }
    699 
    700 
    701 void JSSetIterator::JSSetIteratorVerify() {
    702   CHECK(IsJSSetIterator());
    703   JSObjectVerify();
    704   VerifyHeapPointer(table());
    705   CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
    706   CHECK(index()->IsSmi() || index()->IsUndefined());
    707   CHECK(kind()->IsSmi() || kind()->IsUndefined());
    708 }
    709 
    710 
    711 void JSMapIterator::JSMapIteratorVerify() {
    712   CHECK(IsJSMapIterator());
    713   JSObjectVerify();
    714   VerifyHeapPointer(table());
    715   CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
    716   CHECK(index()->IsSmi() || index()->IsUndefined());
    717   CHECK(kind()->IsSmi() || kind()->IsUndefined());
    718 }
    719 
    720 
    721 void JSWeakMap::JSWeakMapVerify() {
    722   CHECK(IsJSWeakMap());
    723   JSObjectVerify();
    724   VerifyHeapPointer(table());
    725   CHECK(table()->IsHashTable() || table()->IsUndefined());
    726 }
    727 
    728 
    729 void JSWeakSet::JSWeakSetVerify() {
    730   CHECK(IsJSWeakSet());
    731   JSObjectVerify();
    732   VerifyHeapPointer(table());
    733   CHECK(table()->IsHashTable() || table()->IsUndefined());
    734 }
    735 
    736 
    737 void JSRegExp::JSRegExpVerify() {
    738   JSObjectVerify();
    739   CHECK(data()->IsUndefined() || data()->IsFixedArray());
    740   switch (TypeTag()) {
    741     case JSRegExp::ATOM: {
    742       FixedArray* arr = FixedArray::cast(data());
    743       CHECK(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
    744       break;
    745     }
    746     case JSRegExp::IRREGEXP: {
    747       bool is_native = RegExpImpl::UsesNativeRegExp();
    748 
    749       FixedArray* arr = FixedArray::cast(data());
    750       Object* ascii_data = arr->get(JSRegExp::kIrregexpASCIICodeIndex);
    751       // Smi : Not compiled yet (-1) or code prepared for flushing.
    752       // JSObject: Compilation error.
    753       // Code/ByteArray: Compiled code.
    754       CHECK(ascii_data->IsSmi() ||
    755              (is_native ? ascii_data->IsCode() : ascii_data->IsByteArray()));
    756       Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex);
    757       CHECK(uc16_data->IsSmi() ||
    758              (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray()));
    759 
    760       Object* ascii_saved = arr->get(JSRegExp::kIrregexpASCIICodeSavedIndex);
    761       CHECK(ascii_saved->IsSmi() || ascii_saved->IsString() ||
    762              ascii_saved->IsCode());
    763       Object* uc16_saved = arr->get(JSRegExp::kIrregexpUC16CodeSavedIndex);
    764       CHECK(uc16_saved->IsSmi() || uc16_saved->IsString() ||
    765              uc16_saved->IsCode());
    766 
    767       CHECK(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi());
    768       CHECK(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi());
    769       break;
    770     }
    771     default:
    772       CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag());
    773       CHECK(data()->IsUndefined());
    774       break;
    775   }
    776 }
    777 
    778 
    779 void JSProxy::JSProxyVerify() {
    780   CHECK(IsJSProxy());
    781   VerifyPointer(handler());
    782   CHECK(hash()->IsSmi() || hash()->IsUndefined());
    783 }
    784 
    785 
    786 void JSFunctionProxy::JSFunctionProxyVerify() {
    787   CHECK(IsJSFunctionProxy());
    788   JSProxyVerify();
    789   VerifyPointer(call_trap());
    790   VerifyPointer(construct_trap());
    791 }
    792 
    793 
    794 void JSArrayBuffer::JSArrayBufferVerify() {
    795   CHECK(IsJSArrayBuffer());
    796   JSObjectVerify();
    797   VerifyPointer(byte_length());
    798   CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
    799         || byte_length()->IsUndefined());
    800 }
    801 
    802 
    803 void JSArrayBufferView::JSArrayBufferViewVerify() {
    804   CHECK(IsJSArrayBufferView());
    805   JSObjectVerify();
    806   VerifyPointer(buffer());
    807   CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined()
    808         || buffer() == Smi::FromInt(0));
    809 
    810   VerifyPointer(byte_offset());
    811   CHECK(byte_offset()->IsSmi() || byte_offset()->IsHeapNumber()
    812         || byte_offset()->IsUndefined());
    813 
    814   VerifyPointer(byte_length());
    815   CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
    816         || byte_length()->IsUndefined());
    817 }
    818 
    819 
    820 void JSTypedArray::JSTypedArrayVerify() {
    821   CHECK(IsJSTypedArray());
    822   JSArrayBufferViewVerify();
    823   VerifyPointer(length());
    824   CHECK(length()->IsSmi() || length()->IsHeapNumber()
    825         || length()->IsUndefined());
    826 
    827   VerifyPointer(elements());
    828 }
    829 
    830 
    831 void JSDataView::JSDataViewVerify() {
    832   CHECK(IsJSDataView());
    833   JSArrayBufferViewVerify();
    834 }
    835 
    836 
    837 void Foreign::ForeignVerify() {
    838   CHECK(IsForeign());
    839 }
    840 
    841 
    842 void Box::BoxVerify() {
    843   CHECK(IsBox());
    844   value()->ObjectVerify();
    845 }
    846 
    847 
    848 void AccessorInfo::AccessorInfoVerify() {
    849   VerifyPointer(name());
    850   VerifyPointer(flag());
    851   VerifyPointer(expected_receiver_type());
    852 }
    853 
    854 
    855 void ExecutableAccessorInfo::ExecutableAccessorInfoVerify() {
    856   CHECK(IsExecutableAccessorInfo());
    857   AccessorInfoVerify();
    858   VerifyPointer(getter());
    859   VerifyPointer(setter());
    860   VerifyPointer(data());
    861 }
    862 
    863 
    864 void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorVerify() {
    865   CHECK(IsDeclaredAccessorDescriptor());
    866   VerifyPointer(serialized_data());
    867 }
    868 
    869 
    870 void DeclaredAccessorInfo::DeclaredAccessorInfoVerify() {
    871   CHECK(IsDeclaredAccessorInfo());
    872   AccessorInfoVerify();
    873   VerifyPointer(descriptor());
    874 }
    875 
    876 
    877 void AccessorPair::AccessorPairVerify() {
    878   CHECK(IsAccessorPair());
    879   VerifyPointer(getter());
    880   VerifyPointer(setter());
    881   VerifySmiField(kAccessFlagsOffset);
    882 }
    883 
    884 
    885 void AccessCheckInfo::AccessCheckInfoVerify() {
    886   CHECK(IsAccessCheckInfo());
    887   VerifyPointer(named_callback());
    888   VerifyPointer(indexed_callback());
    889   VerifyPointer(data());
    890 }
    891 
    892 
    893 void InterceptorInfo::InterceptorInfoVerify() {
    894   CHECK(IsInterceptorInfo());
    895   VerifyPointer(getter());
    896   VerifyPointer(setter());
    897   VerifyPointer(query());
    898   VerifyPointer(deleter());
    899   VerifyPointer(enumerator());
    900   VerifyPointer(data());
    901 }
    902 
    903 
    904 void CallHandlerInfo::CallHandlerInfoVerify() {
    905   CHECK(IsCallHandlerInfo());
    906   VerifyPointer(callback());
    907   VerifyPointer(data());
    908 }
    909 
    910 
    911 void TemplateInfo::TemplateInfoVerify() {
    912   VerifyPointer(tag());
    913   VerifyPointer(property_list());
    914   VerifyPointer(property_accessors());
    915 }
    916 
    917 
    918 void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
    919   CHECK(IsFunctionTemplateInfo());
    920   TemplateInfoVerify();
    921   VerifyPointer(serial_number());
    922   VerifyPointer(call_code());
    923   VerifyPointer(prototype_template());
    924   VerifyPointer(parent_template());
    925   VerifyPointer(named_property_handler());
    926   VerifyPointer(indexed_property_handler());
    927   VerifyPointer(instance_template());
    928   VerifyPointer(signature());
    929   VerifyPointer(access_check_info());
    930 }
    931 
    932 
    933 void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
    934   CHECK(IsObjectTemplateInfo());
    935   TemplateInfoVerify();
    936   VerifyPointer(constructor());
    937   VerifyPointer(internal_field_count());
    938 }
    939 
    940 
    941 void SignatureInfo::SignatureInfoVerify() {
    942   CHECK(IsSignatureInfo());
    943   VerifyPointer(receiver());
    944   VerifyPointer(args());
    945 }
    946 
    947 
    948 void TypeSwitchInfo::TypeSwitchInfoVerify() {
    949   CHECK(IsTypeSwitchInfo());
    950   VerifyPointer(types());
    951 }
    952 
    953 
    954 void AllocationSite::AllocationSiteVerify() {
    955   CHECK(IsAllocationSite());
    956 }
    957 
    958 
    959 void AllocationMemento::AllocationMementoVerify() {
    960   CHECK(IsAllocationMemento());
    961   VerifyHeapPointer(allocation_site());
    962   CHECK(!IsValid() || GetAllocationSite()->IsAllocationSite());
    963 }
    964 
    965 
    966 void Script::ScriptVerify() {
    967   CHECK(IsScript());
    968   VerifyPointer(source());
    969   VerifyPointer(name());
    970   line_offset()->SmiVerify();
    971   column_offset()->SmiVerify();
    972   VerifyPointer(wrapper());
    973   type()->SmiVerify();
    974   VerifyPointer(line_ends());
    975   VerifyPointer(id());
    976 }
    977 
    978 
    979 void JSFunctionResultCache::JSFunctionResultCacheVerify() {
    980   JSFunction::cast(get(kFactoryIndex))->ObjectVerify();
    981 
    982   int size = Smi::cast(get(kCacheSizeIndex))->value();
    983   CHECK(kEntriesIndex <= size);
    984   CHECK(size <= length());
    985   CHECK_EQ(0, size % kEntrySize);
    986 
    987   int finger = Smi::cast(get(kFingerIndex))->value();
    988   CHECK(kEntriesIndex <= finger);
    989   CHECK((finger < size) || (finger == kEntriesIndex && finger == size));
    990   CHECK_EQ(0, finger % kEntrySize);
    991 
    992   if (FLAG_enable_slow_asserts) {
    993     for (int i = kEntriesIndex; i < size; i++) {
    994       CHECK(!get(i)->IsTheHole());
    995       get(i)->ObjectVerify();
    996     }
    997     for (int i = size; i < length(); i++) {
    998       CHECK(get(i)->IsTheHole());
    999       get(i)->ObjectVerify();
   1000     }
   1001   }
   1002 }
   1003 
   1004 
   1005 void NormalizedMapCache::NormalizedMapCacheVerify() {
   1006   FixedArray::cast(this)->FixedArrayVerify();
   1007   if (FLAG_enable_slow_asserts) {
   1008     for (int i = 0; i < length(); i++) {
   1009       Object* e = FixedArray::get(i);
   1010       if (e->IsMap()) {
   1011         Map::cast(e)->SharedMapVerify();
   1012       } else {
   1013         CHECK(e->IsUndefined());
   1014       }
   1015     }
   1016   }
   1017 }
   1018 
   1019 
   1020 void DebugInfo::DebugInfoVerify() {
   1021   CHECK(IsDebugInfo());
   1022   VerifyPointer(shared());
   1023   VerifyPointer(original_code());
   1024   VerifyPointer(code());
   1025   VerifyPointer(break_points());
   1026 }
   1027 
   1028 
   1029 void BreakPointInfo::BreakPointInfoVerify() {
   1030   CHECK(IsBreakPointInfo());
   1031   code_position()->SmiVerify();
   1032   source_position()->SmiVerify();
   1033   statement_position()->SmiVerify();
   1034   VerifyPointer(break_point_objects());
   1035 }
   1036 #endif  // VERIFY_HEAP
   1037 
   1038 #ifdef DEBUG
   1039 
   1040 void JSObject::IncrementSpillStatistics(SpillInformation* info) {
   1041   info->number_of_objects_++;
   1042   // Named properties
   1043   if (HasFastProperties()) {
   1044     info->number_of_objects_with_fast_properties_++;
   1045     info->number_of_fast_used_fields_   += map()->NextFreePropertyIndex();
   1046     info->number_of_fast_unused_fields_ += map()->unused_property_fields();
   1047   } else {
   1048     NameDictionary* dict = property_dictionary();
   1049     info->number_of_slow_used_properties_ += dict->NumberOfElements();
   1050     info->number_of_slow_unused_properties_ +=
   1051         dict->Capacity() - dict->NumberOfElements();
   1052   }
   1053   // Indexed properties
   1054   switch (GetElementsKind()) {
   1055     case FAST_HOLEY_SMI_ELEMENTS:
   1056     case FAST_SMI_ELEMENTS:
   1057     case FAST_HOLEY_DOUBLE_ELEMENTS:
   1058     case FAST_DOUBLE_ELEMENTS:
   1059     case FAST_HOLEY_ELEMENTS:
   1060     case FAST_ELEMENTS: {
   1061       info->number_of_objects_with_fast_elements_++;
   1062       int holes = 0;
   1063       FixedArray* e = FixedArray::cast(elements());
   1064       int len = e->length();
   1065       Heap* heap = GetHeap();
   1066       for (int i = 0; i < len; i++) {
   1067         if (e->get(i) == heap->the_hole_value()) holes++;
   1068       }
   1069       info->number_of_fast_used_elements_   += len - holes;
   1070       info->number_of_fast_unused_elements_ += holes;
   1071       break;
   1072     }
   1073 
   1074 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
   1075     case EXTERNAL_##TYPE##_ELEMENTS:                                          \
   1076     case TYPE##_ELEMENTS:
   1077 
   1078     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   1079 #undef TYPED_ARRAY_CASE
   1080     { info->number_of_objects_with_fast_elements_++;
   1081       FixedArrayBase* e = FixedArrayBase::cast(elements());
   1082       info->number_of_fast_used_elements_ += e->length();
   1083       break;
   1084     }
   1085     case DICTIONARY_ELEMENTS: {
   1086       SeededNumberDictionary* dict = element_dictionary();
   1087       info->number_of_slow_used_elements_ += dict->NumberOfElements();
   1088       info->number_of_slow_unused_elements_ +=
   1089           dict->Capacity() - dict->NumberOfElements();
   1090       break;
   1091     }
   1092     case SLOPPY_ARGUMENTS_ELEMENTS:
   1093       break;
   1094   }
   1095 }
   1096 
   1097 
   1098 void JSObject::SpillInformation::Clear() {
   1099   number_of_objects_ = 0;
   1100   number_of_objects_with_fast_properties_ = 0;
   1101   number_of_objects_with_fast_elements_ = 0;
   1102   number_of_fast_used_fields_ = 0;
   1103   number_of_fast_unused_fields_ = 0;
   1104   number_of_slow_used_properties_ = 0;
   1105   number_of_slow_unused_properties_ = 0;
   1106   number_of_fast_used_elements_ = 0;
   1107   number_of_fast_unused_elements_ = 0;
   1108   number_of_slow_used_elements_ = 0;
   1109   number_of_slow_unused_elements_ = 0;
   1110 }
   1111 
   1112 
   1113 void JSObject::SpillInformation::Print() {
   1114   PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);
   1115 
   1116   PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
   1117          number_of_objects_with_fast_properties_,
   1118          number_of_fast_used_fields_, number_of_fast_unused_fields_);
   1119 
   1120   PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
   1121          number_of_objects_ - number_of_objects_with_fast_properties_,
   1122          number_of_slow_used_properties_, number_of_slow_unused_properties_);
   1123 
   1124   PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
   1125          number_of_objects_with_fast_elements_,
   1126          number_of_fast_used_elements_, number_of_fast_unused_elements_);
   1127 
   1128   PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
   1129          number_of_objects_ - number_of_objects_with_fast_elements_,
   1130          number_of_slow_used_elements_, number_of_slow_unused_elements_);
   1131 
   1132   PrintF("\n");
   1133 }
   1134 
   1135 
   1136 bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) {
   1137   if (valid_entries == -1) valid_entries = number_of_descriptors();
   1138   Name* current_key = NULL;
   1139   uint32_t current = 0;
   1140   for (int i = 0; i < number_of_descriptors(); i++) {
   1141     Name* key = GetSortedKey(i);
   1142     if (key == current_key) {
   1143       PrintDescriptors();
   1144       return false;
   1145     }
   1146     current_key = key;
   1147     uint32_t hash = GetSortedKey(i)->Hash();
   1148     if (hash < current) {
   1149       PrintDescriptors();
   1150       return false;
   1151     }
   1152     current = hash;
   1153   }
   1154   return true;
   1155 }
   1156 
   1157 
   1158 bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
   1159   ASSERT(valid_entries == -1);
   1160   Name* current_key = NULL;
   1161   uint32_t current = 0;
   1162   for (int i = 0; i < number_of_transitions(); i++) {
   1163     Name* key = GetSortedKey(i);
   1164     if (key == current_key) {
   1165       PrintTransitions();
   1166       return false;
   1167     }
   1168     current_key = key;
   1169     uint32_t hash = GetSortedKey(i)->Hash();
   1170     if (hash < current) {
   1171       PrintTransitions();
   1172       return false;
   1173     }
   1174     current = hash;
   1175   }
   1176   return true;
   1177 }
   1178 
   1179 
   1180 static bool CheckOneBackPointer(Map* current_map, Object* target) {
   1181   return !target->IsMap() || Map::cast(target)->GetBackPointer() == current_map;
   1182 }
   1183 
   1184 
   1185 bool TransitionArray::IsConsistentWithBackPointers(Map* current_map) {
   1186   for (int i = 0; i < number_of_transitions(); ++i) {
   1187     if (!CheckOneBackPointer(current_map, GetTarget(i))) return false;
   1188   }
   1189   return true;
   1190 }
   1191 
   1192 
   1193 #endif  // DEBUG
   1194 
   1195 } }  // namespace v8::internal
   1196