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); |