TransitionArray::Search() now returns insertion index if the entry was not found.
authorishell@chromium.org <ishell@chromium.org>
Tue, 4 Nov 2014 09:29:31 +0000 (09:29 +0000)
committerishell@chromium.org <ishell@chromium.org>
Tue, 4 Nov 2014 09:30:20 +0000 (09:30 +0000)
This is a prerequisite for https://codereview.chromium.org/661133002/.

R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/698043003

Cr-Commit-Position: refs/heads/master@{#25099}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25099 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/objects-inl.h
src/objects.h
src/transitions-inl.h
src/transitions.cc
src/transitions.h

index b25ac5c15bf3cdd21b2f2eb8b9660c1a77818c74..6d0f8d4e61110b55e641ad0b02dcf5dab36e2853 100644 (file)
@@ -2801,8 +2801,10 @@ void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
 // Perform a binary search in a fixed array. Low and high are entry indices. If
 // there are three entries in this array it should be called with low=0 and
 // high=2.
-template<SearchMode search_mode, typename T>
-int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) {
+template <SearchMode search_mode, typename T>
+int BinarySearch(T* array, Name* name, int low, int high, int valid_entries,
+                 int* out_insertion_index) {
+  DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == NULL);
   uint32_t hash = name->Hash();
   int limit = high;
 
@@ -2823,7 +2825,13 @@ int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) {
   for (; low <= limit; ++low) {
     int sort_index = array->GetSortedKeyIndex(low);
     Name* entry = array->GetKey(sort_index);
-    if (entry->Hash() != hash) break;
+    uint32_t current_hash = entry->Hash();
+    if (current_hash != hash) {
+      if (out_insertion_index != NULL) {
+        *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
+      }
+      return T::kNotFound;
+    }
     if (entry->Equals(name)) {
       if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
         return sort_index;
@@ -2832,37 +2840,45 @@ int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) {
     }
   }
 
+  if (out_insertion_index != NULL) *out_insertion_index = limit + 1;
   return T::kNotFound;
 }
 
 
 // Perform a linear search in this fixed array. len is the number of entry
 // indices that are valid.
-template<SearchMode search_mode, typename T>
-int LinearSearch(T* array, Name* name, int len, int valid_entries) {
+template <SearchMode search_mode, typename T>
+int LinearSearch(T* array, Name* name, int len, int valid_entries,
+                 int* out_insertion_index) {
   uint32_t hash = name->Hash();
   if (search_mode == ALL_ENTRIES) {
     for (int number = 0; number < len; number++) {
       int sorted_index = array->GetSortedKeyIndex(number);
       Name* entry = array->GetKey(sorted_index);
       uint32_t current_hash = entry->Hash();
-      if (current_hash > hash) break;
+      if (current_hash > hash) {
+        if (out_insertion_index != NULL) *out_insertion_index = sorted_index;
+        return T::kNotFound;
+      }
       if (current_hash == hash && entry->Equals(name)) return sorted_index;
     }
+    if (out_insertion_index != NULL) *out_insertion_index = len;
+    return T::kNotFound;
   } else {
     DCHECK(len >= valid_entries);
+    DCHECK_EQ(NULL, out_insertion_index);  // Not supported here.
     for (int number = 0; number < valid_entries; number++) {
       Name* entry = array->GetKey(number);
       uint32_t current_hash = entry->Hash();
       if (current_hash == hash && entry->Equals(name)) return number;
     }
+    return T::kNotFound;
   }
-  return T::kNotFound;
 }
 
 
-template<SearchMode search_mode, typename T>
-int Search(T* array, Name* name, int valid_entries) {
+template <SearchMode search_mode, typename T>
+int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) {
   if (search_mode == VALID_ENTRIES) {
     SLOW_DCHECK(array->IsSortedNoDuplicates(valid_entries));
   } else {
@@ -2870,7 +2886,10 @@ int Search(T* array, Name* name, int valid_entries) {
   }
 
   int nof = array->number_of_entries();
-  if (nof == 0) return T::kNotFound;
+  if (nof == 0) {
+    if (out_insertion_index != NULL) *out_insertion_index = 0;
+    return T::kNotFound;
+  }
 
   // Fast case: do linear search for small arrays.
   const int kMaxElementsForLinearSearch = 8;
@@ -2878,16 +2897,18 @@ int Search(T* array, Name* name, int valid_entries) {
        nof <= kMaxElementsForLinearSearch) ||
       (search_mode == VALID_ENTRIES &&
        valid_entries <= (kMaxElementsForLinearSearch * 3))) {
-    return LinearSearch<search_mode>(array, name, nof, valid_entries);
+    return LinearSearch<search_mode>(array, name, nof, valid_entries,
+                                     out_insertion_index);
   }
 
   // Slow case: perform binary search.
-  return BinarySearch<search_mode>(array, name, 0, nof - 1, valid_entries);
+  return BinarySearch<search_mode>(array, name, 0, nof - 1, valid_entries,
+                                   out_insertion_index);
 }
 
 
 int DescriptorArray::Search(Name* name, int valid_descriptors) {
-  return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors);
+  return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors, NULL);
 }
 
 
index 0f2cfc0f11cf469aed61169d24892a25dca0234e..d12896fb94d8d1aa2b0dce522c819f59dd3905e3 100644 (file)
@@ -3145,12 +3145,9 @@ class DescriptorArray: public FixedArray {
 
 enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
 
-template<SearchMode search_mode, typename T>
-inline int LinearSearch(T* array, Name* name, int len, int valid_entries);
-
-
-template<SearchMode search_mode, typename T>
-inline int Search(T* array, Name* name, int valid_entries = 0);
+template <SearchMode search_mode, typename T>
+inline int Search(T* array, Name* name, int valid_entries = 0,
+                  int* out_insertion_index = NULL);
 
 
 // HashTable is a subclass of FixedArray that implements a hash table
index 6ed86a1407e120b7f5ae279650b01d9c2fd665f5..087755d1bdde10f941d17e23f903a0660f5030b2 100644 (file)
@@ -140,13 +140,16 @@ Object* TransitionArray::GetTargetValue(int transition_number) {
 }
 
 
-int TransitionArray::Search(Name* name) {
+int TransitionArray::Search(Name* name, int* out_insertion_index) {
   if (IsSimpleTransition()) {
     Name* key = GetKey(kSimpleTransitionIndex);
     if (key->Equals(name)) return kSimpleTransitionIndex;
+    if (out_insertion_index != NULL) {
+      *out_insertion_index = key->Hash() > name->Hash() ? 0 : 1;
+    }
     return kNotFound;
   }
-  return internal::Search<ALL_ENTRIES>(this, name);
+  return internal::Search<ALL_ENTRIES>(this, name, 0, out_insertion_index);
 }
 
 
index 3e570ff9b0ca9e9a499d1b44b05c558e4d72e883..ec1b7f4fc991f4d91ac2ce1c9fc04af7d24cd6e1 100644 (file)
@@ -41,11 +41,6 @@ void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
 }
 
 
-static bool InsertionPointFound(Name* key1, Name* key2) {
-  return key1->Hash() > key2->Hash();
-}
-
-
 Handle<TransitionArray> TransitionArray::NewWith(Handle<Map> map,
                                                  Handle<Name> name,
                                                  Handle<Map> target,
@@ -99,30 +94,36 @@ Handle<TransitionArray> TransitionArray::Insert(Handle<Map> map,
   int number_of_transitions = map->transitions()->number_of_transitions();
   int new_nof = number_of_transitions;
 
-  int insertion_index = map->transitions()->Search(*name);
-  if (insertion_index == kNotFound) ++new_nof;
+  int insertion_index = kNotFound;
+  int index = map->transitions()->Search(*name, &insertion_index);
+
+  if (index == kNotFound) {
+    ++new_nof;
+  } else {
+    insertion_index = index;
+  }
+  DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);
+
   CHECK(new_nof <= kMaxNumberOfTransitions);
 
   if (new_nof <= map->transitions()->number_of_transitions_storage()) {
     DisallowHeapAllocation no_gc;
     TransitionArray* array = map->transitions();
 
-    if (insertion_index != kNotFound) {
-      array->SetTarget(insertion_index, *target);
+    if (index != kNotFound) {
+      array->SetTarget(index, *target);
       return handle(array);
     }
 
     array->SetNumberOfTransitions(new_nof);
-    uint32_t hash = name->Hash();
-    for (insertion_index = number_of_transitions; insertion_index > 0;
-         --insertion_index) {
-      Name* key = array->GetKey(insertion_index - 1);
-      if (key->Hash() <= hash) break;
-      array->SetKey(insertion_index, key);
-      array->SetTarget(insertion_index, array->GetTarget(insertion_index - 1));
+    for (index = number_of_transitions; index > insertion_index; --index) {
+      Name* key = array->GetKey(index - 1);
+      DCHECK(key->Hash() > name->Hash());
+      array->SetKey(index, key);
+      array->SetTarget(index, array->GetTarget(index - 1));
     }
-    array->SetKey(insertion_index, *name);
-    array->SetTarget(insertion_index, *target);
+    array->SetKey(index, *name);
+    array->SetTarget(index, *target);
     return handle(array);
   }
 
@@ -142,8 +143,14 @@ Handle<TransitionArray> TransitionArray::Insert(Handle<Map> map,
     number_of_transitions = array->number_of_transitions();
     new_nof = number_of_transitions;
 
-    insertion_index = array->Search(*name);
-    if (insertion_index == kNotFound) ++new_nof;
+    insertion_index = kNotFound;
+    index = array->Search(*name, &insertion_index);
+    if (index == kNotFound) {
+      ++new_nof;
+    } else {
+      insertion_index = index;
+    }
+    DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);
 
     result->Shrink(ToKeyIndex(new_nof));
     result->SetNumberOfTransitions(new_nof);
@@ -153,18 +160,13 @@ Handle<TransitionArray> TransitionArray::Insert(Handle<Map> map,
     result->SetPrototypeTransitions(array->GetPrototypeTransitions());
   }
 
-  insertion_index = 0;
-  for (; insertion_index < number_of_transitions; ++insertion_index) {
-    if (InsertionPointFound(array->GetKey(insertion_index), *name)) break;
-    result->NoIncrementalWriteBarrierCopyFrom(
-        array, insertion_index, insertion_index);
+  DCHECK_NE(kNotFound, insertion_index);
+  for (int i = 0; i < insertion_index; ++i) {
+    result->NoIncrementalWriteBarrierCopyFrom(array, i, i);
   }
-
   result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target);
-
-  for (; insertion_index < number_of_transitions; ++insertion_index) {
-    result->NoIncrementalWriteBarrierCopyFrom(
-        array, insertion_index, insertion_index + 1);
+  for (int i = insertion_index; i < number_of_transitions; ++i) {
+    result->NoIncrementalWriteBarrierCopyFrom(array, i, i + 1);
   }
 
   result->set_back_pointer_storage(array->back_pointer_storage());
index b7e4ebe2856e022dc963fcbf3e74e3b7e1881c69..c5f9a30018a16cf02006c49a9cedb644ac3e7986 100644 (file)
@@ -100,7 +100,7 @@ class TransitionArray: public FixedArray {
                                         SimpleTransitionFlag flag);
 
   // Search a transition for a given property name.
-  inline int Search(Name* name);
+  inline int Search(Name* name, int* out_insertion_index = NULL);
 
   // Allocates a TransitionArray.
   static Handle<TransitionArray> Allocate(Isolate* isolate,