| Index: src/lookup.cc | 
| diff --git a/src/lookup.cc b/src/lookup.cc | 
| index c3cf013c68f60cf102c7063035353a0f98d92db2..b78016142bf9f6a2932a97ae86e9770a1052b9ae 100644 | 
| --- a/src/lookup.cc | 
| +++ b/src/lookup.cc | 
| @@ -237,9 +237,21 @@ void LookupIterator::PrepareForDataProperty(Handle<Object> value) { | 
| } | 
| if (!holder->HasFastProperties()) return; | 
|  | 
| +  PropertyConstness new_constness = kConst; | 
| +  if (FLAG_track_constant_fields) { | 
| +    if (constness() == kConst) { | 
| +      DCHECK_EQ(kData, property_details_.kind()); | 
| +      // Check that current value matches new value otherwise we should make | 
| +      // the property mutable. | 
| +      if (!IsConstFieldValueEqualTo(*value)) new_constness = kMutable; | 
| +    } | 
| +  } else { | 
| +    new_constness = kMutable; | 
| +  } | 
| + | 
| Handle<Map> old_map(holder->map(), isolate_); | 
| -  Handle<Map> new_map = | 
| -      Map::PrepareForDataProperty(old_map, descriptor_number(), value); | 
| +  Handle<Map> new_map = Map::PrepareForDataProperty( | 
| +      old_map, descriptor_number(), new_constness, value); | 
|  | 
| if (old_map.is_identical_to(new_map)) { | 
| // Update the property details if the representation was None. | 
| @@ -271,7 +283,10 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value, | 
| Handle<Map> old_map(holder->map(), isolate_); | 
| Handle<Map> new_map = Map::ReconfigureExistingProperty( | 
| old_map, descriptor_number(), i::kData, attributes); | 
| -    new_map = Map::PrepareForDataProperty(new_map, descriptor_number(), value); | 
| +    // Force mutable to avoid changing constant value by reconfiguring | 
| +    // kData -> kAccessor -> kData. | 
| +    new_map = Map::PrepareForDataProperty(new_map, descriptor_number(), | 
| +                                          kMutable, value); | 
| JSObject::MigrateToMap(holder, new_map); | 
| ReloadPropertyInformation<false>(); | 
| } else { | 
| @@ -296,7 +311,7 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value, | 
| state_ = DATA; | 
| } | 
|  | 
| -  WriteDataValue(value); | 
| +  WriteDataValue(value, true); | 
|  | 
| #if VERIFY_HEAP | 
| if (FLAG_verify_heap) { | 
| @@ -360,8 +375,8 @@ void LookupIterator::PrepareTransitionToDataProperty( | 
| return; | 
| } | 
|  | 
| -  Handle<Map> transition = | 
| -      Map::TransitionToDataProperty(map, name_, value, attributes, store_mode); | 
| +  Handle<Map> transition = Map::TransitionToDataProperty( | 
| +      map, name_, value, attributes, kDefaultFieldConstness, store_mode); | 
| state_ = TRANSITION; | 
| transition_ = transition; | 
|  | 
| @@ -603,6 +618,39 @@ Handle<Object> LookupIterator::FetchValue() const { | 
| return handle(result, isolate_); | 
| } | 
|  | 
| +bool LookupIterator::IsConstFieldValueEqualTo(Object* value) const { | 
| +  DCHECK(!IsElement()); | 
| +  DCHECK(holder_->HasFastProperties()); | 
| +  DCHECK_EQ(kField, property_details_.location()); | 
| +  DCHECK_EQ(kConst, property_details_.constness()); | 
| +  Handle<JSObject> holder = GetHolder<JSObject>(); | 
| +  FieldIndex field_index = FieldIndex::ForDescriptor(holder->map(), number_); | 
| +  if (property_details_.representation().IsDouble()) { | 
| +    if (!value->IsNumber()) return false; | 
| +    uint64_t bits; | 
| +    if (holder->IsUnboxedDoubleField(field_index)) { | 
| +      bits = holder->RawFastDoublePropertyAsBitsAt(field_index); | 
| +    } else { | 
| +      Object* current_value = holder->RawFastPropertyAt(field_index); | 
| +      DCHECK(current_value->IsMutableHeapNumber()); | 
| +      bits = HeapNumber::cast(current_value)->value_as_bits(); | 
| +    } | 
| +    // Use bit representation of double to to check for hole double, since | 
| +    // manipulating the signaling NaN used for the hole in C++, e.g. with | 
| +    // bit_cast or value(), will change its value on ia32 (the x87 stack is | 
| +    // used to return values and stores to the stack silently clear the | 
| +    // signalling bit). | 
| +    if (bits == kHoleNanInt64) { | 
| +      // Uninitialized double field. | 
| +      return true; | 
| +    } | 
| +    return bit_cast<double>(bits) == value->Number(); | 
| +  } else { | 
| +    Object* current_value = holder->RawFastPropertyAt(field_index); | 
| +    return current_value->IsUninitialized(isolate()) || current_value == value; | 
| +  } | 
| +} | 
| + | 
| int LookupIterator::GetFieldDescriptorIndex() const { | 
| DCHECK(has_property_); | 
| DCHECK(holder_->HasFastProperties()); | 
| @@ -625,6 +673,7 @@ int LookupIterator::GetConstantIndex() const { | 
| DCHECK(holder_->HasFastProperties()); | 
| DCHECK_EQ(kDescriptor, property_details_.location()); | 
| DCHECK_EQ(kData, property_details_.kind()); | 
| +  DCHECK(!FLAG_track_constant_fields); | 
| DCHECK(!IsElement()); | 
| return descriptor_number(); | 
| } | 
| @@ -673,8 +722,8 @@ Handle<Object> LookupIterator::GetDataValue() const { | 
| return value; | 
| } | 
|  | 
| - | 
| -void LookupIterator::WriteDataValue(Handle<Object> value) { | 
| +void LookupIterator::WriteDataValue(Handle<Object> value, | 
| +                                    bool initializing_store) { | 
| DCHECK_EQ(DATA, state_); | 
| Handle<JSReceiver> holder = GetHolder<JSReceiver>(); | 
| if (IsElement()) { | 
| @@ -683,6 +732,11 @@ void LookupIterator::WriteDataValue(Handle<Object> value) { | 
| accessor->Set(object, number_, *value); | 
| } else if (holder->HasFastProperties()) { | 
| if (property_details_.location() == kField) { | 
| +      // Check that in case of kConst field the existing value is equal to | 
| +      // |value|. | 
| +      DCHECK_IMPLIES( | 
| +          !initializing_store && property_details_.constness() == kConst, | 
| +          IsConstFieldValueEqualTo(*value)); | 
| JSObject::cast(*holder)->WriteToField(descriptor_number(), | 
| property_details_, *value); | 
| } else { | 
|  |