// 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 =
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(
}
-// 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|.
}
+// 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
static Representation FromKind(Kind kind) { return Representation(kind); }
- bool Equals(const Representation& other) {
+ bool Equals(const Representation& other) const {
return kind_ == other.kind_;
}
- bool is_more_general_than(const Representation& other) {
+ bool is_more_general_than(const Representation& other) const {
ASSERT(kind_ != kExternal);
ASSERT(other.kind_ != kExternal);
return kind_ > other.kind_;
}
+ bool fits_into(const Representation& other) const {
+ return other.is_more_general_than(*this) || other.Equals(*this);
+ }
+
Representation generalize(Representation other) {
if (is_more_general_than(other)) {
return *this;