Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(811)

Unified Diff: src/objects.cc

Issue 888623002: Property reconfiguring implemented. Tests added. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Prototype transitions printing removed Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 425d7703752554a1dd6a264ba1733402d1df7d59..775a66479bff7cd527592cacadfb79f491610a47 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1269,6 +1269,25 @@ void JSObject::PrintElementsTransition(
}
+void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
+ PropertyAttributes attributes) {
+ OFStream os(file);
+ os << "[reconfiguring ";
+ constructor_name()->PrintOn(file);
+ os << "] ";
+ Name* name = instance_descriptors()->GetKey(modify_index);
+ if (name->IsString()) {
+ String::cast(name)->PrintOn(file);
+ } else {
+ os << "{symbol " << static_cast<void*>(name) << "}";
+ }
+ os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
+ os << attributes << " [";
+ JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
+ os << "]\n";
+}
+
+
void Map::PrintGeneralization(FILE* file,
const char* reason,
int modify_index,
@@ -1977,15 +1996,19 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
PropertyDetails details = new_descriptors->GetDetails(i);
if (details.type() != DATA) continue;
PropertyDetails old_details = old_descriptors->GetDetails(i);
- if (old_details.type() == ACCESSOR_CONSTANT) {
- DCHECK(details.representation().IsTagged());
- continue;
- }
Representation old_representation = old_details.representation();
Representation representation = details.representation();
- DCHECK(old_details.type() == DATA_CONSTANT || old_details.type() == DATA);
Handle<Object> value;
- if (old_details.type() == DATA_CONSTANT) {
+ if (old_details.type() == ACCESSOR_CONSTANT) {
+ // In case of kAccessor -> kData property reconfiguration, the property
+ // must already be prepared for data or certain type.
+ DCHECK(!details.representation().IsNone());
+ if (details.representation().IsDouble()) {
+ value = isolate->factory()->NewHeapNumber(0, MUTABLE);
+ } else {
+ value = isolate->factory()->uninitialized_value();
+ }
+ } else if (old_details.type() == DATA_CONSTANT) {
value = handle(old_descriptors->GetValue(i), isolate);
DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
} else {
@@ -2079,17 +2102,15 @@ int Map::NumberOfFields() {
DescriptorArray* descriptors = instance_descriptors();
int result = 0;
for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
- if (descriptors->GetDetails(i).type() == DATA) result++;
+ if (descriptors->GetDetails(i).location() == kField) result++;
}
return result;
}
-Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
- int modify_index,
- StoreMode store_mode,
- PropertyAttributes attributes,
- const char* reason) {
+Handle<Map> Map::CopyGeneralizeAllRepresentations(
+ Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind,
+ PropertyAttributes attributes, const char* reason) {
Isolate* isolate = map->GetIsolate();
Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
@@ -2110,53 +2131,43 @@ Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
// Unless the instance is being migrated, ensure that modify_index is a field.
- PropertyDetails details = descriptors->GetDetails(modify_index);
- if (store_mode == FORCE_FIELD &&
- (details.type() != DATA || details.attributes() != attributes)) {
- int field_index = details.type() == DATA ? details.field_index()
- : new_map->NumberOfFields();
- DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
- field_index, attributes, Representation::Tagged());
- descriptors->Replace(modify_index, &d);
- if (details.type() != DATA) {
- int unused_property_fields = new_map->unused_property_fields() - 1;
- if (unused_property_fields < 0) {
- unused_property_fields += JSObject::kFieldsAdded;
+ if (modify_index >= 0) {
+ PropertyDetails details = descriptors->GetDetails(modify_index);
+ if (store_mode == FORCE_FIELD &&
+ (details.type() != DATA || details.attributes() != attributes)) {
+ int field_index = details.type() == DATA ? details.field_index()
+ : new_map->NumberOfFields();
+ DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
+ field_index, attributes, Representation::Tagged());
+ descriptors->Replace(modify_index, &d);
+ if (details.type() != DATA) {
+ int unused_property_fields = new_map->unused_property_fields() - 1;
+ if (unused_property_fields < 0) {
+ unused_property_fields += JSObject::kFieldsAdded;
+ }
+ new_map->set_unused_property_fields(unused_property_fields);
}
- new_map->set_unused_property_fields(unused_property_fields);
+ } else {
+ DCHECK(details.attributes() == attributes);
}
- } else {
- DCHECK(details.attributes() == attributes);
- }
- if (FLAG_trace_generalization) {
- HeapType* field_type =
- (details.type() == DATA)
- ? map->instance_descriptors()->GetFieldType(modify_index)
- : NULL;
- map->PrintGeneralization(
- stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
- new_map->NumberOfOwnDescriptors(),
- details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
- details.representation(), Representation::Tagged(), field_type,
- HeapType::Any());
+ if (FLAG_trace_generalization) {
+ HeapType* field_type =
+ (details.type() == DATA)
+ ? map->instance_descriptors()->GetFieldType(modify_index)
+ : NULL;
+ map->PrintGeneralization(
+ stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
+ new_map->NumberOfOwnDescriptors(),
+ details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
+ details.representation(), Representation::Tagged(), field_type,
+ HeapType::Any());
+ }
}
return new_map;
}
-// static
-Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
- int modify_index,
- StoreMode store_mode,
- const char* reason) {
- PropertyDetails details =
- map->instance_descriptors()->GetDetails(modify_index);
- return CopyGeneralizeAllRepresentations(map, modify_index, store_mode,
- details.attributes(), reason);
-}
-
-
void Map::DeprecateTransitionTree() {
if (is_deprecated()) return;
if (HasTransitionArray()) {
@@ -2172,6 +2183,13 @@ void Map::DeprecateTransitionTree() {
}
+static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
+ if (obj1 == obj2) return true; // Valid for both kData and kAccessor kinds.
+ // TODO(ishell): compare AccessorPairs.
+ return false;
+}
+
+
// Invalidates a transition target at |key|, and installs |new_descriptors| over
// the current instance_descriptors to ensure proper sharing of descriptor
// arrays.
@@ -2242,16 +2260,22 @@ Map* Map::FindLastMatchMap(int verbatim,
DescriptorArray* next_descriptors = next->instance_descriptors();
PropertyDetails next_details = next_descriptors->GetDetails(i);
- if (details.type() != next_details.type()) break;
- if (details.attributes() != next_details.attributes()) break;
+ DCHECK_EQ(details.kind(), next_details.kind());
+ DCHECK_EQ(details.attributes(), next_details.attributes());
+ if (details.location() != next_details.location()) break;
if (!details.representation().Equals(next_details.representation())) break;
- if (next_details.type() == DATA) {
- if (!descriptors->GetFieldType(i)->NowIs(
- next_descriptors->GetFieldType(i))) break;
+
+ if (next_details.location() == kField) {
+ HeapType* next_field_type = next_descriptors->GetFieldType(i);
+ if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
+ break;
+ }
} else {
- if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break;
+ if (!EqualImmutableValues(descriptors->GetValue(i),
+ next_descriptors->GetValue(i))) {
+ break;
+ }
}
-
current = next;
}
return current;
@@ -2367,16 +2391,42 @@ void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
}
-// Generalize the representation of the descriptor at |modify_index|.
-// This method rewrites the transition tree to reflect the new change. To avoid
-// high degrees over polymorphism, and to stabilize quickly, on every rewrite
-// the new type is deduced by merging the current type with any potential new
-// (partial) version of the type in the transition tree.
+static inline Handle<HeapType> GetFieldType(Isolate* isolate,
+ Handle<DescriptorArray> descriptors,
+ int descriptor,
+ PropertyLocation location,
+ Representation representation) {
+#ifdef DEBUG
+ PropertyDetails details = descriptors->GetDetails(descriptor);
+ DCHECK_EQ(kData, details.kind());
+ DCHECK_EQ(details.location(), location);
+#endif
+ if (location == kField) {
+ return handle(descriptors->GetFieldType(descriptor), isolate);
+ } else {
+ return descriptors->GetValue(descriptor)
+ ->OptimalType(isolate, representation);
+ }
+}
+
+
+// Reconfigures property at |modify_index| with |new_kind|, |new_attributes|,
+// |store_mode| and/or |new_representation|/|new_field_type|.
+// If |modify_index| is negative then no properties are reconfigured but the
+// map is migrated to the up-to-date non-deprecated state.
+//
+// This method rewrites or completes the transition tree to reflect the new
+// change. To avoid high degrees over polymorphism, and to stabilize quickly,
+// on every rewrite the new type is deduced by merging the current type with
+// any potential new (partial) version of the type in the transition tree.
// To do this, on each rewrite:
// - Search the root of the transition tree using FindRootMap.
-// - Find |target_map|, the newest matching version of this map using the keys
-// in the |old_map|'s descriptor array to walk the transition tree.
-// - Merge/generalize the descriptor array of the |old_map| and |target_map|.
+// - Find |target_map|, the newest matching version of this map using the
+// virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
+// |modify_index| is considered to be of |new_kind| and having
+// |new_attributes|) to walk the transition tree.
+// - Merge/generalize the "enhanced" descriptor array of the |old_map| and
+// descriptor array of the |target_map|.
// - Generalize the |modify_index| descriptor using |new_representation| and
// |new_field_type|.
// - Walk the tree again starting from the root towards |target_map|. Stop at
@@ -2386,68 +2436,113 @@ void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
// Return it.
// - Otherwise, invalidate the outdated transition target from |target_map|, and
// replace its transition tree with a new branch for the updated descriptors.
-Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
- int modify_index,
- Representation new_representation,
- Handle<HeapType> new_field_type,
- StoreMode store_mode) {
+Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
+ PropertyKind new_kind,
+ PropertyAttributes new_attributes,
+ Representation new_representation,
+ Handle<HeapType> new_field_type,
+ StoreMode store_mode) {
+ DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet.
+ DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
Isolate* isolate = old_map->GetIsolate();
Handle<DescriptorArray> old_descriptors(
old_map->instance_descriptors(), isolate);
int old_nof = old_map->NumberOfOwnDescriptors();
- PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
- Representation old_representation = old_details.representation();
-
- // It's fine to transition from None to anything but double without any
- // modification to the object, because the default uninitialized value for
- // representation None can be overwritten by both smi and tagged values.
- // Doubles, however, would require a box allocation.
- if (old_representation.IsNone() && !new_representation.IsNone() &&
+
+ // If it's just a representation generalization case (i.e. property kind and
+ // attributes stays unchanged) it's fine to transition from None to anything
+ // but double without any modification to the object, because the default
+ // uninitialized value for representation None can be overwritten by both
+ // smi and tagged values. Doubles, however, would require a box allocation.
+ if (modify_index >= 0 && !new_representation.IsNone() &&
!new_representation.IsDouble()) {
- DCHECK(old_details.type() == DATA);
- if (FLAG_trace_generalization) {
- old_map->PrintGeneralization(
- stdout, "uninitialized field",
- modify_index, old_map->NumberOfOwnDescriptors(),
- old_map->NumberOfOwnDescriptors(), false,
- old_representation, new_representation,
- old_descriptors->GetFieldType(modify_index), *new_field_type);
- }
- Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
+ PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
+ Representation old_representation = old_details.representation();
+
+ if (old_representation.IsNone()) {
+ DCHECK_EQ(new_kind, old_details.kind());
+ DCHECK_EQ(new_attributes, old_details.attributes());
+ DCHECK_EQ(DATA, old_details.type());
+ if (FLAG_trace_generalization) {
+ old_map->PrintGeneralization(
+ stdout, "uninitialized field", modify_index,
+ old_map->NumberOfOwnDescriptors(),
+ old_map->NumberOfOwnDescriptors(), false, old_representation,
+ new_representation, old_descriptors->GetFieldType(modify_index),
+ *new_field_type);
+ }
+ Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
- GeneralizeFieldType(field_owner, modify_index, new_representation,
- new_field_type);
- DCHECK(old_descriptors->GetDetails(modify_index).representation().Equals(
- new_representation));
- DCHECK(old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
- return old_map;
+ GeneralizeFieldType(field_owner, modify_index, new_representation,
+ new_field_type);
+ DCHECK(old_descriptors->GetDetails(modify_index)
+ .representation()
+ .Equals(new_representation));
+ DCHECK(
+ old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
+ return old_map;
+ }
}
// Check the state of the root map.
Handle<Map> root_map(old_map->FindRootMap(), isolate);
if (!old_map->EquivalentToForTransition(*root_map)) {
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
+ new_kind, new_attributes,
"GenAll_NotEquivalent");
}
int root_nof = root_map->NumberOfOwnDescriptors();
- if (modify_index < root_nof) {
+ if (modify_index >= 0 && modify_index < root_nof) {
PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
+ if (old_details.kind() != new_kind ||
+ old_details.attributes() != new_attributes) {
+ return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
+ new_kind, new_attributes,
+ "GenAll_RootModification1");
+ }
if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
(old_details.type() == DATA &&
(!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
!new_representation.fits_into(old_details.representation())))) {
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
- "GenAll_RootModification");
+ new_kind, new_attributes,
+ "GenAll_RootModification2");
}
}
Handle<Map> target_map = root_map;
for (int i = root_nof; i < old_nof; ++i) {
PropertyDetails old_details = old_descriptors->GetDetails(i);
- int j = target_map->SearchTransition(old_details.kind(),
- old_descriptors->GetKey(i),
- old_details.attributes());
+ PropertyKind next_kind;
+ PropertyLocation next_location;
+ PropertyAttributes next_attributes;
+ Representation next_representation;
+ bool property_kind_reconfiguration = false;
+
+ if (modify_index == i) {
+ DCHECK_EQ(FORCE_FIELD, store_mode);
+ property_kind_reconfiguration = old_details.kind() != new_kind;
+
+ next_kind = new_kind;
+ next_location = kField;
+ next_attributes = new_attributes;
+ // If property kind is not reconfigured merge the result with
+ // representation/field type from the old descriptor.
+ next_representation = new_representation;
+ if (!property_kind_reconfiguration) {
+ next_representation =
+ next_representation.generalize(old_details.representation());
+ }
+
+ } else {
+ next_kind = old_details.kind();
+ next_location = old_details.location();
+ next_attributes = old_details.attributes();
+ next_representation = old_details.representation();
+ }
+ int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i),
+ next_attributes);
if (j == TransitionArray::kNotFound) break;
Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
Handle<DescriptorArray> tmp_descriptors = handle(
@@ -2455,42 +2550,48 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
// Check if target map is incompatible.
PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
- PropertyType old_type = old_details.type();
- PropertyType tmp_type = tmp_details.type();
- DCHECK_EQ(old_details.attributes(), tmp_details.attributes());
- if ((tmp_type == ACCESSOR_CONSTANT || old_type == ACCESSOR_CONSTANT) &&
- (tmp_type != old_type ||
- tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) {
+ DCHECK_EQ(next_kind, tmp_details.kind());
+ DCHECK_EQ(next_attributes, tmp_details.attributes());
+ if (next_kind == kAccessor &&
+ !EqualImmutableValues(old_descriptors->GetValue(i),
+ tmp_descriptors->GetValue(i))) {
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
+ new_kind, new_attributes,
"GenAll_Incompatible");
}
- Representation old_representation = old_details.representation();
+ if (next_location == kField && tmp_details.location() == kDescriptor) break;
+
Representation tmp_representation = tmp_details.representation();
- if (!old_representation.fits_into(tmp_representation) ||
- (!new_representation.fits_into(tmp_representation) &&
- modify_index == i)) {
- break;
- }
- if (tmp_type == DATA) {
- // Generalize the field type as necessary.
- Handle<HeapType> old_field_type =
- (old_type == DATA) ? handle(old_descriptors->GetFieldType(i), isolate)
- : old_descriptors->GetValue(i)
- ->OptimalType(isolate, tmp_representation);
- if (modify_index == i) {
- old_field_type = GeneralizeFieldType(
- new_field_type, old_field_type, isolate);
- }
- GeneralizeFieldType(tmp_map, i, tmp_representation, old_field_type);
- } else if (tmp_type == DATA_CONSTANT) {
- if (old_type != DATA_CONSTANT ||
- old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) {
- break;
+ if (!next_representation.fits_into(tmp_representation)) break;
+
+ PropertyLocation old_location = old_details.location();
+ PropertyLocation tmp_location = tmp_details.location();
+ if (tmp_location == kField) {
+ if (next_kind == kData) {
+ Handle<HeapType> next_field_type;
+ if (modify_index == i) {
+ next_field_type = new_field_type;
+ if (!property_kind_reconfiguration) {
+ Handle<HeapType> old_field_type =
+ GetFieldType(isolate, old_descriptors, i,
+ old_details.location(), tmp_representation);
+ next_field_type =
+ GeneralizeFieldType(next_field_type, old_field_type, isolate);
+ }
+ } else {
+ Handle<HeapType> old_field_type =
+ GetFieldType(isolate, old_descriptors, i, old_details.location(),
+ tmp_representation);
+ next_field_type = old_field_type;
+ }
+ GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
}
- } else {
- DCHECK_EQ(tmp_type, old_type);
- DCHECK_EQ(tmp_descriptors->GetValue(i), old_descriptors->GetValue(i));
+ } else if (old_location == kField ||
+ !EqualImmutableValues(old_descriptors->GetValue(i),
+ tmp_descriptors->GetValue(i))) {
+ break;
}
+ DCHECK(!tmp_map->is_deprecated());
target_map = tmp_map;
}
@@ -2500,37 +2601,55 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
int target_nof = target_map->NumberOfOwnDescriptors();
if (target_nof == old_nof &&
(store_mode != FORCE_FIELD ||
- target_descriptors->GetDetails(modify_index).type() == DATA)) {
- DCHECK(modify_index < target_nof);
- DCHECK(new_representation.fits_into(
- target_descriptors->GetDetails(modify_index).representation()));
- DCHECK(
- target_descriptors->GetDetails(modify_index).type() != DATA ||
- new_field_type->NowIs(target_descriptors->GetFieldType(modify_index)));
+ (modify_index >= 0 &&
+ target_descriptors->GetDetails(modify_index).location() == kField))) {
+#ifdef DEBUG
+ if (modify_index >= 0) {
+ PropertyDetails details = target_descriptors->GetDetails(modify_index);
+ DCHECK_EQ(new_kind, details.kind());
+ DCHECK_EQ(new_attributes, details.attributes());
+ DCHECK(new_representation.fits_into(details.representation()));
+ DCHECK(details.location() != kField ||
+ new_field_type->NowIs(
+ target_descriptors->GetFieldType(modify_index)));
+ }
+#endif
return target_map;
}
// Find the last compatible target map in the transition tree.
for (int i = target_nof; i < old_nof; ++i) {
PropertyDetails old_details = old_descriptors->GetDetails(i);
- int j = target_map->SearchTransition(old_details.kind(),
- old_descriptors->GetKey(i),
- old_details.attributes());
+ PropertyKind next_kind;
+ PropertyAttributes next_attributes;
+ if (modify_index == i) {
+ next_kind = new_kind;
+ next_attributes = new_attributes;
+ } else {
+ next_kind = old_details.kind();
+ next_attributes = old_details.attributes();
+ }
+ int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i),
+ next_attributes);
if (j == TransitionArray::kNotFound) break;
Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
Handle<DescriptorArray> tmp_descriptors(
tmp_map->instance_descriptors(), isolate);
// Check if target map is compatible.
+#ifdef DEBUG
PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
- DCHECK_EQ(old_details.attributes(), tmp_details.attributes());
- if ((tmp_details.type() == ACCESSOR_CONSTANT ||
- old_details.type() == ACCESSOR_CONSTANT) &&
- (tmp_details.type() != old_details.type() ||
- tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) {
+ DCHECK_EQ(next_kind, tmp_details.kind());
+ DCHECK_EQ(next_attributes, tmp_details.attributes());
+#endif
+ if (next_kind == kAccessor &&
+ !EqualImmutableValues(old_descriptors->GetValue(i),
+ tmp_descriptors->GetValue(i))) {
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
+ new_kind, new_attributes,
"GenAll_Incompatible");
}
+ DCHECK(!tmp_map->is_deprecated());
target_map = tmp_map;
}
target_nof = target_map->NumberOfOwnDescriptors();
@@ -2553,7 +2672,7 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
int current_offset = 0;
for (int i = 0; i < root_nof; ++i) {
PropertyDetails old_details = old_descriptors->GetDetails(i);
- if (old_details.type() == DATA) {
+ if (old_details.location() == kField) {
current_offset += old_details.field_width_in_words();
}
Descriptor d(handle(old_descriptors->GetKey(i), isolate),
@@ -2567,43 +2686,85 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
PropertyDetails old_details = old_descriptors->GetDetails(i);
PropertyDetails target_details = target_descriptors->GetDetails(i);
- target_details = target_details.CopyWithRepresentation(
- old_details.representation().generalize(
- target_details.representation()));
+
+ PropertyKind next_kind;
+ PropertyAttributes next_attributes;
+ PropertyLocation next_location;
+ Representation next_representation;
+ bool property_kind_reconfiguration = false;
+
if (modify_index == i) {
- target_details = target_details.CopyWithRepresentation(
- new_representation.generalize(target_details.representation()));
- }
- DCHECK_EQ(old_details.attributes(), target_details.attributes());
- if (old_details.type() == DATA || target_details.type() == DATA ||
- (modify_index == i && store_mode == FORCE_FIELD) ||
- (target_descriptors->GetValue(i) != old_descriptors->GetValue(i))) {
- Handle<HeapType> old_field_type =
- (old_details.type() == DATA)
- ? handle(old_descriptors->GetFieldType(i), isolate)
- : old_descriptors->GetValue(i)
- ->OptimalType(isolate, target_details.representation());
- Handle<HeapType> target_field_type =
- (target_details.type() == DATA)
- ? handle(target_descriptors->GetFieldType(i), isolate)
- : target_descriptors->GetValue(i)
- ->OptimalType(isolate, target_details.representation());
- target_field_type = GeneralizeFieldType(
- target_field_type, old_field_type, isolate);
- if (modify_index == i) {
- target_field_type = GeneralizeFieldType(
- target_field_type, new_field_type, isolate);
+ DCHECK_EQ(FORCE_FIELD, store_mode);
+ property_kind_reconfiguration = old_details.kind() != new_kind;
+
+ next_kind = new_kind;
+ next_attributes = new_attributes;
+ next_location = kField;
+
+ // Merge new representation/field type with ones from the target
+ // descriptor. If property kind is not reconfigured merge the result with
+ // representation/field type from the old descriptor.
+ next_representation =
+ new_representation.generalize(target_details.representation());
+ if (!property_kind_reconfiguration) {
+ next_representation =
+ next_representation.generalize(old_details.representation());
}
- DataDescriptor d(target_key, current_offset, target_field_type,
- target_details.attributes(),
- target_details.representation());
- current_offset += d.GetDetails().field_width_in_words();
- new_descriptors->Set(i, &d);
} else {
- DCHECK_NE(DATA, target_details.type());
- Descriptor d(target_key,
- handle(target_descriptors->GetValue(i), isolate),
- target_details);
+ // Merge old_descriptor and target_descriptor entries.
+ DCHECK_EQ(target_details.kind(), old_details.kind());
+ next_kind = target_details.kind();
+ next_attributes = target_details.attributes();
+ next_location =
+ old_details.location() == kField ||
+ target_details.location() == kField ||
+ !EqualImmutableValues(target_descriptors->GetValue(i),
+ old_descriptors->GetValue(i))
+ ? kField
+ : kDescriptor;
+
+ next_representation = old_details.representation().generalize(
+ target_details.representation());
+ }
+ DCHECK_EQ(next_kind, target_details.kind());
+ DCHECK_EQ(next_attributes, target_details.attributes());
+
+ if (next_location == kField) {
+ if (next_kind == kData) {
+ Handle<HeapType> target_field_type =
+ GetFieldType(isolate, target_descriptors, i,
+ target_details.location(), next_representation);
+
+ Handle<HeapType> next_field_type;
+ if (modify_index == i) {
+ next_field_type =
+ GeneralizeFieldType(target_field_type, new_field_type, isolate);
+ if (!property_kind_reconfiguration) {
+ Handle<HeapType> old_field_type =
+ GetFieldType(isolate, old_descriptors, i,
+ old_details.location(), next_representation);
+ next_field_type =
+ GeneralizeFieldType(next_field_type, old_field_type, isolate);
+ }
+ } else {
+ Handle<HeapType> old_field_type =
+ GetFieldType(isolate, old_descriptors, i, old_details.location(),
+ next_representation);
+ next_field_type =
+ GeneralizeFieldType(target_field_type, old_field_type, isolate);
+ }
+ DataDescriptor d(target_key, current_offset, next_field_type,
+ next_attributes, next_representation);
+ current_offset += d.GetDetails().field_width_in_words();
+ new_descriptors->Set(i, &d);
+ } else {
+ UNIMPLEMENTED(); // TODO(ishell): implement.
+ }
+ } else {
+ PropertyDetails details(next_attributes, next_kind, next_location,
+ next_representation);
+ Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
+ details);
new_descriptors->Set(i, &d);
}
}
@@ -2612,47 +2773,74 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
for (int i = target_nof; i < old_nof; ++i) {
PropertyDetails old_details = old_descriptors->GetDetails(i);
Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
+
+ // Merge old_descriptor entry and modified details together.
+ PropertyKind next_kind;
+ PropertyAttributes next_attributes;
+ PropertyLocation next_location;
+ Representation next_representation;
+ bool property_kind_reconfiguration = false;
+
if (modify_index == i) {
- old_details = old_details.CopyWithRepresentation(
- new_representation.generalize(old_details.representation()));
- }
- if (old_details.type() == DATA) {
- Handle<HeapType> old_field_type(
- old_descriptors->GetFieldType(i), isolate);
- if (modify_index == i) {
- old_field_type = GeneralizeFieldType(
- old_field_type, new_field_type, isolate);
+ DCHECK_EQ(FORCE_FIELD, store_mode);
+ // In case of property kind reconfiguration it is not necessary to
+ // take into account representation/field type of the old descriptor.
+ property_kind_reconfiguration = old_details.kind() != new_kind;
+
+ next_kind = new_kind;
+ next_attributes = new_attributes;
+ next_location = kField;
+ next_representation = new_representation;
+ if (!property_kind_reconfiguration) {
+ next_representation =
+ next_representation.generalize(old_details.representation());
}
- DataDescriptor d(old_key, current_offset, old_field_type,
- old_details.attributes(), old_details.representation());
- current_offset += d.GetDetails().field_width_in_words();
- new_descriptors->Set(i, &d);
} else {
- DCHECK(old_details.type() == DATA_CONSTANT ||
- old_details.type() == ACCESSOR_CONSTANT);
- if (modify_index == i && store_mode == FORCE_FIELD) {
- DataDescriptor d(
- old_key, current_offset,
- GeneralizeFieldType(old_descriptors->GetValue(i)->OptimalType(
- isolate, old_details.representation()),
- new_field_type, isolate),
- old_details.attributes(), old_details.representation());
+ next_kind = old_details.kind();
+ next_attributes = old_details.attributes();
+ next_location = old_details.location();
+ next_representation = old_details.representation();
+ }
+
+ if (next_location == kField) {
+ if (next_kind == kData) {
+ Handle<HeapType> next_field_type;
+ if (modify_index == i) {
+ next_field_type = new_field_type;
+ if (!property_kind_reconfiguration) {
+ Handle<HeapType> old_field_type =
+ GetFieldType(isolate, old_descriptors, i,
+ old_details.location(), next_representation);
+ old_field_type =
+ GeneralizeFieldType(old_field_type, next_field_type, isolate);
+ }
+ } else {
+ Handle<HeapType> old_field_type =
+ GetFieldType(isolate, old_descriptors, i, old_details.location(),
+ next_representation);
+ next_field_type = old_field_type;
+ }
+
+ DataDescriptor d(old_key, current_offset, next_field_type,
+ next_attributes, next_representation);
current_offset += d.GetDetails().field_width_in_words();
new_descriptors->Set(i, &d);
} else {
- DCHECK_NE(DATA, old_details.type());
- Descriptor d(old_key,
- handle(old_descriptors->GetValue(i), isolate),
- old_details);
- new_descriptors->Set(i, &d);
+ UNIMPLEMENTED(); // TODO(ishell): implement.
}
+ } else {
+ PropertyDetails details(next_attributes, next_kind, next_location,
+ next_representation);
+ Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
+ details);
+ new_descriptors->Set(i, &d);
}
}
new_descriptors->Sort();
DCHECK(store_mode != FORCE_FIELD ||
- new_descriptors->GetDetails(modify_index).type() == DATA);
+ new_descriptors->GetDetails(modify_index).location() == kField);
Handle<Map> split_map(root_map->FindLastMatchMap(
root_nof, old_nof, *new_descriptors), isolate);
@@ -2661,21 +2849,31 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
Handle<LayoutDescriptor> new_layout_descriptor =
LayoutDescriptor::New(split_map, new_descriptors, old_nof);
- PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
+
+ PropertyKind split_kind;
+ PropertyAttributes split_attributes;
+ if (modify_index == split_nof) {
+ split_kind = new_kind;
+ split_attributes = new_attributes;
+ } else {
+ PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
+ split_kind = split_prop_details.kind();
+ split_attributes = split_prop_details.attributes();
+ }
bool transition_target_deprecated = split_map->DeprecateTarget(
- split_prop_details.kind(), old_descriptors->GetKey(split_nof),
- split_prop_details.attributes(), *new_descriptors,
- *new_layout_descriptor);
+ split_kind, old_descriptors->GetKey(split_nof), split_attributes,
+ *new_descriptors, *new_layout_descriptor);
// If |transition_target_deprecated| is true then the transition array
// already contains entry for given descriptor. This means that the transition
// could be inserted regardless of whether transitions array is full or not.
if (!transition_target_deprecated && !split_map->CanHaveMoreTransitions()) {
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
+ new_kind, new_attributes,
"GenAll_CantHaveMoreTransitions");
}
- if (FLAG_trace_generalization) {
+ if (FLAG_trace_generalization && modify_index >= 0) {
PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
Handle<HeapType> old_field_type =
@@ -2692,7 +2890,7 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
isolate);
old_map->PrintGeneralization(
stdout, "", modify_index, split_nof, old_nof,
- old_details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
+ old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
old_details.representation(), new_details.representation(),
*old_field_type, *new_field_type);
}
@@ -2713,10 +2911,11 @@ Handle<Map> Map::GeneralizeAllFieldRepresentations(
Handle<Map> map) {
Handle<DescriptorArray> descriptors(map->instance_descriptors());
for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
- if (descriptors->GetDetails(i).type() == DATA) {
- map = GeneralizeRepresentation(map, i, Representation::Tagged(),
- HeapType::Any(map->GetIsolate()),
- FORCE_FIELD);
+ PropertyDetails details = descriptors->GetDetails(i);
+ if (details.type() == DATA) {
+ map = ReconfigureProperty(map, i, kData, details.attributes(),
+ Representation::Tagged(),
+ HeapType::Any(map->GetIsolate()), FORCE_FIELD);
}
}
return map;
@@ -2740,9 +2939,9 @@ MaybeHandle<Map> Map::TryUpdate(Handle<Map> map) {
// static
Handle<Map> Map::Update(Handle<Map> map) {
if (!map->is_deprecated()) return map;
- return GeneralizeRepresentation(map, 0, Representation::None(),
- HeapType::None(map->GetIsolate()),
- ALLOW_IN_DESCRIPTOR);
+ return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
+ HeapType::None(map->GetIsolate()),
+ ALLOW_IN_DESCRIPTOR);
}
@@ -3952,7 +4151,6 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
}
it.ReconfigureDataProperty(value, attributes);
- it.PrepareForDataProperty(value);
value = it.WriteDataValue(value);
if (is_observed) {
@@ -3977,7 +4175,6 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
if (is_observed) old_value = it.GetDataValue();
it.ReconfigureDataProperty(value, attributes);
- it.PrepareForDataProperty(value);
value = it.WriteDataValue(value);
if (is_observed) {
@@ -5846,7 +6043,7 @@ int Map::NextFreePropertyIndex() {
DescriptorArray* descs = instance_descriptors();
for (int i = 0; i < number_of_own_descriptors; i++) {
PropertyDetails details = descs->GetDetails(i);
- if (details.type() == DATA) {
+ if (details.location() == kField) {
int candidate = details.field_index() + details.field_width_in_words();
if (candidate > free_index) free_index = candidate;
}
@@ -6841,7 +7038,7 @@ Handle<Map> Map::CopyInstallDescriptors(
int unused_property_fields = map->unused_property_fields();
PropertyDetails details = descriptors->GetDetails(new_descriptor);
- if (details.type() == DATA) {
+ if (details.location() == kField) {
unused_property_fields = map->unused_property_fields() - 1;
if (unused_property_fields < 0) {
unused_property_fields += JSObject::kFieldsAdded;
@@ -7059,11 +7256,13 @@ Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
if (descriptors->CanHoldValue(descriptor, *value)) return map;
Isolate* isolate = map->GetIsolate();
+ PropertyAttributes attributes =
+ descriptors->GetDetails(descriptor).attributes();
Representation representation = value->OptimalRepresentation();
Handle<HeapType> type = value->OptimalType(isolate, representation);
- return GeneralizeRepresentation(map, descriptor, representation, type,
- FORCE_FIELD);
+ return ReconfigureProperty(map, descriptor, kData, attributes, representation,
+ type, FORCE_FIELD);
}
@@ -7120,15 +7319,29 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
}
-Handle<Map> Map::ReconfigureDataProperty(Handle<Map> map, int descriptor,
- PropertyAttributes attributes) {
+Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
+ PropertyKind kind,
+ PropertyAttributes attributes) {
// Dictionaries have to be reconfigured in-place.
DCHECK(!map->is_dictionary_map());
- // For now, give up on transitioning and just create a unique map.
- // TODO(verwaest/ishell): Cache transitions with different attributes.
- return CopyGeneralizeAllRepresentations(
- map, descriptor, FORCE_FIELD, attributes, "GenAll_AttributesMismatch");
+ if (!map->GetBackPointer()->IsMap()) {
+ // There is no benefit from reconstructing transition tree for maps without
+ // back pointers.
+ return CopyGeneralizeAllRepresentations(
+ map, descriptor, FORCE_FIELD, kind, attributes,
+ "GenAll_AttributesMismatchProtoMap");
+ }
+
+ if (FLAG_trace_generalization) {
+ map->PrintReconfiguration(stdout, descriptor, kind, attributes);
+ }
+
+ Isolate* isolate = map->GetIsolate();
+ Handle<Map> new_map = ReconfigureProperty(
+ map, descriptor, kind, attributes, Representation::None(),
+ HeapType::None(isolate), FORCE_FIELD);
+ return new_map;
}
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698