| Index: src/ic.cc
 | 
| diff --git a/src/ic.cc b/src/ic.cc
 | 
| index e0ebdddf018c0046d83d15f8ab1c0916a84e47ad..56877a5eae5ab836cb4b57a1a4e3f45d74f9fea1 100644
 | 
| --- a/src/ic.cc
 | 
| +++ b/src/ic.cc
 | 
| @@ -182,6 +182,15 @@ Address IC::OriginalCodeAddress() const {
 | 
|  static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
 | 
|                                                     Object* receiver,
 | 
|                                                     Object* name) {
 | 
| +  // If the code is NORMAL, it handles dictionary mode objects. Such stubs do
 | 
| +  // not check maps, but do positive/negative lookups.
 | 
| +  if (target->type() != Code::NORMAL) {
 | 
| +    Map* map = target->FindFirstMap();
 | 
| +    if (map != NULL && map->is_deprecated()) {
 | 
| +      return true;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    InlineCacheHolderFlag cache_holder =
 | 
|        Code::ExtractCacheHolderFromFlags(target->flags());
 | 
|  
 | 
| @@ -505,6 +514,13 @@ MaybeObject* CallICBase::LoadFunction(State state,
 | 
|                                        Code::ExtraICState extra_ic_state,
 | 
|                                        Handle<Object> object,
 | 
|                                        Handle<String> name) {
 | 
| +  if (object->IsJSObject()) {
 | 
| +    Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 | 
| +    if (receiver->map()->is_deprecated()) {
 | 
| +      JSObject::MigrateInstance(receiver);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    // If the object is undefined or null it's illegal to try to get any
 | 
|    // of its properties; throw a TypeError in that case.
 | 
|    if (object->IsUndefined() || object->IsNull()) {
 | 
| @@ -776,6 +792,13 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
 | 
|                                      Handle<String>::cast(key));
 | 
|    }
 | 
|  
 | 
| +  if (object->IsJSObject()) {
 | 
| +    Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 | 
| +    if (receiver->map()->is_deprecated()) {
 | 
| +      JSObject::MigrateInstance(receiver);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    if (object->IsUndefined() || object->IsNull()) {
 | 
|      return TypeError("non_object_property_call", object, key);
 | 
|    }
 | 
| @@ -890,6 +913,13 @@ MaybeObject* LoadIC::Load(State state,
 | 
|      return Runtime::GetElementOrCharAtOrFail(isolate(), object, index);
 | 
|    }
 | 
|  
 | 
| +  if (object->IsJSObject()) {
 | 
| +    Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 | 
| +    if (receiver->map()->is_deprecated()) {
 | 
| +      JSObject::MigrateInstance(receiver);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    // Named lookup in the object.
 | 
|    LookupResult lookup(isolate());
 | 
|    LookupForRead(object, name, &lookup);
 | 
| @@ -954,11 +984,19 @@ bool IC::UpdatePolymorphicIC(State state,
 | 
|    MapHandleList receiver_maps;
 | 
|    CodeHandleList handlers;
 | 
|  
 | 
| +  int number_of_valid_maps;
 | 
|    {
 | 
|      AssertNoAllocation no_gc;
 | 
|      target()->FindAllMaps(&receiver_maps);
 | 
|      int number_of_maps = receiver_maps.length();
 | 
| -    if (number_of_maps >= 4) return false;
 | 
| +    number_of_valid_maps = number_of_maps;
 | 
| +    for (int i = 0; i < number_of_maps; i++) {
 | 
| +      if (receiver_maps.at(i)->is_deprecated()) {
 | 
| +        number_of_valid_maps--;
 | 
| +      }
 | 
| +    }
 | 
| +
 | 
| +    if (number_of_valid_maps >= 4) return false;
 | 
|  
 | 
|      // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC.
 | 
|      // In that case, allow the IC to go back monomorphic.
 | 
| @@ -975,7 +1013,7 @@ bool IC::UpdatePolymorphicIC(State state,
 | 
|  
 | 
|    handlers.Add(code);
 | 
|    Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
 | 
| -      &receiver_maps, &handlers, name);
 | 
| +      &receiver_maps, &handlers, number_of_valid_maps + 1, name);
 | 
|    set_target(*ic);
 | 
|    return true;
 | 
|  }
 | 
| @@ -1066,6 +1104,28 @@ void IC::PatchCache(State state,
 | 
|          if (target()->type() != Code::NORMAL) {
 | 
|            if (target()->is_load_stub()) {
 | 
|              CopyICToMegamorphicCache(name);
 | 
| +          } else if (target()->is_store_stub()) {
 | 
| +            // Ensure that the IC stays monomorphic when replacing a monomorphic
 | 
| +            // IC for a deprecated map.
 | 
| +            // TODO(verwaest): Remove this code once polymorphic store ICs are
 | 
| +            // implemented. Updating the polymorphic IC will keep it monomorphic
 | 
| +            // by filtering deprecated maps.
 | 
| +            MapHandleList maps;
 | 
| +            Code* handler = target();
 | 
| +            handler->FindAllMaps(&maps);
 | 
| +            for (int i = 0; i < Min(1, maps.length()); i++) {
 | 
| +              if (maps.at(i)->is_deprecated()) {
 | 
| +                UpdateMonomorphicIC(receiver, code, name);
 | 
| +                return;
 | 
| +              }
 | 
| +            }
 | 
| +            if (maps.length() > 0) {
 | 
| +              if (receiver->map() == *maps.at(0)) {
 | 
| +                UpdateMonomorphicIC(receiver, code, name);
 | 
| +                return;
 | 
| +              }
 | 
| +              UpdateMegamorphicCache(*maps.at(0), *name, handler);
 | 
| +            }
 | 
|            } else {
 | 
|              Code* handler = target();
 | 
|              Map* map = handler->FindFirstMap();
 | 
| @@ -1365,6 +1425,10 @@ MaybeObject* KeyedLoadIC::Load(State state,
 | 
|          }
 | 
|        } else if (object->IsJSObject()) {
 | 
|          Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 | 
| +        if (receiver->map()->is_deprecated()) {
 | 
| +          JSObject::MigrateInstance(receiver);
 | 
| +        }
 | 
| +
 | 
|          if (receiver->elements()->map() ==
 | 
|              isolate()->heap()->non_strict_arguments_elements_map()) {
 | 
|            stub = non_strict_arguments_stub();
 | 
| @@ -1431,6 +1495,7 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
 | 
|  
 | 
|  static bool LookupForWrite(Handle<JSObject> receiver,
 | 
|                             Handle<String> name,
 | 
| +                           Handle<Object> value,
 | 
|                             LookupResult* lookup) {
 | 
|    Handle<JSObject> holder = receiver;
 | 
|    receiver->Lookup(*name, lookup);
 | 
| @@ -1443,9 +1508,10 @@ static bool LookupForWrite(Handle<JSObject> receiver,
 | 
|          receiver->LocalLookupRealNamedProperty(*name, lookup);
 | 
|          return lookup->IsFound() &&
 | 
|              !lookup->IsReadOnly() &&
 | 
| +            lookup->CanHoldValue(value) &&
 | 
|              lookup->IsCacheable();
 | 
|        }
 | 
| -      return true;
 | 
| +      return lookup->CanHoldValue(value);
 | 
|      }
 | 
|  
 | 
|      if (lookup->IsPropertyCallbacks()) return true;
 | 
| @@ -1463,8 +1529,11 @@ static bool LookupForWrite(Handle<JSObject> receiver,
 | 
|    // chain check. This avoids a double lookup, but requires us to pass in the
 | 
|    // receiver when trying to fetch extra information from the transition.
 | 
|    receiver->map()->LookupTransition(*holder, *name, lookup);
 | 
| -  return lookup->IsTransition() &&
 | 
| -      !lookup->GetTransitionDetails(receiver->map()).IsReadOnly();
 | 
| +  if (!lookup->IsTransition()) return false;
 | 
| +  PropertyDetails target_details =
 | 
| +      lookup->GetTransitionDetails(receiver->map());
 | 
| +  if (target_details.IsReadOnly()) return false;
 | 
| +  return value->FitsRepresentation(target_details.representation());
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1498,6 +1567,10 @@ MaybeObject* StoreIC::Store(State state,
 | 
|  
 | 
|    Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 | 
|  
 | 
| +  if (receiver->map()->is_deprecated()) {
 | 
| +    JSObject::MigrateInstance(receiver);
 | 
| +  }
 | 
| +
 | 
|    // Check if the given name is an array index.
 | 
|    uint32_t index;
 | 
|    if (name->AsArrayIndex(&index)) {
 | 
| @@ -1544,7 +1617,7 @@ MaybeObject* StoreIC::Store(State state,
 | 
|    }
 | 
|  
 | 
|    LookupResult lookup(isolate());
 | 
| -  if (LookupForWrite(receiver, name, &lookup)) {
 | 
| +  if (LookupForWrite(receiver, name, value, &lookup)) {
 | 
|      if (FLAG_use_ic) {
 | 
|        UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
 | 
|      }
 | 
| @@ -1953,6 +2026,9 @@ MaybeObject* KeyedStoreIC::Store(State state,
 | 
|      if (miss_mode != MISS_FORCE_GENERIC) {
 | 
|        if (object->IsJSObject()) {
 | 
|          Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 | 
| +        if (receiver->map()->is_deprecated()) {
 | 
| +          JSObject::MigrateInstance(receiver);
 | 
| +        }
 | 
|          bool key_is_smi_like = key->IsSmi() ||
 | 
|              (FLAG_compiled_keyed_stores && !key->ToSmi()->IsFailure());
 | 
|          if (receiver->elements()->map() ==
 | 
| 
 |