Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 122550f5d5c42e8bbf55f0ea20202f2f2bdca999..f5fa70948e9ac3a7a9836ba1c5f0c26d5ee1987c 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -4750,11 +4750,19 @@ MaybeObject* Map::CopyDropDescriptors() { |
MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
String* name, |
+ int last_added, |
TransitionFlag flag) { |
Map* result; |
MaybeObject* maybe_result = CopyDropDescriptors(); |
if (!maybe_result->To(&result)) return maybe_result; |
+ if (last_added == DescriptorArray::kNoneAdded) { |
+ ASSERT(descriptors->IsEmpty()); |
+ ASSERT(flag == OMIT_TRANSITION); |
+ return result; |
+ } |
+ |
+ descriptors->SetLastAdded(last_added); |
result->set_instance_descriptors(descriptors); |
if (flag == INSERT_TRANSITION) { |
@@ -4807,32 +4815,82 @@ MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { |
// array describing these properties. |
ASSERT(constructor()->IsJSFunction()); |
JSFunction* ctor = JSFunction::cast(constructor()); |
+ Map* initial_map = ctor->initial_map(); |
+ DescriptorArray* initial_descriptors = initial_map->instance_descriptors(); |
DescriptorArray* descriptors; |
MaybeObject* maybe_descriptors = |
- ctor->initial_map()->instance_descriptors()->Copy( |
- DescriptorArray::MAY_BE_SHARED); |
+ initial_descriptors->Copy(DescriptorArray::MAY_BE_SHARED); |
if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
- return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION); |
+ int last_added = initial_descriptors->IsEmpty() |
+ ? DescriptorArray::kNoneAdded |
+ : initial_descriptors->LastAdded(); |
+ |
+ return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION); |
} |
MaybeObject* Map::Copy(DescriptorArray::SharedMode shared_mode) { |
+ DescriptorArray* source_descriptors = instance_descriptors(); |
DescriptorArray* descriptors; |
- MaybeObject* maybe_descriptors = instance_descriptors()->Copy(shared_mode); |
+ MaybeObject* maybe_descriptors = source_descriptors->Copy(shared_mode); |
if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
- return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION); |
+ int last_added = source_descriptors->IsEmpty() |
+ ? DescriptorArray::kNoneAdded |
+ : source_descriptors->LastAdded(); |
+ |
+ return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION); |
+} |
+ |
+ |
+static bool InsertionPointFound(String* key1, String* key2) { |
+ return key1->Hash() > key2->Hash() || key1 == key2; |
} |
MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, |
TransitionFlag flag) { |
- DescriptorArray* descriptors; |
- MaybeObject* maybe_descriptors = instance_descriptors()->CopyAdd(descriptor); |
- if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
+ DescriptorArray* descriptors = instance_descriptors(); |
+ |
+ // Ensure the key is a symbol. |
+ MaybeObject* maybe_failure = descriptor->KeyToSymbol(); |
+ if (maybe_failure->IsFailure()) return maybe_failure; |
- return CopyReplaceDescriptors(descriptors, descriptor->GetKey(), flag); |
+ String* key = descriptor->GetKey(); |
+ ASSERT(descriptors->Search(key) == DescriptorArray::kNotFound); |
+ |
+ int old_size = descriptors->number_of_descriptors(); |
+ int new_size = old_size + 1; |
+ |
+ DescriptorArray* new_descriptors; |
+ MaybeObject* maybe_descriptors = |
+ DescriptorArray::Allocate(new_size, DescriptorArray::MAY_BE_SHARED); |
+ if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
+ |
+ FixedArray::WhitenessWitness witness(new_descriptors); |
+ |
+ // Copy the descriptors, inserting a descriptor. |
+ int insertion_index = -1; |
+ int to = 0; |
+ for (int from = 0; from < old_size; ++from) { |
+ if (insertion_index < 0 && |
+ InsertionPointFound(descriptors->GetKey(from), key)) { |
+ insertion_index = to++; |
+ } |
+ new_descriptors->CopyFrom(to++, descriptors, from, witness); |
+ } |
+ if (insertion_index < 0) insertion_index = to++; |
+ |
+ ASSERT(to == new_size); |
+ ASSERT(new_size == descriptors->NextEnumerationIndex()); |
+ |
+ descriptor->SetEnumerationIndex(new_size); |
+ new_descriptors->Set(insertion_index, descriptor, witness); |
+ |
+ SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); |
+ |
+ return CopyReplaceDescriptors(new_descriptors, key, insertion_index, flag); |
} |
@@ -4844,31 +4902,50 @@ MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, |
MaybeObject* maybe_result = descriptor->KeyToSymbol(); |
if (maybe_result->IsFailure()) return maybe_result; |
- DescriptorArray* descriptors; |
- MaybeObject* maybe_descriptors; |
- |
// We replace the key if it is already present. |
int index = old_descriptors->SearchWithCache(descriptor->GetKey()); |
- if (index == DescriptorArray::kNotFound) { |
- maybe_descriptors = old_descriptors->CopyAdd(descriptor); |
- } else { |
- maybe_descriptors = old_descriptors->CopyReplace(descriptor, index); |
+ if (index != DescriptorArray::kNotFound) { |
+ return CopyReplaceDescriptor(descriptor, index, flag); |
} |
- if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
- |
- return CopyReplaceDescriptors(descriptors, descriptor->GetKey(), flag); |
+ return CopyAddDescriptor(descriptor, flag); |
} |
MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, |
- int index, |
+ int insertion_index, |
TransitionFlag flag) { |
- DescriptorArray* descriptors; |
+ DescriptorArray* descriptors = instance_descriptors(); |
+ int size = descriptors->number_of_descriptors(); |
+ ASSERT(0 <= insertion_index && insertion_index < size); |
+ |
+ // Ensure the key is a symbol. |
+ MaybeObject* maybe_failure = descriptor->KeyToSymbol(); |
+ if (maybe_failure->IsFailure()) return maybe_failure; |
+ |
+ String* key = descriptor->GetKey(); |
+ ASSERT(key == descriptors->GetKey(insertion_index)); |
+ |
+ DescriptorArray* new_descriptors; |
MaybeObject* maybe_descriptors = |
- instance_descriptors()->CopyReplace(descriptor, index); |
- if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
+ DescriptorArray::Allocate(size, DescriptorArray::MAY_BE_SHARED); |
+ if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
- return CopyReplaceDescriptors(descriptors, descriptor->GetKey(), flag); |
+ FixedArray::WhitenessWitness witness(new_descriptors); |
+ |
+ // Copy the descriptors, replacing a descriptor. |
+ for (int index = 0; index < size; ++index) { |
+ if (index == insertion_index) continue; |
+ new_descriptors->CopyFrom(index, descriptors, index, witness); |
+ } |
+ |
+ descriptor->SetEnumerationIndex( |
+ descriptors->GetDetails(insertion_index).index()); |
+ new_descriptors->Set(insertion_index, descriptor, witness); |
+ |
+ SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); |
+ |
+ return CopyReplaceDescriptors( |
+ new_descriptors, key, descriptors->LastAdded(), flag); |
} |
@@ -5685,11 +5762,6 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
} |
-static bool InsertionPointFound(String* key1, String* key2) { |
- return key1->Hash() > key2->Hash() || key1 == key2; |
-} |
- |
- |
void DescriptorArray::CopyFrom(int dst_index, |
DescriptorArray* src, |
int src_index, |
@@ -5701,78 +5773,6 @@ void DescriptorArray::CopyFrom(int dst_index, |
} |
-MaybeObject* DescriptorArray::CopyReplace(Descriptor* descriptor, |
- int insertion_index) { |
- ASSERT(0 <= insertion_index && insertion_index < number_of_descriptors()); |
- |
- // Ensure the key is a symbol. |
- MaybeObject* maybe_failure = descriptor->KeyToSymbol(); |
- if (maybe_failure->IsFailure()) return maybe_failure; |
- |
- int size = number_of_descriptors(); |
- |
- DescriptorArray* new_descriptors; |
- MaybeObject* maybe_descriptors = Allocate(size, MAY_BE_SHARED); |
- if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
- |
- FixedArray::WhitenessWitness witness(new_descriptors); |
- |
- // Copy the descriptors, replacing a descriptor. |
- for (int index = 0; index < size; ++index) { |
- if (index == insertion_index) continue; |
- new_descriptors->CopyFrom(index, this, index, witness); |
- } |
- |
- descriptor->SetEnumerationIndex(GetDetails(insertion_index).index()); |
- new_descriptors->Set(insertion_index, descriptor, witness); |
- new_descriptors->SetLastAdded(LastAdded()); |
- |
- SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); |
- |
- return new_descriptors; |
-} |
- |
- |
-MaybeObject* DescriptorArray::CopyAdd(Descriptor* descriptor) { |
- // Ensure the key is a symbol. |
- MaybeObject* maybe_failure = descriptor->KeyToSymbol(); |
- if (maybe_failure->IsFailure()) return maybe_failure; |
- |
- String* key = descriptor->GetKey(); |
- ASSERT(Search(key) == kNotFound); |
- |
- int new_size = number_of_descriptors() + 1; |
- |
- DescriptorArray* new_descriptors; |
- MaybeObject* maybe_descriptors = Allocate(new_size, MAY_BE_SHARED); |
- if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
- |
- FixedArray::WhitenessWitness witness(new_descriptors); |
- |
- // Copy the descriptors, inserting a descriptor. |
- int insertion_index = -1; |
- int to = 0; |
- for (int from = 0; from < number_of_descriptors(); ++from) { |
- if (insertion_index < 0 && InsertionPointFound(GetKey(from), key)) { |
- insertion_index = to++; |
- } |
- new_descriptors->CopyFrom(to++, this, from, witness); |
- } |
- if (insertion_index < 0) insertion_index = to++; |
- |
- ASSERT(to == new_descriptors->number_of_descriptors()); |
- |
- ASSERT(new_size == NextEnumerationIndex()); |
- descriptor->SetEnumerationIndex(new_size); |
- new_descriptors->Set(insertion_index, descriptor, witness); |
- new_descriptors->SetLastAdded(insertion_index); |
- |
- SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); |
- |
- return new_descriptors; |
-} |
- |
- |
MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) { |
// Allocate the new descriptor array. |
int number_of_descriptors = this->number_of_descriptors(); |
@@ -5786,7 +5786,6 @@ MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) { |
for (int i = 0; i < number_of_descriptors; i++) { |
new_descriptors->CopyFrom(i, this, i, witness); |
} |
- new_descriptors->SetLastAdded(LastAdded()); |
} |
return new_descriptors; |