| Index: src/objects.cc
 | 
| diff --git a/src/objects.cc b/src/objects.cc
 | 
| index 047adc5af9bc17c39975a8a2e905ee33d22f06bf..d48a30d8abc922dc4966c3d5e5413d7207f27f1c 100644
 | 
| --- a/src/objects.cc
 | 
| +++ b/src/objects.cc
 | 
| @@ -1939,7 +1939,7 @@ bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
 | 
|  void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) {
 | 
|    Isolate* isolate = parent->GetIsolate();
 | 
|    Handle<Name> name = isolate->factory()->elements_transition_symbol();
 | 
| -  ConnectTransition(parent, child, name, SPECIAL_TRANSITION);
 | 
| +  ConnectTransition(parent, child, name, FULL_TRANSITION);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2259,13 +2259,11 @@ void Map::DeprecateTransitionTree() {
 | 
|  // Invalidates a transition target at |key|, and installs |new_descriptors| over
 | 
|  // the current instance_descriptors to ensure proper sharing of descriptor
 | 
|  // arrays.
 | 
| -void Map::DeprecateTarget(PropertyType type, Name* key,
 | 
| -                          PropertyAttributes attributes,
 | 
| -                          DescriptorArray* new_descriptors,
 | 
| +void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors,
 | 
|                            LayoutDescriptor* new_layout_descriptor) {
 | 
|    if (HasTransitionArray()) {
 | 
|      TransitionArray* transitions = this->transitions();
 | 
| -    int transition = transitions->Search(type, key, attributes);
 | 
| +    int transition = transitions->Search(key);
 | 
|      if (transition != TransitionArray::kNotFound) {
 | 
|        transitions->GetTarget(transition)->DeprecateTransitionTree();
 | 
|      }
 | 
| @@ -2312,15 +2310,14 @@ Map* Map::FindLastMatchMap(int verbatim,
 | 
|    for (int i = verbatim; i < length; i++) {
 | 
|      if (!current->HasTransitionArray()) break;
 | 
|      Name* name = descriptors->GetKey(i);
 | 
| -    PropertyDetails details = descriptors->GetDetails(i);
 | 
|      TransitionArray* transitions = current->transitions();
 | 
| -    int transition =
 | 
| -        transitions->Search(details.type(), name, details.attributes());
 | 
| +    int transition = transitions->Search(name);
 | 
|      if (transition == TransitionArray::kNotFound) break;
 | 
|  
 | 
|      Map* next = transitions->GetTarget(transition);
 | 
|      DescriptorArray* next_descriptors = next->instance_descriptors();
 | 
|  
 | 
| +    PropertyDetails details = descriptors->GetDetails(i);
 | 
|      PropertyDetails next_details = next_descriptors->GetDetails(i);
 | 
|      if (details.type() != next_details.type()) break;
 | 
|      if (details.attributes() != next_details.attributes()) break;
 | 
| @@ -2524,23 +2521,21 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
 | 
|  
 | 
|    Handle<Map> target_map = root_map;
 | 
|    for (int i = root_nof; i < old_nof; ++i) {
 | 
| -    PropertyDetails old_details = old_descriptors->GetDetails(i);
 | 
| -    int j = target_map->SearchTransition(old_details.type(),
 | 
| -                                         old_descriptors->GetKey(i),
 | 
| -                                         old_details.attributes());
 | 
| +    int j = target_map->SearchTransition(old_descriptors->GetKey(i));
 | 
|      if (j == TransitionArray::kNotFound) break;
 | 
|      Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
 | 
|      Handle<DescriptorArray> tmp_descriptors = handle(
 | 
|          tmp_map->instance_descriptors(), isolate);
 | 
|  
 | 
|      // Check if target map is incompatible.
 | 
| +    PropertyDetails old_details = old_descriptors->GetDetails(i);
 | 
|      PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
 | 
|      PropertyType old_type = old_details.type();
 | 
|      PropertyType tmp_type = tmp_details.type();
 | 
| -    DCHECK_EQ(old_details.attributes(), tmp_details.attributes());
 | 
| -    if ((tmp_type == CALLBACKS || old_type == CALLBACKS) &&
 | 
| -        (tmp_type != old_type ||
 | 
| -         tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) {
 | 
| +    if (tmp_details.attributes() != old_details.attributes() ||
 | 
| +        ((tmp_type == CALLBACKS || old_type == CALLBACKS) &&
 | 
| +         (tmp_type != old_type ||
 | 
| +          tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) {
 | 
|        return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
 | 
|                                                "GenAll_Incompatible");
 | 
|      }
 | 
| @@ -2592,21 +2587,19 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
 | 
|  
 | 
|    // Find the last compatible target map in the transition tree.
 | 
|    for (int i = target_nof; i < old_nof; ++i) {
 | 
| -    PropertyDetails old_details = old_descriptors->GetDetails(i);
 | 
| -    int j = target_map->SearchTransition(old_details.type(),
 | 
| -                                         old_descriptors->GetKey(i),
 | 
| -                                         old_details.attributes());
 | 
| +    int j = target_map->SearchTransition(old_descriptors->GetKey(i));
 | 
|      if (j == TransitionArray::kNotFound) break;
 | 
|      Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
 | 
|      Handle<DescriptorArray> tmp_descriptors(
 | 
|          tmp_map->instance_descriptors(), isolate);
 | 
|  
 | 
|      // Check if target map is compatible.
 | 
| +    PropertyDetails old_details = old_descriptors->GetDetails(i);
 | 
|      PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
 | 
| -    DCHECK_EQ(old_details.attributes(), tmp_details.attributes());
 | 
| -    if ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) &&
 | 
| -        (tmp_details.type() != old_details.type() ||
 | 
| -         tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) {
 | 
| +    if (tmp_details.attributes() != old_details.attributes() ||
 | 
| +        ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) &&
 | 
| +         (tmp_details.type() != old_details.type() ||
 | 
| +          tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) {
 | 
|        return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
 | 
|                                                "GenAll_Incompatible");
 | 
|      }
 | 
| @@ -2738,11 +2731,8 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
 | 
|  
 | 
|    Handle<LayoutDescriptor> new_layout_descriptor =
 | 
|        LayoutDescriptor::New(split_map, new_descriptors, old_nof);
 | 
| -  PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
 | 
| -  split_map->DeprecateTarget(split_prop_details.type(),
 | 
| -                             old_descriptors->GetKey(split_nof),
 | 
| -                             split_prop_details.attributes(), *new_descriptors,
 | 
| -                             *new_layout_descriptor);
 | 
| +  split_map->DeprecateTarget(old_descriptors->GetKey(split_nof),
 | 
| +                             *new_descriptors, *new_layout_descriptor);
 | 
|  
 | 
|    if (FLAG_trace_generalization) {
 | 
|      PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
 | 
| @@ -2832,15 +2822,13 @@ MaybeHandle<Map> Map::TryUpdateInternal(Handle<Map> old_map) {
 | 
|  
 | 
|    Map* new_map = root_map;
 | 
|    for (int i = root_nof; i < old_nof; ++i) {
 | 
| -    PropertyDetails old_details = old_descriptors->GetDetails(i);
 | 
| -    int j = new_map->SearchTransition(old_details.type(),
 | 
| -                                      old_descriptors->GetKey(i),
 | 
| -                                      old_details.attributes());
 | 
| +    int j = new_map->SearchTransition(old_descriptors->GetKey(i));
 | 
|      if (j == TransitionArray::kNotFound) return MaybeHandle<Map>();
 | 
|      new_map = new_map->GetTransition(j);
 | 
|      DescriptorArray* new_descriptors = new_map->instance_descriptors();
 | 
|  
 | 
|      PropertyDetails new_details = new_descriptors->GetDetails(i);
 | 
| +    PropertyDetails old_details = old_descriptors->GetDetails(i);
 | 
|      if (old_details.attributes() != new_details.attributes() ||
 | 
|          !old_details.representation().fits_into(new_details.representation())) {
 | 
|        return MaybeHandle<Map>();
 | 
| @@ -5467,7 +5455,7 @@ MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
 | 
|  
 | 
|    Handle<Map> old_map(object->map(), isolate);
 | 
|    int transition_index =
 | 
| -      old_map->SearchSpecialTransition(isolate->heap()->frozen_symbol());
 | 
| +      old_map->SearchTransition(isolate->heap()->frozen_symbol());
 | 
|    if (transition_index != TransitionArray::kNotFound) {
 | 
|      Handle<Map> transition_map(old_map->GetTransition(transition_index));
 | 
|      DCHECK(transition_map->has_dictionary_elements());
 | 
| @@ -5520,7 +5508,7 @@ void JSObject::SetObserved(Handle<JSObject> object) {
 | 
|    Handle<Map> old_map(object->map(), isolate);
 | 
|    DCHECK(!old_map->is_observed());
 | 
|    int transition_index =
 | 
| -      old_map->SearchSpecialTransition(isolate->heap()->observed_symbol());
 | 
| +      old_map->SearchTransition(isolate->heap()->observed_symbol());
 | 
|    if (transition_index != TransitionArray::kNotFound) {
 | 
|      new_map = handle(old_map->GetTransition(transition_index), isolate);
 | 
|      DCHECK(new_map->is_observed());
 | 
| @@ -6731,7 +6719,7 @@ Handle<Map> Map::ShareDescriptor(Handle<Map> map,
 | 
|    }
 | 
|  
 | 
|    DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
 | 
| -  ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
 | 
| +  ConnectTransition(map, result, name, SIMPLE_TRANSITION);
 | 
|  
 | 
|    return result;
 | 
|  }
 | 
| @@ -6864,7 +6852,7 @@ Handle<Map> Map::CopyInstallDescriptors(
 | 
|    }
 | 
|  
 | 
|    Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
 | 
| -  ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
 | 
| +  ConnectTransition(map, result, name, SIMPLE_TRANSITION);
 | 
|  
 | 
|    return result;
 | 
|  }
 | 
| @@ -6942,7 +6930,7 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) {
 | 
|  
 | 
|    if (map->CanHaveMoreTransitions()) {
 | 
|      Handle<Name> name = isolate->factory()->observed_symbol();
 | 
| -    ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
 | 
| +    ConnectTransition(map, new_map, name, FULL_TRANSITION);
 | 
|    }
 | 
|    return new_map;
 | 
|  }
 | 
| @@ -6956,8 +6944,7 @@ Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
 | 
|    Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
 | 
|                                                   map->GetIsolate());
 | 
|    return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
 | 
| -                                OMIT_TRANSITION, MaybeHandle<Name>(), reason,
 | 
| -                                SPECIAL_TRANSITION);
 | 
| +                                OMIT_TRANSITION, MaybeHandle<Name>(), reason);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -6996,7 +6983,7 @@ Handle<Map> Map::CopyForFreeze(Handle<Map> map) {
 | 
|                                                   isolate);
 | 
|    Handle<Map> new_map = CopyReplaceDescriptors(
 | 
|        map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
 | 
| -      isolate->factory()->frozen_symbol(), "CopyForFreeze", SPECIAL_TRANSITION);
 | 
| +      isolate->factory()->frozen_symbol(), "CopyForFreeze");
 | 
|    new_map->freeze();
 | 
|    new_map->set_is_extensible(false);
 | 
|    new_map->set_elements_kind(DICTIONARY_ELEMENTS);
 | 
| @@ -7060,14 +7047,17 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
 | 
|    // Migrate to the newest map before storing the property.
 | 
|    map = Update(map);
 | 
|  
 | 
| -  int index = map->SearchTransition(FIELD, *name, attributes);
 | 
| +  int index = map->SearchTransition(*name);
 | 
|    if (index != TransitionArray::kNotFound) {
 | 
|      Handle<Map> transition(map->GetTransition(index));
 | 
|      int descriptor = transition->LastAdded();
 | 
|  
 | 
| -    DCHECK_EQ(attributes, transition->instance_descriptors()
 | 
| -                              ->GetDetails(descriptor)
 | 
| -                              .attributes());
 | 
| +    // TODO(verwaest): Handle attributes better.
 | 
| +    DescriptorArray* descriptors = transition->instance_descriptors();
 | 
| +    if (descriptors->GetDetails(descriptor).attributes() != attributes) {
 | 
| +      return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
 | 
| +                            "IncompatibleAttributes");
 | 
| +    }
 | 
|  
 | 
|      return Map::PrepareForDataProperty(transition, descriptor, value);
 | 
|    }
 | 
| @@ -7137,15 +7127,26 @@ Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
 | 
|                                         ? KEEP_INOBJECT_PROPERTIES
 | 
|                                         : CLEAR_INOBJECT_PROPERTIES;
 | 
|  
 | 
| -  int index = map->SearchTransition(CALLBACKS, *name, attributes);
 | 
| +  int index = map->SearchTransition(*name);
 | 
|    if (index != TransitionArray::kNotFound) {
 | 
|      Handle<Map> transition(map->GetTransition(index));
 | 
|      DescriptorArray* descriptors = transition->instance_descriptors();
 | 
| +    // Fast path, assume that we're modifying the last added descriptor.
 | 
|      int descriptor = transition->LastAdded();
 | 
| -    DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
 | 
| +    if (descriptors->GetKey(descriptor) != *name) {
 | 
| +      // If not, search for the descriptor.
 | 
| +      descriptor = descriptors->SearchWithCache(*name, *transition);
 | 
| +    }
 | 
| +
 | 
| +    if (descriptors->GetDetails(descriptor).type() != CALLBACKS) {
 | 
| +      return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
 | 
| +    }
 | 
|  
 | 
| -    DCHECK_EQ(CALLBACKS, descriptors->GetDetails(descriptor).type());
 | 
| -    DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
 | 
| +    // TODO(verwaest): Handle attributes better.
 | 
| +    if (descriptors->GetDetails(descriptor).attributes() != attributes) {
 | 
| +      return Map::Normalize(map, mode,
 | 
| +                            "TransitionToAccessorDifferentAttributes");
 | 
| +    }
 | 
|  
 | 
|      Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
 | 
|      if (!maybe_pair->IsAccessorPair()) {
 | 
| @@ -7164,9 +7165,6 @@ Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
 | 
|    DescriptorArray* old_descriptors = map->instance_descriptors();
 | 
|    int descriptor = old_descriptors->SearchWithCache(*name, *map);
 | 
|    if (descriptor != DescriptorArray::kNotFound) {
 | 
| -    if (descriptor != map->LastAdded()) {
 | 
| -      return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
 | 
| -    }
 | 
|      PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
 | 
|      if (old_details.type() != CALLBACKS) {
 | 
|        return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
 | 
| @@ -7228,7 +7226,7 @@ Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
 | 
|  
 | 
|    return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
 | 
|                                  flag, descriptor->GetKey(), "CopyAddDescriptor",
 | 
| -                                SIMPLE_PROPERTY_TRANSITION);
 | 
| +                                SIMPLE_TRANSITION);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -7324,8 +7322,8 @@ Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
 | 
|  
 | 
|    SimpleTransitionFlag simple_flag =
 | 
|        (insertion_index == descriptors->number_of_descriptors() - 1)
 | 
| -          ? SIMPLE_PROPERTY_TRANSITION
 | 
| -          : PROPERTY_TRANSITION;
 | 
| +          ? SIMPLE_TRANSITION
 | 
| +          : FULL_TRANSITION;
 | 
|    return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
 | 
|                                  flag, key, "CopyReplaceDescriptor",
 | 
|                                  simple_flag);
 | 
| 
 |