| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 3ea5b19c0743a3b700350233b7e4712b33ccd711..743819918abde5931a6fc73af24472a5eeccada5 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -49,6 +49,7 @@
|
| #include "src/log.h"
|
| #include "src/lookup.h"
|
| #include "src/macro-assembler.h"
|
| +#include "src/map-updater.h"
|
| #include "src/messages.h"
|
| #include "src/objects-body-descriptors-inl.h"
|
| #include "src/property-descriptor.h"
|
| @@ -3326,7 +3327,7 @@ Context* JSReceiver::GetCreationContext() {
|
| return function->context()->native_context();
|
| }
|
|
|
| -static Handle<Object> WrapType(Handle<FieldType> type) {
|
| +Handle<Object> Map::WrapType(Handle<FieldType> type) {
|
| if (type->IsClass()) return Map::WeakCellForMap(type->AsClass());
|
| return type;
|
| }
|
| @@ -3969,13 +3970,6 @@ 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;
|
| -}
|
| -
|
| -
|
| // Installs |new_descriptors| over the current instance_descriptors to ensure
|
| // proper sharing of descriptor arrays.
|
| void Map::ReplaceDescriptors(DescriptorArray* new_descriptors,
|
| @@ -4018,47 +4012,6 @@ Map* Map::FindRootMap() {
|
| }
|
|
|
|
|
| -Map* Map::FindLastMatchMap(int verbatim,
|
| - int length,
|
| - DescriptorArray* descriptors) {
|
| - DisallowHeapAllocation no_allocation;
|
| -
|
| - // This can only be called on roots of transition trees.
|
| - DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
|
| -
|
| - Map* current = this;
|
| -
|
| - for (int i = verbatim; i < length; i++) {
|
| - Name* name = descriptors->GetKey(i);
|
| - PropertyDetails details = descriptors->GetDetails(i);
|
| - Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
|
| - details.attributes());
|
| - if (next == NULL) break;
|
| - DescriptorArray* next_descriptors = next->instance_descriptors();
|
| -
|
| - PropertyDetails next_details = next_descriptors->GetDetails(i);
|
| - 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.location() == kField) {
|
| - FieldType* next_field_type = next_descriptors->GetFieldType(i);
|
| - if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
|
| - break;
|
| - }
|
| - } else {
|
| - if (!EqualImmutableValues(descriptors->GetValue(i),
|
| - next_descriptors->GetValue(i))) {
|
| - break;
|
| - }
|
| - }
|
| - current = next;
|
| - }
|
| - return current;
|
| -}
|
| -
|
| -
|
| Map* Map::FindFieldOwner(int descriptor) {
|
| DisallowHeapAllocation no_allocation;
|
| DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
|
| @@ -4139,9 +4092,9 @@ Handle<FieldType> Map::GeneralizeFieldType(Representation rep1,
|
|
|
|
|
| // static
|
| -void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
|
| - Representation new_representation,
|
| - Handle<FieldType> new_field_type) {
|
| +void Map::GeneralizeField(Handle<Map> map, int modify_index,
|
| + Representation new_representation,
|
| + Handle<FieldType> new_field_type) {
|
| Isolate* isolate = map->GetIsolate();
|
|
|
| // Check if we actually need to generalize the field type at all.
|
| @@ -4156,8 +4109,8 @@ void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
|
| // Checking old_field_type for being cleared is not necessary because
|
| // the NowIs check below would fail anyway in that case.
|
| new_field_type->NowIs(old_field_type)) {
|
| - DCHECK(Map::GeneralizeFieldType(old_representation, old_field_type,
|
| - new_representation, new_field_type, isolate)
|
| + DCHECK(GeneralizeFieldType(old_representation, old_field_type,
|
| + new_representation, new_field_type, isolate)
|
| ->NowIs(old_field_type));
|
| return;
|
| }
|
| @@ -4190,579 +4143,41 @@ void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
|
| }
|
| }
|
|
|
| -static inline Handle<FieldType> 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 elements kind to |new_elements_kind| and/or 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/create a |root_map| with requested |new_elements_kind|.
|
| -// - 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
|
| -// |split_map|, the first map who's descriptor array does not match the merged
|
| -// descriptor array.
|
| -// - If |target_map| == |split_map|, |target_map| is in the expected state.
|
| -// 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::Reconfigure(Handle<Map> old_map,
|
| - ElementsKind new_elements_kind, int modify_index,
|
| - PropertyKind new_kind,
|
| - PropertyAttributes new_attributes,
|
| - Representation new_representation,
|
| - Handle<FieldType> 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();
|
| -
|
| - // 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() &&
|
| - old_map->elements_kind() == new_elements_kind) {
|
| - 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,
|
| - handle(old_descriptors->GetFieldType(modify_index), isolate),
|
| - MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
|
| - }
|
| - 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;
|
| - }
|
| - }
|
| -
|
| - // 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, new_elements_kind, modify_index, store_mode, new_kind,
|
| - new_attributes, "GenAll_NotEquivalent");
|
| - }
|
| -
|
| - ElementsKind from_kind = root_map->elements_kind();
|
| - ElementsKind to_kind = new_elements_kind;
|
| - // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
|
| - if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
|
| - to_kind != SLOW_STRING_WRAPPER_ELEMENTS &&
|
| - to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
|
| - !(IsTransitionableFastElementsKind(from_kind) &&
|
| - IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
|
| - return CopyGeneralizeAllRepresentations(
|
| - old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
|
| - "GenAll_InvalidElementsTransition");
|
| - }
|
| - int root_nof = root_map->NumberOfOwnDescriptors();
|
| - 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, to_kind, 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, to_kind, modify_index, store_mode, new_kind, new_attributes,
|
| - "GenAll_RootModification2");
|
| - }
|
| - }
|
| -
|
| - // From here on, use the map with correct elements kind as root map.
|
| - if (from_kind != to_kind) {
|
| - root_map = Map::AsElementsKind(root_map, to_kind);
|
| - }
|
| -
|
| - Handle<Map> target_map = root_map;
|
| - for (int i = root_nof; i < old_nof; ++i) {
|
| - PropertyDetails old_details = old_descriptors->GetDetails(i);
|
| - 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();
|
| - }
|
| - Map* transition = TransitionArray::SearchTransition(
|
| - *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
|
| - if (transition == NULL) break;
|
| - Handle<Map> tmp_map(transition, isolate);
|
| -
|
| - Handle<DescriptorArray> tmp_descriptors = handle(
|
| - tmp_map->instance_descriptors(), isolate);
|
| -
|
| - // Check if target map is incompatible.
|
| - PropertyDetails tmp_details = tmp_descriptors->GetDetails(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, to_kind, modify_index, store_mode, new_kind, new_attributes,
|
| - "GenAll_Incompatible");
|
| - }
|
| - if (next_location == kField && tmp_details.location() == kDescriptor) break;
|
| -
|
| - Representation tmp_representation = tmp_details.representation();
|
| - 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<FieldType> next_field_type;
|
| - if (modify_index == i) {
|
| - next_field_type = new_field_type;
|
| - if (!property_kind_reconfiguration) {
|
| - Handle<FieldType> old_field_type =
|
| - GetFieldType(isolate, old_descriptors, i,
|
| - old_details.location(), tmp_representation);
|
| - Representation old_representation = old_details.representation();
|
| - next_field_type = GeneralizeFieldType(
|
| - old_representation, old_field_type, new_representation,
|
| - next_field_type, isolate);
|
| - }
|
| - } else {
|
| - Handle<FieldType> 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 if (old_location == kField ||
|
| - !EqualImmutableValues(old_descriptors->GetValue(i),
|
| - tmp_descriptors->GetValue(i))) {
|
| - break;
|
| - }
|
| - DCHECK(!tmp_map->is_deprecated());
|
| - target_map = tmp_map;
|
| - }
|
| -
|
| - // Directly change the map if the target map is more general.
|
| - Handle<DescriptorArray> target_descriptors(
|
| - target_map->instance_descriptors(), isolate);
|
| - int target_nof = target_map->NumberOfOwnDescriptors();
|
| - if (target_nof == old_nof &&
|
| - (store_mode != FORCE_FIELD ||
|
| - (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
|
| - if (*target_map != *old_map) {
|
| - old_map->NotifyLeafMapLayoutChange();
|
| - }
|
| - 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);
|
| - 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();
|
| - }
|
| - Map* transition = TransitionArray::SearchTransition(
|
| - *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
|
| - if (transition == NULL) break;
|
| - Handle<Map> tmp_map(transition, 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(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, to_kind, modify_index, store_mode, new_kind, new_attributes,
|
| - "GenAll_Incompatible");
|
| - }
|
| - DCHECK(!tmp_map->is_deprecated());
|
| - target_map = tmp_map;
|
| - }
|
| - target_nof = target_map->NumberOfOwnDescriptors();
|
| - target_descriptors = handle(target_map->instance_descriptors(), isolate);
|
| -
|
| - // Allocate a new descriptor array large enough to hold the required
|
| - // descriptors, with minimally the exact same size as the old descriptor
|
| - // array.
|
| - int new_slack = Max(
|
| - old_nof, old_descriptors->number_of_descriptors()) - old_nof;
|
| - Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
|
| - isolate, old_nof, new_slack);
|
| - DCHECK(new_descriptors->length() > target_descriptors->length() ||
|
| - new_descriptors->NumberOfSlackDescriptors() > 0 ||
|
| - new_descriptors->number_of_descriptors() ==
|
| - old_descriptors->number_of_descriptors());
|
| - DCHECK(new_descriptors->number_of_descriptors() == old_nof);
|
| -
|
| - // 0 -> |root_nof|
|
| - int current_offset = 0;
|
| - for (int i = 0; i < root_nof; ++i) {
|
| - PropertyDetails old_details = old_descriptors->GetDetails(i);
|
| - if (old_details.location() == kField) {
|
| - current_offset += old_details.field_width_in_words();
|
| - }
|
| - Descriptor d(handle(old_descriptors->GetKey(i), isolate),
|
| - handle(old_descriptors->GetValue(i), isolate),
|
| - old_details);
|
| - new_descriptors->Set(i, &d);
|
| - }
|
| -
|
| - // |root_nof| -> |target_nof|
|
| - for (int i = root_nof; i < target_nof; ++i) {
|
| - Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
|
| - PropertyDetails old_details = old_descriptors->GetDetails(i);
|
| - PropertyDetails target_details = target_descriptors->GetDetails(i);
|
| -
|
| - PropertyKind next_kind;
|
| - PropertyAttributes next_attributes;
|
| - PropertyLocation next_location;
|
| - 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_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());
|
| - }
|
| - } else {
|
| - // 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<FieldType> target_field_type =
|
| - GetFieldType(isolate, target_descriptors, i,
|
| - target_details.location(), next_representation);
|
| -
|
| - Handle<FieldType> next_field_type;
|
| - if (modify_index == i) {
|
| - next_field_type = GeneralizeFieldType(
|
| - target_details.representation(), target_field_type,
|
| - new_representation, new_field_type, isolate);
|
| - if (!property_kind_reconfiguration) {
|
| - Handle<FieldType> old_field_type =
|
| - GetFieldType(isolate, old_descriptors, i,
|
| - old_details.location(), next_representation);
|
| - next_field_type = GeneralizeFieldType(
|
| - old_details.representation(), old_field_type,
|
| - next_representation, next_field_type, isolate);
|
| - }
|
| - } else {
|
| - Handle<FieldType> old_field_type =
|
| - GetFieldType(isolate, old_descriptors, i, old_details.location(),
|
| - next_representation);
|
| - next_field_type = GeneralizeFieldType(
|
| - old_details.representation(), old_field_type, next_representation,
|
| - target_field_type, isolate);
|
| - }
|
| - Handle<Object> wrapped_type(WrapType(next_field_type));
|
| - Descriptor d =
|
| - Descriptor::DataField(target_key, current_offset, wrapped_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);
|
| - }
|
| - }
|
| -
|
| - // |target_nof| -> |old_nof|
|
| - 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) {
|
| - 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());
|
| - }
|
| - } else {
|
| - 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<FieldType> next_field_type;
|
| - if (modify_index == i) {
|
| - next_field_type = new_field_type;
|
| - if (!property_kind_reconfiguration) {
|
| - Handle<FieldType> old_field_type =
|
| - GetFieldType(isolate, old_descriptors, i,
|
| - old_details.location(), next_representation);
|
| - next_field_type = GeneralizeFieldType(
|
| - old_details.representation(), old_field_type,
|
| - next_representation, next_field_type, isolate);
|
| - }
|
| - } else {
|
| - Handle<FieldType> old_field_type =
|
| - GetFieldType(isolate, old_descriptors, i, old_details.location(),
|
| - next_representation);
|
| - next_field_type = old_field_type;
|
| - }
|
| -
|
| - Handle<Object> wrapped_type(WrapType(next_field_type));
|
| -
|
| - Descriptor d =
|
| - Descriptor::DataField(old_key, current_offset, wrapped_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(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).location() == kField);
|
| -
|
| - Handle<Map> split_map(root_map->FindLastMatchMap(
|
| - root_nof, old_nof, *new_descriptors), isolate);
|
| - int split_nof = split_map->NumberOfOwnDescriptors();
|
| - DCHECK_NE(old_nof, 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();
|
| - }
|
| -
|
| - // Invalidate a transition target at |key|.
|
| - Map* maybe_transition = TransitionArray::SearchTransition(
|
| - *split_map, split_kind, old_descriptors->GetKey(split_nof),
|
| - split_attributes);
|
| - if (maybe_transition != NULL) {
|
| - maybe_transition->DeprecateTransitionTree();
|
| - }
|
| -
|
| - // If |maybe_transition| is not NULL 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 (maybe_transition == NULL &&
|
| - !TransitionArray::CanHaveMoreTransitions(split_map)) {
|
| - return CopyGeneralizeAllRepresentations(
|
| - old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
|
| - "GenAll_CantHaveMoreTransitions");
|
| - }
|
| -
|
| - old_map->NotifyLeafMapLayoutChange();
|
| -
|
| - if (FLAG_trace_generalization && modify_index >= 0) {
|
| - PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
|
| - PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
|
| - MaybeHandle<FieldType> old_field_type;
|
| - MaybeHandle<FieldType> new_field_type;
|
| - MaybeHandle<Object> old_value;
|
| - MaybeHandle<Object> new_value;
|
| - if (old_details.type() == DATA) {
|
| - old_field_type =
|
| - handle(old_descriptors->GetFieldType(modify_index), isolate);
|
| - } else {
|
| - old_value = handle(old_descriptors->GetValue(modify_index), isolate);
|
| - }
|
| - if (new_details.type() == DATA) {
|
| - new_field_type =
|
| - handle(new_descriptors->GetFieldType(modify_index), isolate);
|
| - } else {
|
| - new_value = handle(new_descriptors->GetValue(modify_index), isolate);
|
| - }
|
| -
|
| - old_map->PrintGeneralization(
|
| - stdout, "", modify_index, split_nof, old_nof,
|
| - old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
|
| - old_details.representation(), new_details.representation(),
|
| - old_field_type, old_value, new_field_type, new_value);
|
| - }
|
| -
|
| - Handle<LayoutDescriptor> new_layout_descriptor =
|
| - LayoutDescriptor::New(split_map, new_descriptors, old_nof);
|
| -
|
| - Handle<Map> new_map =
|
| - AddMissingTransitions(split_map, new_descriptors, new_layout_descriptor);
|
| -
|
| - // Deprecated part of the transition tree is no longer reachable, so replace
|
| - // current instance descriptors in the "survived" part of the tree with
|
| - // the new descriptors to maintain descriptors sharing invariant.
|
| - split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor);
|
| - return new_map;
|
| +// TODO(ishell): remove.
|
| +// static
|
| +Handle<Map> Map::ReconfigureProperty(Handle<Map> map, int modify_index,
|
| + PropertyKind new_kind,
|
| + PropertyAttributes new_attributes,
|
| + Representation new_representation,
|
| + Handle<FieldType> new_field_type,
|
| + StoreMode store_mode) {
|
| + DCHECK_EQ(kData, new_kind); // Only kData case is supported.
|
| + MapUpdater mu(map->GetIsolate(), map);
|
| + return mu.ReconfigureToDataField(modify_index, new_attributes,
|
| + new_representation, new_field_type);
|
| +}
|
| +
|
| +// TODO(ishell): remove.
|
| +// static
|
| +Handle<Map> Map::ReconfigureElementsKind(Handle<Map> map,
|
| + ElementsKind new_elements_kind) {
|
| + MapUpdater mu(map->GetIsolate(), map);
|
| + return mu.ReconfigureElementsKind(new_elements_kind);
|
| }
|
|
|
| -
|
| // Generalize the representation of all DATA descriptors.
|
| Handle<Map> Map::GeneralizeAllFieldRepresentations(
|
| Handle<Map> map) {
|
| + Isolate* isolate = map->GetIsolate();
|
| + Handle<FieldType> any_type = FieldType::Any(isolate);
|
| +
|
| Handle<DescriptorArray> descriptors(map->instance_descriptors());
|
| for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
|
| PropertyDetails details = descriptors->GetDetails(i);
|
| if (details.type() == DATA) {
|
| - map = ReconfigureProperty(map, i, kData, details.attributes(),
|
| - Representation::Tagged(),
|
| - FieldType::Any(map->GetIsolate()), FORCE_FIELD);
|
| + MapUpdater mu(isolate, map);
|
| + map = mu.ReconfigureToDataField(i, details.attributes(),
|
| + Representation::Tagged(), any_type);
|
| }
|
| }
|
| return map;
|
| @@ -4869,9 +4284,8 @@ Map* Map::TryReplayPropertyTransitions(Map* old_map) {
|
| // static
|
| Handle<Map> Map::Update(Handle<Map> map) {
|
| if (!map->is_deprecated()) return map;
|
| - return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
|
| - FieldType::None(map->GetIsolate()),
|
| - ALLOW_IN_DESCRIPTOR);
|
| + MapUpdater mu(map->GetIsolate(), map);
|
| + return mu.Update();
|
| }
|
|
|
| Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
|
| @@ -9753,8 +9167,9 @@ Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor,
|
| Representation representation = value->OptimalRepresentation();
|
| Handle<FieldType> type = value->OptimalType(isolate, representation);
|
|
|
| - return Map::ReconfigureProperty(map, descriptor, kData, attributes,
|
| - representation, type, FORCE_FIELD);
|
| + MapUpdater mu(isolate, map);
|
| + return mu.ReconfigureToDataField(descriptor, attributes, representation,
|
| + type);
|
| }
|
|
|
| } // namespace
|
| @@ -9847,9 +9262,11 @@ Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
|
| }
|
|
|
| Isolate* isolate = map->GetIsolate();
|
| - Handle<Map> new_map = ReconfigureProperty(
|
| - map, descriptor, kind, attributes, Representation::None(),
|
| - FieldType::None(isolate), FORCE_FIELD);
|
| +
|
| + MapUpdater mu(isolate, map);
|
| + DCHECK_EQ(kData, kind); // Only kData case is supported so far.
|
| + Handle<Map> new_map = mu.ReconfigureToDataField(
|
| + descriptor, attributes, Representation::None(), FieldType::None(isolate));
|
| return new_map;
|
| }
|
|
|
|
|