Commit d7bc74f8 authored by ishell@chromium.org's avatar ishell@chromium.org

TransitionArray::Search() now returns insertion index if the entry was not found.

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