Home | History | Annotate | Download | only in src
      1 // Copyright 2010 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include "v8.h"
     29 
     30 #include "disassembler.h"
     31 #include "disasm.h"
     32 #include "jsregexp.h"
     33 #include "objects-visiting.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 #ifdef DEBUG
     39 
     40 void MaybeObject::Verify() {
     41   Object* this_as_object;
     42   if (ToObject(&this_as_object)) {
     43     if (this_as_object->IsSmi()) {
     44       Smi::cast(this_as_object)->SmiVerify();
     45     } else {
     46       HeapObject::cast(this_as_object)->HeapObjectVerify();
     47     }
     48   } else {
     49     Failure::cast(this)->FailureVerify();
     50   }
     51 }
     52 
     53 
     54 void Object::VerifyPointer(Object* p) {
     55   if (p->IsHeapObject()) {
     56     HeapObject::VerifyHeapPointer(p);
     57   } else {
     58     ASSERT(p->IsSmi());
     59   }
     60 }
     61 
     62 
     63 void Smi::SmiVerify() {
     64   ASSERT(IsSmi());
     65 }
     66 
     67 
     68 void Failure::FailureVerify() {
     69   ASSERT(IsFailure());
     70 }
     71 
     72 
     73 void HeapObject::HeapObjectVerify() {
     74   InstanceType instance_type = map()->instance_type();
     75 
     76   if (instance_type < FIRST_NONSTRING_TYPE) {
     77     String::cast(this)->StringVerify();
     78     return;
     79   }
     80 
     81   switch (instance_type) {
     82     case MAP_TYPE:
     83       Map::cast(this)->MapVerify();
     84       break;
     85     case HEAP_NUMBER_TYPE:
     86       HeapNumber::cast(this)->HeapNumberVerify();
     87       break;
     88     case FIXED_ARRAY_TYPE:
     89       FixedArray::cast(this)->FixedArrayVerify();
     90       break;
     91     case BYTE_ARRAY_TYPE:
     92       ByteArray::cast(this)->ByteArrayVerify();
     93       break;
     94     case EXTERNAL_PIXEL_ARRAY_TYPE:
     95       ExternalPixelArray::cast(this)->ExternalPixelArrayVerify();
     96       break;
     97     case EXTERNAL_BYTE_ARRAY_TYPE:
     98       ExternalByteArray::cast(this)->ExternalByteArrayVerify();
     99       break;
    100     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
    101       ExternalUnsignedByteArray::cast(this)->ExternalUnsignedByteArrayVerify();
    102       break;
    103     case EXTERNAL_SHORT_ARRAY_TYPE:
    104       ExternalShortArray::cast(this)->ExternalShortArrayVerify();
    105       break;
    106     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
    107       ExternalUnsignedShortArray::cast(this)->
    108           ExternalUnsignedShortArrayVerify();
    109       break;
    110     case EXTERNAL_INT_ARRAY_TYPE:
    111       ExternalIntArray::cast(this)->ExternalIntArrayVerify();
    112       break;
    113     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
    114       ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayVerify();
    115       break;
    116     case EXTERNAL_FLOAT_ARRAY_TYPE:
    117       ExternalFloatArray::cast(this)->ExternalFloatArrayVerify();
    118       break;
    119     case CODE_TYPE:
    120       Code::cast(this)->CodeVerify();
    121       break;
    122     case ODDBALL_TYPE:
    123       Oddball::cast(this)->OddballVerify();
    124       break;
    125     case JS_OBJECT_TYPE:
    126     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    127       JSObject::cast(this)->JSObjectVerify();
    128       break;
    129     case JS_VALUE_TYPE:
    130       JSValue::cast(this)->JSValueVerify();
    131       break;
    132     case JS_FUNCTION_TYPE:
    133       JSFunction::cast(this)->JSFunctionVerify();
    134       break;
    135     case JS_GLOBAL_PROXY_TYPE:
    136       JSGlobalProxy::cast(this)->JSGlobalProxyVerify();
    137       break;
    138     case JS_GLOBAL_OBJECT_TYPE:
    139       JSGlobalObject::cast(this)->JSGlobalObjectVerify();
    140       break;
    141     case JS_BUILTINS_OBJECT_TYPE:
    142       JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
    143       break;
    144     case JS_GLOBAL_PROPERTY_CELL_TYPE:
    145       JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellVerify();
    146       break;
    147     case JS_ARRAY_TYPE:
    148       JSArray::cast(this)->JSArrayVerify();
    149       break;
    150     case JS_REGEXP_TYPE:
    151       JSRegExp::cast(this)->JSRegExpVerify();
    152       break;
    153     case FILLER_TYPE:
    154       break;
    155     case PROXY_TYPE:
    156       Proxy::cast(this)->ProxyVerify();
    157       break;
    158     case SHARED_FUNCTION_INFO_TYPE:
    159       SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
    160       break;
    161     case JS_MESSAGE_OBJECT_TYPE:
    162       JSMessageObject::cast(this)->JSMessageObjectVerify();
    163       break;
    164 
    165 #define MAKE_STRUCT_CASE(NAME, Name, name) \
    166   case NAME##_TYPE:                        \
    167     Name::cast(this)->Name##Verify();      \
    168     break;
    169     STRUCT_LIST(MAKE_STRUCT_CASE)
    170 #undef MAKE_STRUCT_CASE
    171 
    172     default:
    173       UNREACHABLE();
    174       break;
    175   }
    176 }
    177 
    178 
    179 void HeapObject::VerifyHeapPointer(Object* p) {
    180   ASSERT(p->IsHeapObject());
    181   ASSERT(HEAP->Contains(HeapObject::cast(p)));
    182 }
    183 
    184 
    185 void HeapNumber::HeapNumberVerify() {
    186   ASSERT(IsHeapNumber());
    187 }
    188 
    189 
    190 void ByteArray::ByteArrayVerify() {
    191   ASSERT(IsByteArray());
    192 }
    193 
    194 
    195 void ExternalPixelArray::ExternalPixelArrayVerify() {
    196   ASSERT(IsExternalPixelArray());
    197 }
    198 
    199 
    200 void ExternalByteArray::ExternalByteArrayVerify() {
    201   ASSERT(IsExternalByteArray());
    202 }
    203 
    204 
    205 void ExternalUnsignedByteArray::ExternalUnsignedByteArrayVerify() {
    206   ASSERT(IsExternalUnsignedByteArray());
    207 }
    208 
    209 
    210 void ExternalShortArray::ExternalShortArrayVerify() {
    211   ASSERT(IsExternalShortArray());
    212 }
    213 
    214 
    215 void ExternalUnsignedShortArray::ExternalUnsignedShortArrayVerify() {
    216   ASSERT(IsExternalUnsignedShortArray());
    217 }
    218 
    219 
    220 void ExternalIntArray::ExternalIntArrayVerify() {
    221   ASSERT(IsExternalIntArray());
    222 }
    223 
    224 
    225 void ExternalUnsignedIntArray::ExternalUnsignedIntArrayVerify() {
    226   ASSERT(IsExternalUnsignedIntArray());
    227 }
    228 
    229 
    230 void ExternalFloatArray::ExternalFloatArrayVerify() {
    231   ASSERT(IsExternalFloatArray());
    232 }
    233 
    234 
    235 void JSObject::JSObjectVerify() {
    236   VerifyHeapPointer(properties());
    237   VerifyHeapPointer(elements());
    238   if (HasFastProperties()) {
    239     CHECK_EQ(map()->unused_property_fields(),
    240              (map()->inobject_properties() + properties()->length() -
    241               map()->NextFreePropertyIndex()));
    242   }
    243   ASSERT(map()->has_fast_elements() ==
    244          (elements()->map() == GetHeap()->fixed_array_map() ||
    245           elements()->map() == GetHeap()->fixed_cow_array_map()));
    246   ASSERT(map()->has_fast_elements() == HasFastElements());
    247 }
    248 
    249 
    250 void Map::MapVerify() {
    251   ASSERT(!HEAP->InNewSpace(this));
    252   ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
    253   ASSERT(instance_size() == kVariableSizeSentinel ||
    254          (kPointerSize <= instance_size() &&
    255           instance_size() < HEAP->Capacity()));
    256   VerifyHeapPointer(prototype());
    257   VerifyHeapPointer(instance_descriptors());
    258 }
    259 
    260 
    261 void Map::SharedMapVerify() {
    262   MapVerify();
    263   ASSERT(is_shared());
    264   ASSERT_EQ(GetHeap()->empty_descriptor_array(), instance_descriptors());
    265   ASSERT_EQ(0, pre_allocated_property_fields());
    266   ASSERT_EQ(0, unused_property_fields());
    267   ASSERT_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
    268       visitor_id());
    269 }
    270 
    271 
    272 void CodeCache::CodeCacheVerify() {
    273   VerifyHeapPointer(default_cache());
    274   VerifyHeapPointer(normal_type_cache());
    275   ASSERT(default_cache()->IsFixedArray());
    276   ASSERT(normal_type_cache()->IsUndefined()
    277          || normal_type_cache()->IsCodeCacheHashTable());
    278 }
    279 
    280 
    281 void FixedArray::FixedArrayVerify() {
    282   for (int i = 0; i < length(); i++) {
    283     Object* e = get(i);
    284     if (e->IsHeapObject()) {
    285       VerifyHeapPointer(e);
    286     } else {
    287       e->Verify();
    288     }
    289   }
    290 }
    291 
    292 
    293 void JSValue::JSValueVerify() {
    294   Object* v = value();
    295   if (v->IsHeapObject()) {
    296     VerifyHeapPointer(v);
    297   }
    298 }
    299 
    300 
    301 void JSMessageObject::JSMessageObjectVerify() {
    302   CHECK(IsJSMessageObject());
    303   CHECK(type()->IsString());
    304   CHECK(arguments()->IsJSArray());
    305   VerifyObjectField(kStartPositionOffset);
    306   VerifyObjectField(kEndPositionOffset);
    307   VerifyObjectField(kArgumentsOffset);
    308   VerifyObjectField(kScriptOffset);
    309   VerifyObjectField(kStackTraceOffset);
    310   VerifyObjectField(kStackFramesOffset);
    311 }
    312 
    313 
    314 void String::StringVerify() {
    315   CHECK(IsString());
    316   CHECK(length() >= 0 && length() <= Smi::kMaxValue);
    317   if (IsSymbol()) {
    318     CHECK(!HEAP->InNewSpace(this));
    319   }
    320 }
    321 
    322 
    323 void JSFunction::JSFunctionVerify() {
    324   CHECK(IsJSFunction());
    325   VerifyObjectField(kPrototypeOrInitialMapOffset);
    326   VerifyObjectField(kNextFunctionLinkOffset);
    327   CHECK(next_function_link()->IsUndefined() ||
    328         next_function_link()->IsJSFunction());
    329 }
    330 
    331 
    332 void SharedFunctionInfo::SharedFunctionInfoVerify() {
    333   CHECK(IsSharedFunctionInfo());
    334   VerifyObjectField(kNameOffset);
    335   VerifyObjectField(kCodeOffset);
    336   VerifyObjectField(kScopeInfoOffset);
    337   VerifyObjectField(kInstanceClassNameOffset);
    338   VerifyObjectField(kFunctionDataOffset);
    339   VerifyObjectField(kScriptOffset);
    340   VerifyObjectField(kDebugInfoOffset);
    341 }
    342 
    343 
    344 void JSGlobalProxy::JSGlobalProxyVerify() {
    345   CHECK(IsJSGlobalProxy());
    346   JSObjectVerify();
    347   VerifyObjectField(JSGlobalProxy::kContextOffset);
    348   // Make sure that this object has no properties, elements.
    349   CHECK_EQ(0, properties()->length());
    350   CHECK(HasFastElements());
    351   CHECK_EQ(0, FixedArray::cast(elements())->length());
    352 }
    353 
    354 
    355 void JSGlobalObject::JSGlobalObjectVerify() {
    356   CHECK(IsJSGlobalObject());
    357   JSObjectVerify();
    358   for (int i = GlobalObject::kBuiltinsOffset;
    359        i < JSGlobalObject::kSize;
    360        i += kPointerSize) {
    361     VerifyObjectField(i);
    362   }
    363 }
    364 
    365 
    366 void JSBuiltinsObject::JSBuiltinsObjectVerify() {
    367   CHECK(IsJSBuiltinsObject());
    368   JSObjectVerify();
    369   for (int i = GlobalObject::kBuiltinsOffset;
    370        i < JSBuiltinsObject::kSize;
    371        i += kPointerSize) {
    372     VerifyObjectField(i);
    373   }
    374 }
    375 
    376 
    377 void Oddball::OddballVerify() {
    378   CHECK(IsOddball());
    379   VerifyHeapPointer(to_string());
    380   Object* number = to_number();
    381   if (number->IsHeapObject()) {
    382     ASSERT(number == HEAP->nan_value());
    383   } else {
    384     ASSERT(number->IsSmi());
    385     int value = Smi::cast(number)->value();
    386     // Hidden oddballs have negative smis.
    387     const int kLeastHiddenOddballNumber = -4;
    388     ASSERT(value <= 1);
    389     ASSERT(value >= kLeastHiddenOddballNumber);
    390   }
    391 }
    392 
    393 
    394 void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() {
    395   CHECK(IsJSGlobalPropertyCell());
    396   VerifyObjectField(kValueOffset);
    397 }
    398 
    399 
    400 void Code::CodeVerify() {
    401   CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
    402                   kCodeAlignment));
    403   Address last_gc_pc = NULL;
    404   for (RelocIterator it(this); !it.done(); it.next()) {
    405     it.rinfo()->Verify();
    406     // Ensure that GC will not iterate twice over the same pointer.
    407     if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
    408       CHECK(it.rinfo()->pc() != last_gc_pc);
    409       last_gc_pc = it.rinfo()->pc();
    410     }
    411   }
    412 }
    413 
    414 
    415 void JSArray::JSArrayVerify() {
    416   JSObjectVerify();
    417   ASSERT(length()->IsNumber() || length()->IsUndefined());
    418   ASSERT(elements()->IsUndefined() || elements()->IsFixedArray());
    419 }
    420 
    421 
    422 void JSRegExp::JSRegExpVerify() {
    423   JSObjectVerify();
    424   ASSERT(data()->IsUndefined() || data()->IsFixedArray());
    425   switch (TypeTag()) {
    426     case JSRegExp::ATOM: {
    427       FixedArray* arr = FixedArray::cast(data());
    428       ASSERT(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
    429       break;
    430     }
    431     case JSRegExp::IRREGEXP: {
    432       bool is_native = RegExpImpl::UsesNativeRegExp();
    433 
    434       FixedArray* arr = FixedArray::cast(data());
    435       Object* ascii_data = arr->get(JSRegExp::kIrregexpASCIICodeIndex);
    436       // TheHole : Not compiled yet.
    437       // JSObject: Compilation error.
    438       // Code/ByteArray: Compiled code.
    439       ASSERT(ascii_data->IsTheHole() || ascii_data->IsJSObject() ||
    440           (is_native ? ascii_data->IsCode() : ascii_data->IsByteArray()));
    441       Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex);
    442       ASSERT(uc16_data->IsTheHole() || uc16_data->IsJSObject() ||
    443           (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray()));
    444       ASSERT(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi());
    445       ASSERT(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi());
    446       break;
    447     }
    448     default:
    449       ASSERT_EQ(JSRegExp::NOT_COMPILED, TypeTag());
    450       ASSERT(data()->IsUndefined());
    451       break;
    452   }
    453 }
    454 
    455 
    456 void Proxy::ProxyVerify() {
    457   ASSERT(IsProxy());
    458 }
    459 
    460 
    461 void AccessorInfo::AccessorInfoVerify() {
    462   CHECK(IsAccessorInfo());
    463   VerifyPointer(getter());
    464   VerifyPointer(setter());
    465   VerifyPointer(name());
    466   VerifyPointer(data());
    467   VerifyPointer(flag());
    468 }
    469 
    470 
    471 void AccessCheckInfo::AccessCheckInfoVerify() {
    472   CHECK(IsAccessCheckInfo());
    473   VerifyPointer(named_callback());
    474   VerifyPointer(indexed_callback());
    475   VerifyPointer(data());
    476 }
    477 
    478 
    479 void InterceptorInfo::InterceptorInfoVerify() {
    480   CHECK(IsInterceptorInfo());
    481   VerifyPointer(getter());
    482   VerifyPointer(setter());
    483   VerifyPointer(query());
    484   VerifyPointer(deleter());
    485   VerifyPointer(enumerator());
    486   VerifyPointer(data());
    487 }
    488 
    489 
    490 void CallHandlerInfo::CallHandlerInfoVerify() {
    491   CHECK(IsCallHandlerInfo());
    492   VerifyPointer(callback());
    493   VerifyPointer(data());
    494 }
    495 
    496 
    497 void TemplateInfo::TemplateInfoVerify() {
    498   VerifyPointer(tag());
    499   VerifyPointer(property_list());
    500 }
    501 
    502 void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
    503   CHECK(IsFunctionTemplateInfo());
    504   TemplateInfoVerify();
    505   VerifyPointer(serial_number());
    506   VerifyPointer(call_code());
    507   VerifyPointer(property_accessors());
    508   VerifyPointer(prototype_template());
    509   VerifyPointer(parent_template());
    510   VerifyPointer(named_property_handler());
    511   VerifyPointer(indexed_property_handler());
    512   VerifyPointer(instance_template());
    513   VerifyPointer(signature());
    514   VerifyPointer(access_check_info());
    515 }
    516 
    517 
    518 void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
    519   CHECK(IsObjectTemplateInfo());
    520   TemplateInfoVerify();
    521   VerifyPointer(constructor());
    522   VerifyPointer(internal_field_count());
    523 }
    524 
    525 
    526 void SignatureInfo::SignatureInfoVerify() {
    527   CHECK(IsSignatureInfo());
    528   VerifyPointer(receiver());
    529   VerifyPointer(args());
    530 }
    531 
    532 
    533 void TypeSwitchInfo::TypeSwitchInfoVerify() {
    534   CHECK(IsTypeSwitchInfo());
    535   VerifyPointer(types());
    536 }
    537 
    538 
    539 void Script::ScriptVerify() {
    540   CHECK(IsScript());
    541   VerifyPointer(source());
    542   VerifyPointer(name());
    543   line_offset()->SmiVerify();
    544   column_offset()->SmiVerify();
    545   VerifyPointer(data());
    546   VerifyPointer(wrapper());
    547   type()->SmiVerify();
    548   VerifyPointer(line_ends());
    549   VerifyPointer(id());
    550 }
    551 
    552 
    553 #ifdef ENABLE_DEBUGGER_SUPPORT
    554 void DebugInfo::DebugInfoVerify() {
    555   CHECK(IsDebugInfo());
    556   VerifyPointer(shared());
    557   VerifyPointer(original_code());
    558   VerifyPointer(code());
    559   VerifyPointer(break_points());
    560 }
    561 
    562 
    563 void BreakPointInfo::BreakPointInfoVerify() {
    564   CHECK(IsBreakPointInfo());
    565   code_position()->SmiVerify();
    566   source_position()->SmiVerify();
    567   statement_position()->SmiVerify();
    568   VerifyPointer(break_point_objects());
    569 }
    570 #endif  // ENABLE_DEBUGGER_SUPPORT
    571 
    572 
    573 void JSObject::IncrementSpillStatistics(SpillInformation* info) {
    574   info->number_of_objects_++;
    575   // Named properties
    576   if (HasFastProperties()) {
    577     info->number_of_objects_with_fast_properties_++;
    578     info->number_of_fast_used_fields_   += map()->NextFreePropertyIndex();
    579     info->number_of_fast_unused_fields_ += map()->unused_property_fields();
    580   } else {
    581     StringDictionary* dict = property_dictionary();
    582     info->number_of_slow_used_properties_ += dict->NumberOfElements();
    583     info->number_of_slow_unused_properties_ +=
    584         dict->Capacity() - dict->NumberOfElements();
    585   }
    586   // Indexed properties
    587   switch (GetElementsKind()) {
    588     case FAST_ELEMENTS: {
    589       info->number_of_objects_with_fast_elements_++;
    590       int holes = 0;
    591       FixedArray* e = FixedArray::cast(elements());
    592       int len = e->length();
    593       Heap* heap = HEAP;
    594       for (int i = 0; i < len; i++) {
    595         if (e->get(i) == heap->the_hole_value()) holes++;
    596       }
    597       info->number_of_fast_used_elements_   += len - holes;
    598       info->number_of_fast_unused_elements_ += holes;
    599       break;
    600     }
    601     case EXTERNAL_PIXEL_ELEMENTS: {
    602       info->number_of_objects_with_fast_elements_++;
    603       ExternalPixelArray* e = ExternalPixelArray::cast(elements());
    604       info->number_of_fast_used_elements_ += e->length();
    605       break;
    606     }
    607     case DICTIONARY_ELEMENTS: {
    608       NumberDictionary* dict = element_dictionary();
    609       info->number_of_slow_used_elements_ += dict->NumberOfElements();
    610       info->number_of_slow_unused_elements_ +=
    611           dict->Capacity() - dict->NumberOfElements();
    612       break;
    613     }
    614     default:
    615       UNREACHABLE();
    616       break;
    617   }
    618 }
    619 
    620 
    621 void JSObject::SpillInformation::Clear() {
    622   number_of_objects_ = 0;
    623   number_of_objects_with_fast_properties_ = 0;
    624   number_of_objects_with_fast_elements_ = 0;
    625   number_of_fast_used_fields_ = 0;
    626   number_of_fast_unused_fields_ = 0;
    627   number_of_slow_used_properties_ = 0;
    628   number_of_slow_unused_properties_ = 0;
    629   number_of_fast_used_elements_ = 0;
    630   number_of_fast_unused_elements_ = 0;
    631   number_of_slow_used_elements_ = 0;
    632   number_of_slow_unused_elements_ = 0;
    633 }
    634 
    635 void JSObject::SpillInformation::Print() {
    636   PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);
    637 
    638   PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
    639          number_of_objects_with_fast_properties_,
    640          number_of_fast_used_fields_, number_of_fast_unused_fields_);
    641 
    642   PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
    643          number_of_objects_ - number_of_objects_with_fast_properties_,
    644          number_of_slow_used_properties_, number_of_slow_unused_properties_);
    645 
    646   PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
    647          number_of_objects_with_fast_elements_,
    648          number_of_fast_used_elements_, number_of_fast_unused_elements_);
    649 
    650   PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
    651          number_of_objects_ - number_of_objects_with_fast_elements_,
    652          number_of_slow_used_elements_, number_of_slow_unused_elements_);
    653 
    654   PrintF("\n");
    655 }
    656 
    657 
    658 bool DescriptorArray::IsSortedNoDuplicates() {
    659   String* current_key = NULL;
    660   uint32_t current = 0;
    661   for (int i = 0; i < number_of_descriptors(); i++) {
    662     String* key = GetKey(i);
    663     if (key == current_key) {
    664       PrintDescriptors();
    665       return false;
    666     }
    667     current_key = key;
    668     uint32_t hash = GetKey(i)->Hash();
    669     if (hash < current) {
    670       PrintDescriptors();
    671       return false;
    672     }
    673     current = hash;
    674   }
    675   return true;
    676 }
    677 
    678 
    679 void JSFunctionResultCache::JSFunctionResultCacheVerify() {
    680   JSFunction::cast(get(kFactoryIndex))->Verify();
    681 
    682   int size = Smi::cast(get(kCacheSizeIndex))->value();
    683   ASSERT(kEntriesIndex <= size);
    684   ASSERT(size <= length());
    685   ASSERT_EQ(0, size % kEntrySize);
    686 
    687   int finger = Smi::cast(get(kFingerIndex))->value();
    688   ASSERT(kEntriesIndex <= finger);
    689   ASSERT((finger < size) || (finger == kEntriesIndex && finger == size));
    690   ASSERT_EQ(0, finger % kEntrySize);
    691 
    692   if (FLAG_enable_slow_asserts) {
    693     for (int i = kEntriesIndex; i < size; i++) {
    694       ASSERT(!get(i)->IsTheHole());
    695       get(i)->Verify();
    696     }
    697     for (int i = size; i < length(); i++) {
    698       ASSERT(get(i)->IsTheHole());
    699       get(i)->Verify();
    700     }
    701   }
    702 }
    703 
    704 
    705 void NormalizedMapCache::NormalizedMapCacheVerify() {
    706   FixedArray::cast(this)->Verify();
    707   if (FLAG_enable_slow_asserts) {
    708     for (int i = 0; i < length(); i++) {
    709       Object* e = get(i);
    710       if (e->IsMap()) {
    711         Map::cast(e)->SharedMapVerify();
    712       } else {
    713         ASSERT(e->IsUndefined());
    714       }
    715     }
    716   }
    717 }
    718 
    719 
    720 #endif  // DEBUG
    721 
    722 } }  // namespace v8::internal
    723