Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 94fd487aa3eef6f6016bcb153e4c69ba2e608273..67305a806dd7a4785f3d7051f5bb2d04456ad5c3 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2460,12 +2460,17 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index, |
// Check the state of the root map. |
DescriptorArray* updated_descriptors = updated->instance_descriptors(); |
+ int valid = updated->NumberOfOwnDescriptors(); |
+ if (updated_descriptors->IsMoreGeneralThan( |
+ verbatim, valid, descriptors, old_descriptors)) { |
+ Representation updated_representation = |
+ updated_descriptors->GetDetails(modify_index).representation(); |
+ if (new_representation.fits_into(updated_representation)) return updated; |
+ } |
+ |
DescriptorArray* new_descriptors; |
MaybeObject* maybe_descriptors = updated_descriptors->Merge( |
- verbatim, |
- updated->NumberOfOwnDescriptors(), |
- descriptors, |
- old_descriptors); |
+ verbatim, valid, descriptors, old_descriptors); |
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
old_reprepresentation = |
@@ -2477,9 +2482,9 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index, |
verbatim, descriptors, new_descriptors); |
int split_descriptors = split_map->NumberOfOwnDescriptors(); |
- // Check whether |split_map| matches what we were looking for. If so, return |
- // it. |
- if (descriptors == split_descriptors) return split_map; |
+ // This is shadowed by |updated_descriptors| being more general than |
+ // |old_descriptors|. |
+ ASSERT(descriptors != split_descriptors); |
int descriptor = split_descriptors; |
split_map->DeprecateTarget( |
@@ -7260,7 +7265,7 @@ void DescriptorArray::CopyFrom(int dst_index, |
} |
-// Generalize the |other| descriptor array by merging it with the (at least |
+// Generalize the |other| descriptor array by merging it into the (at least |
// partly) updated |this| descriptor array. |
// The method merges two descriptor array in three parts. Both descriptor arrays |
// are identical up to |verbatim|. They also overlap in keys up to |valid|. |
@@ -7343,6 +7348,37 @@ MaybeObject* DescriptorArray::Merge(int verbatim, |
} |
+// Checks whether a merge of |other| into |this| would return a copy of |this|. |
+bool DescriptorArray::IsMoreGeneralThan(int verbatim, |
+ int valid, |
+ int new_size, |
+ DescriptorArray* other) { |
+ ASSERT(verbatim <= valid); |
+ ASSERT(valid <= new_size); |
+ if (valid != new_size) return false; |
+ |
+ for (int descriptor = verbatim; descriptor < valid; descriptor++) { |
+ PropertyDetails details = GetDetails(descriptor); |
+ PropertyDetails other_details = other->GetDetails(descriptor); |
+ if (details.type() != other_details.type()) { |
+ if (details.type() != FIELD || |
+ other_details.type() != CONSTANT_FUNCTION) { |
+ return false; |
+ } |
+ } else if (details.type() == CONSTANT_FUNCTION) { |
+ if (GetValue(descriptor) != other->GetValue(descriptor)) { |
+ return false; |
+ } |
+ } else if (!other_details.representation().fits_into( |
+ details.representation())) { |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
+ |
// We need the whiteness witness since sort will reshuffle the entries in the |
// descriptor array. If the descriptor array were to be black, the shuffling |
// would move a slot that was already recorded as pointing into an evacuation |