| Index: src/ic.cc
|
| diff --git a/src/ic.cc b/src/ic.cc
|
| index 1f0070b193dff8b232a3020a1cd72654e44d3bea..d87205f62f1397055940134879a44a120aec63fd 100644
|
| --- a/src/ic.cc
|
| +++ b/src/ic.cc
|
| @@ -1304,9 +1304,10 @@ static bool StoreICableLookup(LookupResult* lookup) {
|
| if (!lookup->IsCacheable()) return false;
|
|
|
| // If the property is read-only, we leave the IC in its current state.
|
| - if (lookup->IsReadOnly()) return false;
|
| -
|
| - return true;
|
| + if (lookup->IsTransition()) {
|
| + return !lookup->GetTransitionDetails().IsReadOnly();
|
| + }
|
| + return !lookup->IsReadOnly();
|
| }
|
|
|
|
|
| @@ -1458,14 +1459,6 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
| Handle<Map>::null(),
|
| strict_mode);
|
| break;
|
| - case MAP_TRANSITION: {
|
| - if (lookup->GetAttributes() != NONE) return;
|
| - Handle<Map> transition(lookup->GetTransitionMap());
|
| - int index = transition->PropertyIndexFor(*name);
|
| - code = isolate()->stub_cache()->ComputeStoreField(
|
| - name, receiver, index, transition, strict_mode);
|
| - break;
|
| - }
|
| case NORMAL:
|
| if (receiver->IsGlobalObject()) {
|
| // The stub generated for the global object picks the value directly
|
| @@ -1508,8 +1501,26 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
| name, receiver, strict_mode);
|
| break;
|
| case CONSTANT_FUNCTION:
|
| - case CONSTANT_TRANSITION:
|
| return;
|
| + case TRANSITION: {
|
| + Object* value = lookup->GetTransitionValue();
|
| + // Callbacks.
|
| + if (value->IsAccessorPair()) return;
|
| +
|
| + Handle<Map> transition(Map::cast(value));
|
| + DescriptorArray* target_descriptors = transition->instance_descriptors();
|
| + int descriptor = target_descriptors->SearchWithCache(*name);
|
| + ASSERT(descriptor != DescriptorArray::kNotFound);
|
| + PropertyDetails details = target_descriptors->GetDetails(descriptor);
|
| +
|
| + if (details.type() != FIELD || details.attributes() != NONE) return;
|
| +
|
| + int field_index = target_descriptors->GetFieldIndex(descriptor);
|
| + code = isolate()->stub_cache()->ComputeStoreField(
|
| + name, receiver, field_index, transition, strict_mode);
|
| +
|
| + break;
|
| + }
|
| case NONEXISTENT:
|
| case HANDLER:
|
| UNREACHABLE();
|
| @@ -1958,20 +1969,34 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
|
| name, receiver, lookup->GetFieldIndex(),
|
| Handle<Map>::null(), strict_mode);
|
| break;
|
| - case MAP_TRANSITION:
|
| - if (lookup->GetAttributes() == NONE) {
|
| - Handle<Map> transition(lookup->GetTransitionMap());
|
| - int index = transition->PropertyIndexFor(*name);
|
| + case TRANSITION: {
|
| + Object* value = lookup->GetTransitionValue();
|
| + // Callbacks transition.
|
| + if (value->IsAccessorPair()) {
|
| + code = (strict_mode == kStrictMode)
|
| + ? generic_stub_strict()
|
| + : generic_stub();
|
| + break;
|
| + }
|
| +
|
| + Handle<Map> transition(Map::cast(value));
|
| + DescriptorArray* target_descriptors = transition->instance_descriptors();
|
| + int descriptor = target_descriptors->SearchWithCache(*name);
|
| + ASSERT(descriptor != DescriptorArray::kNotFound);
|
| + PropertyDetails details = target_descriptors->GetDetails(descriptor);
|
| +
|
| + if (details.type() == FIELD && details.attributes() == NONE) {
|
| + int field_index = target_descriptors->GetFieldIndex(descriptor);
|
| code = isolate()->stub_cache()->ComputeKeyedStoreField(
|
| - name, receiver, index, transition, strict_mode);
|
| + name, receiver, field_index, transition, strict_mode);
|
| break;
|
| }
|
| // fall through.
|
| + }
|
| case NORMAL:
|
| case CONSTANT_FUNCTION:
|
| case CALLBACKS:
|
| case INTERCEPTOR:
|
| - case CONSTANT_TRANSITION:
|
| // Always rewrite to the generic case so that we do not
|
| // repeatedly try to rewrite.
|
| code = (strict_mode == kStrictMode)
|
|
|