| Index: src/objects-debug.cc | 
| diff --git a/src/objects-debug.cc b/src/objects-debug.cc | 
| index 13342ca36a405b187a862c54dca11a972d085f9e..fff4f3091c05f9e9c05af37a0abbd1d4d79aa0c7 100644 | 
| --- a/src/objects-debug.cc | 
| +++ b/src/objects-debug.cc | 
| @@ -100,13 +100,15 @@ void HeapObject::HeapObjectVerify() { | 
| break; | 
| case JS_OBJECT_TYPE: | 
| case JS_ERROR_TYPE: | 
| -    case JS_ARGUMENTS_TYPE: | 
| case JS_API_OBJECT_TYPE: | 
| case JS_SPECIAL_API_OBJECT_TYPE: | 
| case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 
| case JS_PROMISE_TYPE: | 
| JSObject::cast(this)->JSObjectVerify(); | 
| break; | 
| +    case JS_ARGUMENTS_TYPE: | 
| +      JSArgumentsObject::cast(this)->JSArgumentsObjectVerify(); | 
| +      break; | 
| case JS_GENERATOR_OBJECT_TYPE: | 
| JSGeneratorObject::cast(this)->JSGeneratorObjectVerify(); | 
| break; | 
| @@ -246,9 +248,9 @@ void FreeSpace::FreeSpaceVerify() { | 
|  | 
| template <class Traits> | 
| void FixedTypedArray<Traits>::FixedTypedArrayVerify() { | 
| -  CHECK(IsHeapObject() && | 
| -        HeapObject::cast(this)->map()->instance_type() == | 
| -            Traits::kInstanceType); | 
| +  CHECK(IsHeapObject()); | 
| +  CHECK(HeapObject::cast(this)->map()->instance_type() == | 
| +        Traits::kInstanceType); | 
| if (base_pointer() == this) { | 
| CHECK(external_pointer() == | 
| ExternalReference::fixed_typed_array_base_data_offset().address()); | 
| @@ -265,76 +267,166 @@ bool JSObject::ElementsAreSafeToExamine() { | 
| GetHeap()->one_pointer_filler_map(); | 
| } | 
|  | 
| - | 
| -void JSObject::JSObjectVerify() { | 
| -  VerifyHeapPointer(properties()); | 
| -  VerifyHeapPointer(elements()); | 
| - | 
| -  if (HasSloppyArgumentsElements()) { | 
| -    CHECK(this->elements()->IsFixedArray()); | 
| -    CHECK_GE(this->elements()->length(), 2); | 
| +namespace { | 
| + | 
| +void VerifyFastProperties(JSReceiver* receiver) { | 
| +  // TODO(cbruni): JSProxy support for slow properties | 
| +  if (!receiver->IsJSObject()) return; | 
| +  Isolate* isolate = receiver->GetIsolate(); | 
| +  Map* map = receiver->map(); | 
| +  CHECK(!map->is_dictionary_map()); | 
| +  JSObject* obj = JSObject::cast(receiver); | 
| +  int actual_unused_property_fields = map->GetInObjectProperties() + | 
| +                                      obj->properties()->length() - | 
| +                                      map->NextFreePropertyIndex(); | 
| +  if (map->unused_property_fields() != actual_unused_property_fields) { | 
| +    // This could actually happen in the middle of StoreTransitionStub | 
| +    // when the new extended backing store is already set into the object and | 
| +    // the allocation of the MutableHeapNumber triggers GC (in this case map | 
| +    // is not updated yet). | 
| +    CHECK_EQ(map->unused_property_fields(), | 
| +             actual_unused_property_fields - JSObject::kFieldsAdded); | 
| } | 
| - | 
| -  if (HasFastProperties()) { | 
| -    int actual_unused_property_fields = map()->GetInObjectProperties() + | 
| -                                        properties()->length() - | 
| -                                        map()->NextFreePropertyIndex(); | 
| -    if (map()->unused_property_fields() != actual_unused_property_fields) { | 
| -      // This could actually happen in the middle of StoreTransitionStub | 
| -      // when the new extended backing store is already set into the object and | 
| -      // the allocation of the MutableHeapNumber triggers GC (in this case map | 
| -      // is not updated yet). | 
| -      CHECK_EQ(map()->unused_property_fields(), | 
| -               actual_unused_property_fields - JSObject::kFieldsAdded); | 
| +  DescriptorArray* descriptors = map->instance_descriptors(); | 
| +  for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | 
| +    if (descriptors->GetDetails(i).type() != DATA) continue; | 
| +    Representation r = descriptors->GetDetails(i).representation(); | 
| +    FieldIndex index = FieldIndex::ForDescriptor(map, i); | 
| +    if (obj->IsUnboxedDoubleField(index)) { | 
| +      DCHECK(r.IsDouble()); | 
| +      continue; | 
| } | 
| -    DescriptorArray* descriptors = map()->instance_descriptors(); | 
| -    Isolate* isolate = GetIsolate(); | 
| -    for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) { | 
| -      if (descriptors->GetDetails(i).type() == DATA) { | 
| -        Representation r = descriptors->GetDetails(i).representation(); | 
| -        FieldIndex index = FieldIndex::ForDescriptor(map(), i); | 
| -        if (IsUnboxedDoubleField(index)) { | 
| -          DCHECK(r.IsDouble()); | 
| -          continue; | 
| -        } | 
| -        Object* value = RawFastPropertyAt(index); | 
| -        if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber()); | 
| -        if (value->IsUninitialized(isolate)) continue; | 
| -        if (r.IsSmi()) DCHECK(value->IsSmi()); | 
| -        if (r.IsHeapObject()) DCHECK(value->IsHeapObject()); | 
| -        FieldType* field_type = descriptors->GetFieldType(i); | 
| -        bool type_is_none = field_type->IsNone(); | 
| -        bool type_is_any = field_type->IsAny(); | 
| -        if (r.IsNone()) { | 
| -          CHECK(type_is_none); | 
| -        } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) { | 
| -          // If allocation folding is off then GC could happen during inner | 
| -          // object literal creation and we will end up having and undefined | 
| -          // value that does not match the field type. | 
| -          CHECK(!field_type->NowStable() || field_type->NowContains(value) || | 
| -                (!FLAG_use_allocation_folding && value->IsUndefined(isolate))); | 
| -        } | 
| -      } | 
| +    Object* value = obj->RawFastPropertyAt(index); | 
| +    if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber()); | 
| +    if (value->IsUninitialized(isolate)) continue; | 
| +    if (r.IsSmi()) DCHECK(value->IsSmi()); | 
| +    if (r.IsHeapObject()) DCHECK(value->IsHeapObject()); | 
| +    FieldType* field_type = descriptors->GetFieldType(i); | 
| +    bool type_is_none = field_type->IsNone(); | 
| +    bool type_is_any = field_type->IsAny(); | 
| +    if (r.IsNone()) { | 
| +      CHECK(type_is_none); | 
| +    } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) { | 
| +      // If allocation folding is off then GC could happen during inner | 
| +      // object literal creation and we will end up having and undefined | 
| +      // value that does not match the field type. | 
| +      CHECK(!field_type->NowStable() || field_type->NowContains(value) || | 
| +            (!FLAG_use_allocation_folding && value->IsUndefined(isolate))); | 
| } | 
| } | 
| +} | 
|  | 
| +template <typename T> | 
| +void VerifyDictionary(T* dict) { | 
| +  CHECK(dict->IsFixedArray()); | 
| +  CHECK(dict->IsDictionary()); | 
| +  int capacity = dict->Capacity(); | 
| +  int nof = dict->NumberOfElements(); | 
| +  int nod = dict->NumberOfDeletedElements(); | 
| +  CHECK_LE(capacity, dict->length()); | 
| +  CHECK_LE(nof, capacity); | 
| +  CHECK_LE(0, nof + nod); | 
| +  CHECK_LE(nof + nod, capacity); | 
| +} | 
| + | 
| +void VerifySlowProperties(JSReceiver* obj) { | 
| +  Map* map = obj->map(); | 
| +  CHECK(map->is_dictionary_map()); | 
| +  CHECK_EQ(0, map->NumberOfOwnDescriptors()); | 
| +  CHECK_EQ(0, map->unused_property_fields()); | 
| +  CHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength()); | 
| +  CHECK(obj->properties()->IsDictionary()); | 
| +  // Kept in-object properties for sow-mode object need to be zapped: | 
| +  int nof_in_object_properties = map->GetInObjectProperties(); | 
| +  if (nof_in_object_properties > 0) { | 
| +    JSObject* js_object = JSObject::cast(obj); | 
| +    Smi* zap_value = Smi::FromInt(0); | 
| +    for (int i = 0; i < nof_in_object_properties; i++) { | 
| +      FieldIndex index = FieldIndex::ForLoadByFieldIndex(map, i); | 
| +      Object* field = js_object->RawFastPropertyAt(index); | 
| +      CHECK_EQ(field, zap_value); | 
| +    } | 
| +  } | 
| +  if (obj->IsJSGlobalObject()) { | 
| +    VerifyDictionary(JSObject::cast(obj)->global_dictionary()); | 
| +  } else { | 
| +    VerifyDictionary(obj->property_dictionary()); | 
| +  } | 
| +} | 
| + | 
| +void VerifyProperties(JSReceiver* obj) { | 
| +  obj->VerifyHeapPointer(obj->properties()); | 
| +  if (obj->HasFastProperties()) { | 
| +    VerifyFastProperties(obj); | 
| +  } else { | 
| +    VerifySlowProperties(obj); | 
| +  } | 
| +} | 
| + | 
| +void VerifyElements(JSObject* obj) { | 
| +  obj->VerifyHeapPointer(obj->elements()); | 
| // If a GC was caused while constructing this object, the elements | 
| // pointer may point to a one pointer filler map. | 
| -  if (ElementsAreSafeToExamine()) { | 
| -    CHECK_EQ((map()->has_fast_smi_or_object_elements() || | 
| -              (elements() == GetHeap()->empty_fixed_array()) || | 
| -              HasFastStringWrapperElements()), | 
| -             (elements()->map() == GetHeap()->fixed_array_map() || | 
| -              elements()->map() == GetHeap()->fixed_cow_array_map())); | 
| -    CHECK(map()->has_fast_object_elements() == HasFastObjectElements()); | 
| +  if (!obj->ElementsAreSafeToExamine()) return; | 
| +  Map* map = obj->map(); | 
| +  Heap* heap = obj->GetHeap(); | 
| +  FixedArrayBase* elements = obj->elements(); | 
| +  CHECK_EQ((map->has_fast_smi_or_object_elements() || | 
| +            (elements == heap->empty_fixed_array()) || | 
| +            obj->HasFastStringWrapperElements()), | 
| +           (elements->map() == heap->fixed_array_map() || | 
| +            elements->map() == heap->fixed_cow_array_map())); | 
| +  CHECK_EQ(map->has_fast_object_elements(), obj->HasFastObjectElements()); | 
| + | 
| +  ElementsKind kind = obj->GetElementsKind(); | 
| +  if (IsFastSmiOrObjectElementsKind(kind)) { | 
| +    CHECK(elements->map() == heap->fixed_array_map() || | 
| +          elements->map() == heap->fixed_cow_array_map()); | 
| +  } else if (IsFastDoubleElementsKind(kind)) { | 
| +    CHECK(elements->IsFixedDoubleArray() || | 
| +          elements == heap->empty_fixed_array()); | 
| +  } else if (kind == DICTIONARY_ELEMENTS) { | 
| +    CHECK(elements->IsSeededNumberDictionary()); | 
| +    VerifyDictionary(SeededNumberDictionary::cast(elements)); | 
| +    return; | 
| +  } else { | 
| +    CHECK(kind > DICTIONARY_ELEMENTS); | 
| +  } | 
| +  CHECK(!IsSloppyArgumentsElements(kind) || | 
| +        (elements->IsFixedArray() && elements->length() >= 2)); | 
| + | 
| +  if (IsFastPackedElementsKind(kind)) { | 
| +    uint32_t length = elements->length(); | 
| +    if (obj->IsJSArray()) { | 
| +      Object* number = JSArray::cast(obj)->length(); | 
| +      if (number->IsSmi()) { | 
| +        length = Min(length, static_cast<uint32_t>(Smi::cast(number)->value())); | 
| +      } | 
| +    } | 
| +    if (kind == FAST_DOUBLE_ELEMENTS) { | 
| +      for (uint32_t i = 0; i < length; i++) { | 
| +        CHECK(!FixedDoubleArray::cast(elements)->is_the_hole(i)); | 
| +      } | 
| +    } else { | 
| +      for (uint32_t i = 0; i < length; i++) { | 
| +        CHECK_NE(FixedArray::cast(elements)->get(i), heap->the_hole_value()); | 
| +      } | 
| +    } | 
| } | 
| } | 
|  | 
| +}  // namespace | 
| + | 
| +void JSObject::JSObjectVerify() { | 
| +  VerifyProperties(this); | 
| +  VerifyElements(this); | 
| +} | 
|  | 
| void Map::MapVerify() { | 
| Heap* heap = GetHeap(); | 
| CHECK(!heap->InNewSpace(this)); | 
| -  CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE); | 
| +  CHECK_LE(FIRST_TYPE, instance_type()); | 
| +  CHECK_LE(instance_type(), LAST_TYPE); | 
| CHECK(instance_size() == kVariableSizeSentinel || | 
| (kPointerSize <= instance_size() && | 
| instance_size() < heap->Capacity())); | 
| @@ -357,6 +449,7 @@ void Map::DictionaryMapVerify() { | 
| CHECK(instance_descriptors()->IsEmpty()); | 
| CHECK_EQ(0, unused_property_fields()); | 
| CHECK_EQ(Heap::GetStaticVisitorIdForMap(this), visitor_id()); | 
| +  CHECK_EQ(kInvalidEnumCacheSentinel, EnumLength()); | 
| } | 
|  | 
|  | 
| @@ -426,6 +519,59 @@ void JSGeneratorObject::JSGeneratorObjectVerify() { | 
| VerifyObjectField(kReceiverOffset); | 
| VerifyObjectField(kOperandStackOffset); | 
| VerifyObjectField(kContinuationOffset); | 
| +  JSObjectVerify(); | 
| +} | 
| + | 
| +namespace { | 
| + | 
| +void VerifyArgumentsParameterMap(FixedArray* elements) { | 
| +  Isolate* isolate = elements->GetIsolate(); | 
| +  CHECK(elements->IsFixedArray()); | 
| +  CHECK_GE(elements->length(), 2); | 
| +  HeapObject* context = HeapObject::cast(elements->get(0)); | 
| +  HeapObject* arguments = HeapObject::cast(elements->get(1)); | 
| +  // TODO(cbruni): fix arguments creation to be atomic. | 
| +  CHECK_IMPLIES(context->IsUndefined(isolate), arguments->IsUndefined(isolate)); | 
| +  CHECK(context->IsUndefined(isolate) || context->IsContext()); | 
| +  CHECK(arguments->IsUndefined(isolate) || arguments->IsFixedArray()); | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| +void JSArgumentsObject::JSArgumentsObjectVerify() { | 
| +  VerifyObjectField(kLengthOffset); | 
| +  JSObjectVerify(); | 
| +  Isolate* isolate = GetIsolate(); | 
| + | 
| +  if (isolate->bootstrapper()->IsActive()) return; | 
| +  Context* context = isolate->context(); | 
| +  Object* constructor = map()->GetConstructor(); | 
| +  if (constructor->IsJSFunction()) { | 
| +    context = JSFunction::cast(constructor)->context(); | 
| +  } | 
| +  // TODO(cbruni): replace with NULL check once all hydrogren stubs manage to | 
| +  // set up the contexts properly. | 
| +  if (isolate->context()->IsSmi()) return; | 
| +  Context* native_context = context->native_context(); | 
| +  if (map() == native_context->sloppy_arguments_map()) { | 
| +    // Sloppy arguments without aliased arguments has a normal elements backing | 
| +    // store which is already verified by JSObjectVerify() above. | 
| +  } else if (map() == native_context->fast_aliased_arguments_map()) { | 
| +    CHECK(HasFastArgumentsElements()); | 
| +    FixedArray* elements = FixedArray::cast(this->elements()); | 
| +    VerifyArgumentsParameterMap(FixedArray::cast(elements)); | 
| +    CHECK_EQ(elements->map(), isolate->heap()->sloppy_arguments_elements_map()); | 
| +  } else if (map() == native_context->slow_aliased_arguments_map()) { | 
| +    CHECK(HasSlowArgumentsElements()); | 
| +    FixedArray* elements = FixedArray::cast(this->elements()); | 
| +    VerifyArgumentsParameterMap(elements); | 
| +    VerifyDictionary(SeededNumberDictionary::cast(elements->get(1))); | 
| +    CHECK_EQ(elements->map(), isolate->heap()->sloppy_arguments_elements_map()); | 
| +  } else if (map() == native_context->strict_arguments_map()) { | 
| +    CHECK(HasFastElements()); | 
| +  } else { | 
| +    // TODO(cbruni): follow up on normalized argument maps. | 
| +  } | 
| } | 
|  | 
|  | 
| @@ -434,10 +580,12 @@ void JSValue::JSValueVerify() { | 
| if (v->IsHeapObject()) { | 
| VerifyHeapPointer(v); | 
| } | 
| +  JSObjectVerify(); | 
| } | 
|  | 
|  | 
| void JSDate::JSDateVerify() { | 
| +  JSObjectVerify(); | 
| if (value()->IsHeapObject()) { | 
| VerifyHeapPointer(value()); | 
| } | 
| @@ -487,6 +635,7 @@ void JSDate::JSDateVerify() { | 
|  | 
|  | 
| void JSMessageObject::JSMessageObjectVerify() { | 
| +  JSObjectVerify(); | 
| CHECK(IsJSMessageObject()); | 
| VerifyObjectField(kStartPositionOffset); | 
| VerifyObjectField(kEndPositionOffset); | 
| @@ -545,6 +694,7 @@ void JSBoundFunction::JSBoundFunctionVerify() { | 
|  | 
| void JSFunction::JSFunctionVerify() { | 
| CHECK(IsJSFunction()); | 
| +  JSObjectVerify(); | 
| VerifyObjectField(kPrototypeOrInitialMapOffset); | 
| VerifyObjectField(kNextFunctionLinkOffset); | 
| CHECK(code()->IsCode()); | 
| @@ -591,6 +741,7 @@ void JSGlobalObject::JSGlobalObjectVerify() { | 
| elements()->length() == 0) { | 
| return; | 
| } | 
| +  CHECK(!HasFastProperties()); | 
| JSObjectVerify(); | 
| } | 
|  | 
| @@ -694,7 +845,7 @@ void Code::VerifyEmbeddedObjectsDependency() { | 
| } else if (obj->IsJSObject()) { | 
| if (isolate->heap()->InNewSpace(obj)) { | 
| ArrayList* list = | 
| -              GetIsolate()->heap()->weak_new_space_object_to_code_list(); | 
| +              isolate->heap()->weak_new_space_object_to_code_list(); | 
| bool found = false; | 
| for (int i = 0; i < list->Length(); i += 2) { | 
| WeakCell* obj_cell = WeakCell::cast(list->Get(i)); | 
| @@ -708,7 +859,7 @@ void Code::VerifyEmbeddedObjectsDependency() { | 
| } else { | 
| Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate); | 
| DependentCode* dep = | 
| -              GetIsolate()->heap()->LookupWeakObjectToCodeDependency(key_obj); | 
| +              isolate->heap()->LookupWeakObjectToCodeDependency(key_obj); | 
| dep->Contains(DependentCode::kWeakCodeGroup, cell); | 
| } | 
| } | 
| @@ -718,18 +869,23 @@ void Code::VerifyEmbeddedObjectsDependency() { | 
|  | 
|  | 
| void JSArray::JSArrayVerify() { | 
| +  CHECK(IsJSArray()); | 
| JSObjectVerify(); | 
| Isolate* isolate = GetIsolate(); | 
| -  CHECK(length()->IsNumber() || length()->IsUndefined(isolate)); | 
| +  // Allow undefined for not fully initialized JSArrays | 
| +  if (length()->IsUndefined(isolate)) { | 
| +    CHECK_EQ(FixedArray::cast(elements()), | 
| +             isolate->heap()->empty_fixed_array()); | 
| +    return; | 
| +  } | 
| +  CHECK(length()->IsNumber()); | 
| // If a GC was caused while constructing this array, the elements | 
| // pointer may point to a one pointer filler map. | 
| if (ElementsAreSafeToExamine()) { | 
| -    CHECK(elements()->IsUndefined(isolate) || elements()->IsFixedArray() || | 
| -          elements()->IsFixedDoubleArray()); | 
| +    CHECK(elements()->IsFixedArray() || elements()->IsFixedDoubleArray()); | 
| } | 
| } | 
|  | 
| - | 
| void JSSet::JSSetVerify() { | 
| CHECK(IsJSSet()); | 
| JSObjectVerify(); | 
| @@ -1296,7 +1452,8 @@ void Code::VerifyRecompiledCode(Code* old_code, Code* new_code) { | 
| while (!old_it.done()) { | 
| RelocInfo* rinfo = old_it.rinfo(); | 
| Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 
| -    CHECK(!target->is_handler() && !target->is_inline_cache_stub()); | 
| +    CHECK(!target->is_handler()); | 
| +    CHECK(!target->is_inline_cache_stub()); | 
| if (target == stack_check) break; | 
| old_it.next(); | 
| } | 
| @@ -1304,7 +1461,8 @@ void Code::VerifyRecompiledCode(Code* old_code, Code* new_code) { | 
| while (!new_it.done()) { | 
| RelocInfo* rinfo = new_it.rinfo(); | 
| Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 
| -    CHECK(!target->is_handler() && !target->is_inline_cache_stub()); | 
| +    CHECK(!target->is_handler()); | 
| +    CHECK(!target->is_inline_cache_stub()); | 
| if (target == stack_check) break; | 
| new_it.next(); | 
| } | 
|  |