| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 4d8fe8eb059a0f0690f1849f071416500df6a740..1974a5de607c01df32f3fe85e3a024092389c313 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -1777,13 +1777,7 @@ MaybeObject* JSObject::ConvertTransitionToMapTransition(
|
| // allocation that may fail.
|
| if (!old_target->StoresOwnDescriptors()) {
|
| DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
| -
|
| - old_target->SetBackPointer(GetHeap()->undefined_value());
|
| MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors);
|
| - // Reset the backpointer before returning failure, otherwise the map ends up
|
| - // with an undefined backpointer and no descriptors, losing its own
|
| - // descriptors. Setting the backpointer always succeeds.
|
| - old_target->SetBackPointer(old_map);
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
| }
|
|
|
| @@ -1802,36 +1796,28 @@ MaybeObject* JSObject::ConvertTransitionToMapTransition(
|
| // invalid back pointers. This will change once we can store multiple
|
| // transitions with the same key.
|
|
|
| - if (old_map->owns_descriptors()) {
|
| - // If the old map owns its own descriptors, transfer ownership to the
|
| - // new_map and install its descriptors in the old_map. Since the old_map
|
| - // stores the descriptors for the new_map, remove the transition array of
|
| - // the new_map that is only in place to store the descriptors.
|
| - old_map->transitions()->descriptors_pointer()->set_value(
|
| - new_map->instance_descriptors());
|
| - new_map->ClearTransitions(GetHeap());
|
| - old_map->set_owns_descriptors(false);
|
| - } else if (old_target->instance_descriptors() ==
|
| - old_map->instance_descriptors()) {
|
| + bool owned_descriptors = old_map->owns_descriptors();
|
| + if (owned_descriptors ||
|
| + old_target->instance_descriptors() == old_map->instance_descriptors()) {
|
| // Since the conversion above generated a new fast map with an additional
|
| // property which can be shared as well, install this descriptor pointer
|
| // along the entire chain of smaller maps; and remove the transition array
|
| // that is only in place to hold the descriptor array in the new map.
|
| Map* map;
|
| - JSGlobalPropertyCell* new_pointer =
|
| - new_map->transitions()->descriptors_pointer();
|
| - JSGlobalPropertyCell* old_pointer =
|
| - old_map->transitions()->descriptors_pointer();
|
| + DescriptorArray* new_descriptors = new_map->instance_descriptors();
|
| + DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
| for (Object* current = old_map;
|
| !current->IsUndefined();
|
| current = map->GetBackPointer()) {
|
| map = Map::cast(current);
|
| if (!map->HasTransitionArray()) break;
|
| TransitionArray* transitions = map->transitions();
|
| - if (transitions->descriptors_pointer() != old_pointer) break;
|
| - map->SetEnumLength(Map::kInvalidEnumCache);
|
| - transitions->set_descriptors_pointer(new_pointer);
|
| + if (transitions->descriptors() != old_descriptors) break;
|
| + // Invalidate the enum caches only if the map did not own its descriptors.
|
| + if (!owned_descriptors) map->SetEnumLength(Map::kInvalidEnumCache);
|
| + transitions->set_descriptors(new_descriptors);
|
| }
|
| + old_map->set_owns_descriptors(false);
|
| new_map->ClearTransitions(GetHeap());
|
| }
|
|
|
| @@ -4975,15 +4961,13 @@ MaybeObject* Map::CopyDropDescriptors() {
|
| }
|
|
|
|
|
| -MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
|
| +MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors,
|
| + Descriptor* descriptor) {
|
| // Sanity check. This path is only to be taken if the map owns its descriptor
|
| // array, implying that its NumberOfOwnDescriptors equals the number of
|
| // descriptors in the descriptor array.
|
| - if (NumberOfOwnDescriptors() !=
|
| - instance_descriptors()->number_of_descriptors()) {
|
| - Isolate::Current()->PushStackTraceAndDie(
|
| - 0xDEAD0002, GetBackPointer(), this, 0xDEAD0003);
|
| - }
|
| + ASSERT(NumberOfOwnDescriptors() ==
|
| + instance_descriptors()->number_of_descriptors());
|
| Map* result;
|
| MaybeObject* maybe_result = CopyDropDescriptors();
|
| if (!maybe_result->To(&result)) return maybe_result;
|
| @@ -4995,7 +4979,6 @@ MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
|
| AddTransition(name, result, SIMPLE_TRANSITION);
|
| if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
|
|
| - DescriptorArray* descriptors = instance_descriptors();
|
| int old_size = descriptors->number_of_descriptors();
|
|
|
| DescriptorArray* new_descriptors;
|
| @@ -5026,9 +5009,21 @@ MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
|
| if (descriptors->HasEnumCache()) {
|
| new_descriptors->CopyEnumCacheFrom(descriptors);
|
| }
|
| - }
|
|
|
| - transitions->set_descriptors(new_descriptors);
|
| + Map* map;
|
| + // Replace descriptors by new_descriptors in all maps that share it.
|
| + for (Object* current = GetBackPointer();
|
| + !current->IsUndefined();
|
| + current = map->GetBackPointer()) {
|
| + map = Map::cast(current);
|
| + if (!map->HasTransitionArray()) break;
|
| + TransitionArray* transitions = map->transitions();
|
| + if (transitions->descriptors() != descriptors) break;
|
| + transitions->set_descriptors(new_descriptors);
|
| + }
|
| +
|
| + transitions->set_descriptors(new_descriptors);
|
| + }
|
|
|
| set_transitions(transitions);
|
| result->SetBackPointer(this);
|
| @@ -5073,7 +5068,7 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
| // If the copied map has no added fields, and the parent map owns its
|
| // descriptors, those descriptors have to be empty. In that case,
|
| // transfer ownership of the descriptors to the new child.
|
| - CHECK(instance_descriptors()->IsEmpty());
|
| + ASSERT(instance_descriptors()->IsEmpty());
|
| set_owns_descriptors(false);
|
| } else {
|
| // If the parent did not own its own descriptors, it may share a larger
|
| @@ -5201,7 +5196,7 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
|
| if (flag == INSERT_TRANSITION &&
|
| owns_descriptors() &&
|
| CanHaveMoreTransitions()) {
|
| - return ShareDescriptor(descriptor);
|
| + return ShareDescriptor(descriptors, descriptor);
|
| }
|
|
|
| DescriptorArray* new_descriptors;
|
| @@ -5241,7 +5236,7 @@ MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
|
| // We replace the key if it is already present.
|
| int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this);
|
| if (index != DescriptorArray::kNotFound) {
|
| - return CopyReplaceDescriptor(descriptor, index, flag);
|
| + return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag);
|
| }
|
| return CopyAddDescriptor(descriptor, flag);
|
| }
|
| @@ -5267,15 +5262,14 @@ MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) {
|
| }
|
|
|
|
|
| -MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor,
|
| +MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors,
|
| + Descriptor* descriptor,
|
| int insertion_index,
|
| TransitionFlag flag) {
|
| // Ensure the key is a symbol.
|
| MaybeObject* maybe_failure = descriptor->KeyToSymbol();
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
|
|
| - DescriptorArray* descriptors = instance_descriptors();
|
| -
|
| String* key = descriptor->GetKey();
|
| ASSERT(key == descriptors->GetKey(insertion_index));
|
|
|
| @@ -7458,17 +7452,7 @@ static void TrimDescriptorArray(Heap* heap,
|
| int to_trim = number_of_descriptors - number_of_own_descriptors;
|
| if (to_trim <= 0) return;
|
|
|
| - // Maximally keep 50% of unused descriptors.
|
| - int keep = Min(to_trim, number_of_own_descriptors / 2);
|
| - for (int i = number_of_own_descriptors;
|
| - i < number_of_own_descriptors + keep;
|
| - ++i) {
|
| - descriptors->EraseDescriptor(heap, i);
|
| - }
|
| -
|
| - if (to_trim > keep) {
|
| - RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim - keep);
|
| - }
|
| + RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim);
|
| descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
|
|
|
| if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors);
|
| @@ -7546,7 +7530,6 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
|
| } else {
|
| t->set_descriptors(heap->empty_descriptor_array());
|
| }
|
| - set_owns_descriptors(true);
|
| }
|
|
|
| int trim = t->number_of_transitions() - transition_index;
|
|
|