| Index: src/objects-inl.h
 | 
| diff --git a/src/objects-inl.h b/src/objects-inl.h
 | 
| index a7978338058b7e9b37dee0d0c17c90d734d04c1f..899e7dcb3fc63647842d1057b2ae76e08039ba4e 100644
 | 
| --- a/src/objects-inl.h
 | 
| +++ b/src/objects-inl.h
 | 
| @@ -1913,31 +1913,45 @@ int BinarySearch(T* array, String* name, int low, int high) {
 | 
|  
 | 
|  // Perform a linear search in this fixed array. len is the number of entry
 | 
|  // indices that are valid.
 | 
| -template<typename T>
 | 
| -int LinearSearch(T* array, String* name, int len) {
 | 
| +template<SearchMode search_mode, typename T>
 | 
| +int LinearSearch(T* array, String* name, int len, int valid_entries) {
 | 
|    uint32_t hash = name->Hash();
 | 
| -  for (int number = 0; number < len; number++) {
 | 
| -    int sorted_index = array->GetSortedKeyIndex(number);
 | 
| -    String* entry = array->GetKey(sorted_index);
 | 
| -    uint32_t current_hash = entry->Hash();
 | 
| -    if (current_hash > hash) break;
 | 
| -    if (current_hash == hash && entry->Equals(name)) return sorted_index;
 | 
| +  if (search_mode == ALL_ENTRIES) {
 | 
| +    for (int number = 0; number < len; number++) {
 | 
| +      int sorted_index = array->GetSortedKeyIndex(number);
 | 
| +      String* entry = array->GetKey(sorted_index);
 | 
| +      uint32_t current_hash = entry->Hash();
 | 
| +      if (current_hash > hash) break;
 | 
| +      if (current_hash == hash && entry->Equals(name)) return sorted_index;
 | 
| +    }
 | 
| +  } else {
 | 
| +    ASSERT(len >= valid_entries);
 | 
| +    for (int number = 0; number < valid_entries; number++) {
 | 
| +      String* entry = array->GetKey(number);
 | 
| +      uint32_t current_hash = entry->Hash();
 | 
| +      if (current_hash == hash && entry->Equals(name)) return number;
 | 
| +    }
 | 
|    }
 | 
|    return T::kNotFound;
 | 
|  }
 | 
|  
 | 
|  
 | 
| -template<typename T>
 | 
| -int Search(T* array, String* name) {
 | 
| -  SLOW_ASSERT(array->IsSortedNoDuplicates());
 | 
| +template<SearchMode search_mode, typename T>
 | 
| +int Search(T* array, String* name, int valid_entries) {
 | 
| +  if (search_mode == VALID_ENTRIES) {
 | 
| +    SLOW_ASSERT(array->IsSortedNoDuplicates(valid_entries));
 | 
| +  } else {
 | 
| +    SLOW_ASSERT(array->IsSortedNoDuplicates());
 | 
| +  }
 | 
|  
 | 
|    int nof = array->number_of_entries();
 | 
|    if (nof == 0) return T::kNotFound;
 | 
|  
 | 
|    // Fast case: do linear search for small arrays.
 | 
|    const int kMaxElementsForLinearSearch = 8;
 | 
| -  if (nof < kMaxElementsForLinearSearch) {
 | 
| -    return LinearSearch(array, name, nof);
 | 
| +  if (search_mode == VALID_ENTRIES ||
 | 
| +      (search_mode == ALL_ENTRIES && nof < kMaxElementsForLinearSearch)) {
 | 
| +    return LinearSearch<search_mode>(array, name, nof, valid_entries);
 | 
|    }
 | 
|  
 | 
|    // Slow case: perform binary search.
 | 
| @@ -1945,20 +1959,21 @@ int Search(T* array, String* name) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -int DescriptorArray::Search(String* name) {
 | 
| -  return internal::Search(this, name);
 | 
| +int DescriptorArray::Search(String* name, int valid_descriptors) {
 | 
| +  return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors);
 | 
|  }
 | 
|  
 | 
|  
 | 
| -int DescriptorArray::SearchWithCache(String* name) {
 | 
| -  if (number_of_descriptors() == 0) return kNotFound;
 | 
| +int DescriptorArray::SearchWithCache(String* name, Map* map) {
 | 
| +  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
 | 
| +  if (number_of_own_descriptors == 0) return kNotFound;
 | 
|  
 | 
|    DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
 | 
| -  int number = cache->Lookup(this, name);
 | 
| +  int number = cache->Lookup(map, name);
 | 
|  
 | 
|    if (number == DescriptorLookupCache::kAbsent) {
 | 
| -    number = Search(name);
 | 
| -    cache->Update(this, name, number);
 | 
| +    number = Search(name, number_of_own_descriptors);
 | 
| +    cache->Update(map, name, number);
 | 
|    }
 | 
|  
 | 
|    return number;
 | 
| @@ -1969,7 +1984,7 @@ void Map::LookupDescriptor(JSObject* holder,
 | 
|                             String* name,
 | 
|                             LookupResult* result) {
 | 
|    DescriptorArray* descriptors = this->instance_descriptors();
 | 
| -  int number = descriptors->SearchWithCache(name);
 | 
| +  int number = descriptors->SearchWithCache(name, this);
 | 
|    if (number == DescriptorArray::kNotFound) return result->NotFound();
 | 
|    result->DescriptorResult(holder, descriptors->GetDetails(number), number);
 | 
|  }
 | 
| @@ -2013,10 +2028,9 @@ String* DescriptorArray::GetSortedKey(int descriptor_number) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void DescriptorArray::SetSortedKey(int pointer, int descriptor_number) {
 | 
| -  int details_index = ToDetailsIndex(pointer);
 | 
| -  PropertyDetails details = PropertyDetails(Smi::cast(get(details_index)));
 | 
| -  set_unchecked(details_index, details.set_pointer(descriptor_number).AsSmi());
 | 
| +void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
 | 
| +  PropertyDetails details = GetDetails(descriptor_index);
 | 
| +  set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi());
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2100,21 +2114,22 @@ void DescriptorArray::Set(int descriptor_number,
 | 
|  void DescriptorArray::Append(Descriptor* desc,
 | 
|                               const WhitenessWitness& witness,
 | 
|                               int number_of_set_descriptors) {
 | 
| -  int enumeration_index = number_of_set_descriptors + 1;
 | 
| +  int descriptor_number = number_of_set_descriptors;
 | 
| +  int enumeration_index = descriptor_number + 1;
 | 
|    desc->SetEnumerationIndex(enumeration_index);
 | 
| -  Set(number_of_set_descriptors, desc, witness);
 | 
| +  Set(descriptor_number, desc, witness);
 | 
|  
 | 
|    uint32_t hash = desc->GetKey()->Hash();
 | 
|  
 | 
|    int insertion;
 | 
|  
 | 
| -  for (insertion = number_of_set_descriptors; insertion > 0; --insertion) {
 | 
| +  for (insertion = descriptor_number; insertion > 0; --insertion) {
 | 
|      String* key = GetSortedKey(insertion - 1);
 | 
|      if (key->Hash() <= hash) break;
 | 
|      SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
 | 
|    }
 | 
|  
 | 
| -  SetSortedKey(insertion, number_of_set_descriptors);
 | 
| +  SetSortedKey(insertion, descriptor_number);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -3013,6 +3028,16 @@ Code::Flags Code::flags() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void Map::set_owns_descriptors(bool is_shared) {
 | 
| +  set_bit_field3(OwnsDescriptors::update(bit_field3(), is_shared));
 | 
| +}
 | 
| +
 | 
| +
 | 
| +bool Map::owns_descriptors() {
 | 
| +  return OwnsDescriptors::decode(bit_field3());
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void Code::set_flags(Code::Flags flags) {
 | 
|    STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
 | 
|    // Make sure that all call stubs have an arguments count.
 | 
| @@ -3448,9 +3473,17 @@ void Map::set_prototype(Object* value, WriteBarrierMode mode) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +JSGlobalPropertyCell* Map::descriptors_pointer() {
 | 
| +  ASSERT(HasTransitionArray());
 | 
| +  return transitions()->descriptors_pointer();
 | 
| +}
 | 
| +
 | 
| +
 | 
|  DescriptorArray* Map::instance_descriptors() {
 | 
| -  if (!HasTransitionArray()) return GetHeap()->empty_descriptor_array();
 | 
| -  return transitions()->descriptors();
 | 
| +  if (HasTransitionArray()) return transitions()->descriptors();
 | 
| +  Object* back_pointer = GetBackPointer();
 | 
| +  if (!back_pointer->IsMap()) return GetHeap()->empty_descriptor_array();
 | 
| +  return Map::cast(back_pointer)->instance_descriptors();
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -3460,29 +3493,31 @@ static MaybeObject* EnsureHasTransitionArray(Map* map) {
 | 
|    if (map->HasTransitionArray()) return map;
 | 
|  
 | 
|    TransitionArray* transitions;
 | 
| -  MaybeObject* maybe_transitions = TransitionArray::Allocate(0);
 | 
| +  JSGlobalPropertyCell* pointer = map->RetrieveDescriptorsPointer();
 | 
| +  MaybeObject* maybe_transitions = TransitionArray::Allocate(0, pointer);
 | 
|    if (!maybe_transitions->To(&transitions)) return maybe_transitions;
 | 
| +
 | 
| +  transitions->set_back_pointer_storage(map->GetBackPointer());
 | 
|    map->set_transitions(transitions);
 | 
|    return transitions;
 | 
|  }
 | 
|  
 | 
|  
 | 
| -MaybeObject* Map::SetDescriptors(DescriptorArray* value,
 | 
| -                                 WriteBarrierMode mode) {
 | 
| +MaybeObject* Map::SetDescriptors(DescriptorArray* value) {
 | 
|    ASSERT(!is_shared());
 | 
|    MaybeObject* maybe_failure = EnsureHasTransitionArray(this);
 | 
|    if (maybe_failure->IsFailure()) return maybe_failure;
 | 
|  
 | 
| -  transitions()->set_descriptors(value, mode);
 | 
| +  ASSERT(NumberOfOwnDescriptors() <= value->number_of_descriptors());
 | 
| +  transitions()->set_descriptors(value);
 | 
|    return this;
 | 
|  }
 | 
|  
 | 
|  
 | 
|  MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) {
 | 
| -#ifdef DEBUG
 | 
|    int len = descriptors->number_of_descriptors();
 | 
| +#ifdef DEBUG
 | 
|    ASSERT(len <= DescriptorArray::kMaxNumberOfDescriptors);
 | 
| -  SLOW_ASSERT(descriptors->IsSortedNoDuplicates());
 | 
|  
 | 
|    bool used_indices[DescriptorArray::kMaxNumberOfDescriptors];
 | 
|    for (int i = 0; i < len; ++i) used_indices[i] = false;
 | 
| @@ -3501,8 +3536,7 @@ MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) {
 | 
|    MaybeObject* maybe_failure = SetDescriptors(descriptors);
 | 
|    if (maybe_failure->IsFailure()) return maybe_failure;
 | 
|  
 | 
| -  SetNumberOfOwnDescriptors(descriptors->number_of_descriptors());
 | 
| -
 | 
| +  SetNumberOfOwnDescriptors(len);
 | 
|    return this;
 | 
|  }
 | 
|  
 | 
| @@ -3571,9 +3605,21 @@ bool Map::CanHaveMoreTransitions() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +JSGlobalPropertyCell* Map::RetrieveDescriptorsPointer() {
 | 
| +  if (!owns_descriptors()) return NULL;
 | 
| +  Object* back_pointer = GetBackPointer();
 | 
| +  if (back_pointer->IsUndefined()) return NULL;
 | 
| +  Map* map = Map::cast(back_pointer);
 | 
| +  ASSERT(map->HasTransitionArray());
 | 
| +  return map->transitions()->descriptors_pointer();
 | 
| +}
 | 
| +
 | 
| +
 | 
|  MaybeObject* Map::AddTransition(String* key, Map* target) {
 | 
|    if (HasTransitionArray()) return transitions()->CopyInsert(key, target);
 | 
| -  return TransitionArray::NewWith(key, target);
 | 
| +  JSGlobalPropertyCell* descriptors_pointer = RetrieveDescriptorsPointer();
 | 
| +  return TransitionArray::NewWith(
 | 
| +      key, target, descriptors_pointer, GetBackPointer());
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -3582,6 +3628,11 @@ void Map::SetTransition(int transition_index, Map* target) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +Map* Map::GetTransition(int transition_index) {
 | 
| +  return transitions()->GetTarget(transition_index);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
 | 
|    MaybeObject* allow_elements = EnsureHasTransitionArray(this);
 | 
|    if (allow_elements->IsFailure()) return allow_elements;
 | 
| @@ -3627,8 +3678,6 @@ TransitionArray* Map::transitions() {
 | 
|  
 | 
|  void Map::set_transitions(TransitionArray* transition_array,
 | 
|                            WriteBarrierMode mode) {
 | 
| -  transition_array->set_descriptors(instance_descriptors());
 | 
| -  transition_array->set_back_pointer_storage(GetBackPointer());
 | 
|  #ifdef DEBUG
 | 
|    if (HasTransitionArray()) {
 | 
|      ASSERT(transitions() != transition_array);
 | 
| 
 |