From: ishell Date: Mon, 24 Nov 2014 14:31:31 +0000 (-0800) Subject: Reland of "TransitionArray::Search() now returns insertion index if the entry was... X-Git-Tag: upstream/4.7.83~5558 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=25b8efffa31d3dc39fce96706018d1c122d19e88;p=platform%2Fupstream%2Fv8.git Reland of "TransitionArray::Search() now returns insertion index if the entry was not found." Review URL: https://codereview.chromium.org/739013004 Cr-Commit-Position: refs/heads/master@{#25482} --- diff --git a/src/objects-inl.h b/src/objects-inl.h index 108f9f624..eb9f16752 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -2850,8 +2850,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 -int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) { +template +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; @@ -2872,7 +2874,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; @@ -2881,37 +2889,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 -int LinearSearch(T* array, Name* name, int len, int valid_entries) { +template +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 -int Search(T* array, Name* name, int valid_entries) { +template +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 { @@ -2919,7 +2935,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; @@ -2927,16 +2946,18 @@ int Search(T* array, Name* name, int valid_entries) { nof <= kMaxElementsForLinearSearch) || (search_mode == VALID_ENTRIES && valid_entries <= (kMaxElementsForLinearSearch * 3))) { - return LinearSearch(array, name, nof, valid_entries); + return LinearSearch(array, name, nof, valid_entries, + out_insertion_index); } // Slow case: perform binary search. - return BinarySearch(array, name, 0, nof - 1, valid_entries); + return BinarySearch(array, name, 0, nof - 1, valid_entries, + out_insertion_index); } int DescriptorArray::Search(Name* name, int valid_descriptors) { - return internal::Search(this, name, valid_descriptors); + return internal::Search(this, name, valid_descriptors, NULL); } diff --git a/src/objects.h b/src/objects.h index 1eab44321..b22a5be20 100644 --- a/src/objects.h +++ b/src/objects.h @@ -3151,12 +3151,9 @@ class DescriptorArray: public FixedArray { enum SearchMode { ALL_ENTRIES, VALID_ENTRIES }; -template -inline int LinearSearch(T* array, Name* name, int len, int valid_entries); - - -template -inline int Search(T* array, Name* name, int valid_entries = 0); +template +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 diff --git a/src/transitions-inl.h b/src/transitions-inl.h index 6ed86a140..087755d1b 100644 --- a/src/transitions-inl.h +++ b/src/transitions-inl.h @@ -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(this, name); + return internal::Search(this, name, 0, out_insertion_index); } diff --git a/src/transitions.cc b/src/transitions.cc index 3e570ff9b..ec1b7f4fc 100644 --- a/src/transitions.cc +++ b/src/transitions.cc @@ -41,11 +41,6 @@ void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin, } -static bool InsertionPointFound(Name* key1, Name* key2) { - return key1->Hash() > key2->Hash(); -} - - Handle TransitionArray::NewWith(Handle map, Handle name, Handle target, @@ -99,30 +94,36 @@ Handle TransitionArray::Insert(Handle 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::Insert(Handle 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::Insert(Handle 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()); diff --git a/src/transitions.h b/src/transitions.h index b7e4ebe28..c5f9a3001 100644 --- a/src/transitions.h +++ b/src/transitions.h @@ -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 Allocate(Isolate* isolate,