| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 7e15f3005d6cbb035c4d9818eab72cefdc58617d..6c402294b6edb262bd6f816c8f9f3e0fbcd98007 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -1450,19 +1450,31 @@ void JSObject::PrintElementsTransition(
|
|
|
|
|
| void Map::PrintGeneralization(FILE* file,
|
| + const char* reason,
|
| int modify_index,
|
| int split,
|
| int descriptors,
|
| + bool constant_to_field,
|
| Representation old_representation,
|
| Representation new_representation) {
|
| PrintF(file, "[generalizing ");
|
| constructor_name()->PrintOn(file);
|
| PrintF(file, "] ");
|
| String::cast(instance_descriptors()->GetKey(modify_index))->PrintOn(file);
|
| - PrintF(file, ":%s->%s (+%i maps) [",
|
| - old_representation.Mnemonic(),
|
| - new_representation.Mnemonic(),
|
| - descriptors - split);
|
| + if (constant_to_field) {
|
| + PrintF(file, ":c->f");
|
| + } else {
|
| + PrintF(file, ":%s->%s",
|
| + old_representation.Mnemonic(),
|
| + new_representation.Mnemonic());
|
| + }
|
| + PrintF(file, " (");
|
| + if (strlen(reason) > 0) {
|
| + PrintF(file, "%s", reason);
|
| + } else {
|
| + PrintF(file, "+%i maps", descriptors - split);
|
| + }
|
| + PrintF(file, ") [");
|
| JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
|
| PrintF(file, "]\n");
|
| }
|
| @@ -1988,7 +2000,7 @@ MaybeObject* JSObject::AddConstantProperty(
|
| ConstantDescriptor d(name, constant, attributes);
|
|
|
| TransitionFlag flag =
|
| - // Do not add transitions to global objects.
|
| + // Do not add transitions to global objects.
|
| (IsGlobalObject() ||
|
| // Don't add transitions to special properties with non-trivial
|
| // attributes.
|
| @@ -2190,55 +2202,6 @@ MaybeObject* JSObject::ReplaceSlowProperty(Name* name,
|
| }
|
|
|
|
|
| -MaybeObject* JSObject::ConvertTransitionToMapTransition(
|
| - int transition_index,
|
| - Name* name,
|
| - Object* new_value,
|
| - PropertyAttributes attributes) {
|
| - Map* old_map = map();
|
| - Map* old_target = old_map->GetTransition(transition_index);
|
| - Object* result;
|
| -
|
| - MaybeObject* maybe_result = ConvertDescriptorToField(
|
| - name, new_value, attributes, OMIT_TRANSITION_KEEP_REPRESENTATIONS);
|
| - if (!maybe_result->To(&result)) return maybe_result;
|
| -
|
| - if (!HasFastProperties()) return result;
|
| -
|
| - // This method should only be used to convert existing transitions.
|
| - Map* new_map = map();
|
| -
|
| - // TODO(verwaest): From here on we lose existing map transitions, causing
|
| - // invalid back pointers. This will change once we can store multiple
|
| - // transitions with the same key.
|
| - 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.
|
| - Map* map;
|
| - 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->instance_descriptors() != old_descriptors) break;
|
| - map->SetEnumLength(Map::kInvalidEnumCache);
|
| - map->set_instance_descriptors(new_descriptors);
|
| - }
|
| - old_map->set_owns_descriptors(false);
|
| - }
|
| -
|
| - old_target->DeprecateTransitionTree();
|
| -
|
| - old_map->SetTransition(transition_index, new_map);
|
| - new_map->SetBackPointer(old_map);
|
| - return result;
|
| -}
|
| -
|
| -
|
| MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
|
| Object* new_value,
|
| PropertyAttributes attributes,
|
| @@ -2491,10 +2454,11 @@ MaybeObject* JSObject::MigrateToMap(Map* new_map) {
|
|
|
| MaybeObject* JSObject::GeneralizeFieldRepresentation(
|
| int modify_index,
|
| - Representation new_representation) {
|
| + Representation new_representation,
|
| + StoreMode store_mode) {
|
| Map* new_map;
|
| - MaybeObject* maybe_new_map =
|
| - map()->GeneralizeRepresentation(modify_index, new_representation);
|
| + MaybeObject* maybe_new_map = map()->GeneralizeRepresentation(
|
| + modify_index, new_representation, store_mode);
|
| if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| if (map() == new_map) return this;
|
|
|
| @@ -2512,16 +2476,39 @@ int Map::NumberOfFields() {
|
| }
|
|
|
|
|
| -MaybeObject* Map::CopyGeneralizeAllRepresentations() {
|
| +MaybeObject* Map::CopyGeneralizeAllRepresentations(
|
| + int modify_index,
|
| + StoreMode store_mode,
|
| + const char* reason) {
|
| Map* new_map;
|
| MaybeObject* maybe_map = this->Copy();
|
| if (!maybe_map->To(&new_map)) return maybe_map;
|
|
|
| - new_map->instance_descriptors()->InitializeRepresentations(
|
| - Representation::Tagged());
|
| + DescriptorArray* descriptors = new_map->instance_descriptors();
|
| + descriptors->InitializeRepresentations(Representation::Tagged());
|
| +
|
| + // 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() != FIELD) {
|
| + FieldDescriptor d(descriptors->GetKey(modify_index),
|
| + new_map->NumberOfFields(),
|
| + details.attributes(),
|
| + Representation::Tagged());
|
| + d.SetSortedKeyIndex(details.pointer());
|
| + descriptors->Set(modify_index, &d);
|
| + 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);
|
| + }
|
| +
|
| if (FLAG_trace_generalization) {
|
| - PrintF("failed generalization %p -> %p\n",
|
| - static_cast<void*>(this), static_cast<void*>(new_map));
|
| + PrintGeneralization(stdout, reason, modify_index,
|
| + new_map->NumberOfOwnDescriptors(),
|
| + new_map->NumberOfOwnDescriptors(),
|
| + details.type() == CONSTANT && store_mode == FORCE_FIELD,
|
| + Representation::Tagged(), Representation::Tagged());
|
| }
|
| return new_map;
|
| }
|
| @@ -2666,7 +2653,8 @@ Map* Map::FindLastMatchMap(int verbatim,
|
| // - Otherwise, invalidate the outdated transition target from |updated|, and
|
| // replace its transition tree with a new branch for the updated descriptors.
|
| MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
| - Representation new_representation) {
|
| + Representation new_representation,
|
| + StoreMode store_mode) {
|
| Map* old_map = this;
|
| DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
| Representation old_representation =
|
| @@ -2688,38 +2676,45 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
|
|
| // Check the state of the root map.
|
| if (!old_map->EquivalentToForTransition(root_map)) {
|
| - return CopyGeneralizeAllRepresentations();
|
| + return CopyGeneralizeAllRepresentations(
|
| + modify_index, store_mode, "not equivalent");
|
| }
|
|
|
| int verbatim = root_map->NumberOfOwnDescriptors();
|
|
|
| + if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) {
|
| + return CopyGeneralizeAllRepresentations(
|
| + modify_index, store_mode, "root modification");
|
| + }
|
| +
|
| Map* updated = root_map->FindUpdatedMap(
|
| verbatim, descriptors, old_descriptors);
|
| - if (updated == NULL) return CopyGeneralizeAllRepresentations();
|
| + if (updated == NULL) {
|
| + return CopyGeneralizeAllRepresentations(
|
| + modify_index, store_mode, "incompatible");
|
| + }
|
|
|
| DescriptorArray* updated_descriptors = updated->instance_descriptors();
|
|
|
| int valid = updated->NumberOfOwnDescriptors();
|
| +
|
| + // Directly change the map if the target map is more general. Ensure that the
|
| + // target type of the modify_index is a FIELD, unless we are migrating.
|
| if (updated_descriptors->IsMoreGeneralThan(
|
| - verbatim, valid, descriptors, old_descriptors)) {
|
| + verbatim, valid, descriptors, old_descriptors) &&
|
| + (store_mode == ALLOW_AS_CONSTANT ||
|
| + updated_descriptors->GetDetails(modify_index).type() == FIELD)) {
|
| Representation updated_representation =
|
| updated_descriptors->GetDetails(modify_index).representation();
|
| - if (new_representation.fits_into(updated_representation)) {
|
| - if (FLAG_trace_generalization &&
|
| - !(modify_index == 0 && new_representation.IsNone())) {
|
| - PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
|
| - PrintGeneralization(stdout, modify_index, descriptors, descriptors,
|
| - old_details.representation(),
|
| - updated_representation);
|
| - }
|
| - return updated;
|
| - }
|
| + if (new_representation.fits_into(updated_representation)) return updated;
|
| }
|
|
|
| DescriptorArray* new_descriptors;
|
| MaybeObject* maybe_descriptors = updated_descriptors->Merge(
|
| - verbatim, valid, descriptors, old_descriptors);
|
| + verbatim, valid, descriptors, modify_index, store_mode, old_descriptors);
|
| if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
| + ASSERT(store_mode == ALLOW_AS_CONSTANT ||
|
| + new_descriptors->GetDetails(modify_index).type() == FIELD);
|
|
|
| old_representation =
|
| new_descriptors->GetDetails(modify_index).representation();
|
| @@ -2741,10 +2736,11 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
| split_map->DeprecateTarget(
|
| old_descriptors->GetKey(descriptor), new_descriptors);
|
|
|
| - if (FLAG_trace_generalization &&
|
| - !(modify_index == 0 && new_representation.IsNone())) {
|
| - PrintGeneralization(stdout, modify_index, descriptor, descriptors,
|
| - old_representation, updated_representation);
|
| + if (FLAG_trace_generalization && store_mode != ALLOW_AS_CONSTANT) {
|
| + PrintGeneralization(
|
| + stdout, "", modify_index, descriptor, descriptors,
|
| + old_descriptors->GetDetails(modify_index).type() == CONSTANT,
|
| + old_representation, updated_representation);
|
| }
|
|
|
| Map* new_map = split_map;
|
| @@ -3782,14 +3778,92 @@ Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) {
|
|
|
| Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map,
|
| int modify_index,
|
| - Representation representation) {
|
| + Representation representation,
|
| + StoreMode store_mode) {
|
| CALL_HEAP_FUNCTION(
|
| map->GetIsolate(),
|
| - map->GeneralizeRepresentation(modify_index, representation),
|
| + map->GeneralizeRepresentation(modify_index, representation, store_mode),
|
| Map);
|
| }
|
|
|
|
|
| +static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + Map* transition_map = lookup->GetTransitionTarget();
|
| + int descriptor = transition_map->LastAdded();
|
| +
|
| + DescriptorArray* descriptors = transition_map->instance_descriptors();
|
| + PropertyDetails details = descriptors->GetDetails(descriptor);
|
| +
|
| + if (details.type() == CALLBACKS || attributes != details.attributes()) {
|
| + return lookup->holder()->ConvertDescriptorToField(
|
| + *name, *value, attributes);
|
| + }
|
| +
|
| + // Keep the target CONSTANT if the same value is stored.
|
| + // TODO(verwaest): Also support keeping the placeholder
|
| + // (value->IsUninitialized) as constant.
|
| + if (details.type() == CONSTANT &&
|
| + descriptors->GetValue(descriptor) == *value) {
|
| + lookup->holder()->set_map(transition_map);
|
| + return *value;
|
| + }
|
| +
|
| + Representation representation = details.representation();
|
| +
|
| + if (!value->FitsRepresentation(representation) ||
|
| + details.type() == CONSTANT) {
|
| + MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
|
| + descriptor, value->OptimalRepresentation(), FORCE_FIELD);
|
| + if (!maybe_map->To(&transition_map)) return maybe_map;
|
| + Object* back = transition_map->GetBackPointer();
|
| + if (back->IsMap()) {
|
| + MaybeObject* maybe_failure =
|
| + lookup->holder()->MigrateToMap(Map::cast(back));
|
| + if (maybe_failure->IsFailure()) return maybe_failure;
|
| + }
|
| + descriptors = transition_map->instance_descriptors();
|
| + representation = descriptors->GetDetails(descriptor).representation();
|
| + }
|
| +
|
| + int field_index = descriptors->GetFieldIndex(descriptor);
|
| + return lookup->holder()->AddFastPropertyUsingMap(
|
| + transition_map, *name, *value, field_index, representation);
|
| +}
|
| +
|
| +
|
| +static MaybeObject* SetPropertyToField(LookupResult* lookup,
|
| + Handle<Name> name,
|
| + Handle<Object> value) {
|
| + Representation representation = lookup->representation();
|
| + if (!value->FitsRepresentation(representation) ||
|
| + lookup->type() == CONSTANT) {
|
| + MaybeObject* maybe_failure =
|
| + lookup->holder()->GeneralizeFieldRepresentation(
|
| + lookup->GetDescriptorIndex(),
|
| + value->OptimalRepresentation(),
|
| + FORCE_FIELD);
|
| + if (maybe_failure->IsFailure()) return maybe_failure;
|
| + DescriptorArray* desc = lookup->holder()->map()->instance_descriptors();
|
| + int descriptor = lookup->GetDescriptorIndex();
|
| + representation = desc->GetDetails(descriptor).representation();
|
| + }
|
| +
|
| + if (FLAG_track_double_fields && representation.IsDouble()) {
|
| + HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt(
|
| + lookup->GetFieldIndex().field_index()));
|
| + storage->set_value(value->Number());
|
| + return *value;
|
| + }
|
| +
|
| + lookup->holder()->FastPropertyAtPut(
|
| + lookup->GetFieldIndex().field_index(), *value);
|
| + return *value;
|
| +}
|
| +
|
| +
|
| MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
|
| Name* name_raw,
|
| Object* value_raw,
|
| @@ -3878,37 +3952,13 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
|
| case NORMAL:
|
| result = lookup->holder()->SetNormalizedProperty(lookup, *value);
|
| break;
|
| - case FIELD: {
|
| - Representation representation = lookup->representation();
|
| - if (!value->FitsRepresentation(representation)) {
|
| - MaybeObject* maybe_failure =
|
| - lookup->holder()->GeneralizeFieldRepresentation(
|
| - lookup->GetDescriptorIndex(), value->OptimalRepresentation());
|
| - if (maybe_failure->IsFailure()) return maybe_failure;
|
| - DescriptorArray* desc = lookup->holder()->map()->instance_descriptors();
|
| - int descriptor = lookup->GetDescriptorIndex();
|
| - representation = desc->GetDetails(descriptor).representation();
|
| - }
|
| - if (FLAG_track_double_fields && representation.IsDouble()) {
|
| - HeapNumber* storage =
|
| - HeapNumber::cast(lookup->holder()->RawFastPropertyAt(
|
| - lookup->GetFieldIndex().field_index()));
|
| - storage->set_value(value->Number());
|
| - result = *value;
|
| - break;
|
| - }
|
| - lookup->holder()->FastPropertyAtPut(
|
| - lookup->GetFieldIndex().field_index(), *value);
|
| - result = *value;
|
| + case FIELD:
|
| + result = SetPropertyToField(lookup, name, value);
|
| break;
|
| - }
|
| case CONSTANT:
|
| // Only replace the constant if necessary.
|
| if (*value == lookup->GetConstant()) return *value;
|
| - // Preserve the attributes of this existing property.
|
| - attributes = lookup->GetAttributes();
|
| - result = lookup->holder()->ConvertDescriptorToField(
|
| - *name, *value, attributes);
|
| + result = SetPropertyToField(lookup, name, value);
|
| break;
|
| case CALLBACKS: {
|
| Object* callback_object = lookup->GetCallbackObject();
|
| @@ -3920,55 +3970,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
|
| *name, *value, attributes, strict_mode);
|
| break;
|
| case TRANSITION: {
|
| - Map* transition_map = lookup->GetTransitionTarget();
|
| - int descriptor = transition_map->LastAdded();
|
| -
|
| - DescriptorArray* descriptors = transition_map->instance_descriptors();
|
| - PropertyDetails details = descriptors->GetDetails(descriptor);
|
| -
|
| - if (details.type() == FIELD) {
|
| - if (attributes == details.attributes()) {
|
| - Representation representation = details.representation();
|
| - if (!value->FitsRepresentation(representation)) {
|
| - MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
|
| - descriptor, value->OptimalRepresentation());
|
| - if (!maybe_map->To(&transition_map)) return maybe_map;
|
| - Object* back = transition_map->GetBackPointer();
|
| - if (back->IsMap()) {
|
| - MaybeObject* maybe_failure =
|
| - lookup->holder()->MigrateToMap(Map::cast(back));
|
| - if (maybe_failure->IsFailure()) return maybe_failure;
|
| - }
|
| - DescriptorArray* desc = transition_map->instance_descriptors();
|
| - int descriptor = transition_map->LastAdded();
|
| - representation = desc->GetDetails(descriptor).representation();
|
| - }
|
| - int field_index = descriptors->GetFieldIndex(descriptor);
|
| - result = lookup->holder()->AddFastPropertyUsingMap(
|
| - transition_map, *name, *value, field_index, representation);
|
| - } else {
|
| - result = lookup->holder()->ConvertDescriptorToField(
|
| - *name, *value, attributes);
|
| - }
|
| - } else if (details.type() == CALLBACKS) {
|
| - result = lookup->holder()->ConvertDescriptorToField(
|
| - *name, *value, attributes);
|
| - } else {
|
| - ASSERT(details.type() == CONSTANT);
|
| -
|
| - Object* constant = descriptors->GetValue(descriptor);
|
| - if (constant == *value) {
|
| - // If the same constant function is being added we can simply
|
| - // transition to the target map.
|
| - lookup->holder()->set_map(transition_map);
|
| - result = constant;
|
| - } else {
|
| - // Otherwise, replace with a map transition to a new map with a FIELD,
|
| - // even if the value is a constant function.
|
| - result = lookup->holder()->ConvertTransitionToMapTransition(
|
| - lookup->GetTransitionIndex(), *name, *value, attributes);
|
| - }
|
| - }
|
| + result = SetPropertyUsingTransition(lookup, name, value, attributes);
|
| break;
|
| }
|
| case HANDLER:
|
| @@ -4088,87 +4090,24 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
|
| result = self->SetNormalizedProperty(*name, *value, details);
|
| break;
|
| }
|
| - case FIELD: {
|
| - Representation representation = lookup.representation();
|
| - Representation value_representation =
|
| - value->OptimalRepresentation(value_type);
|
| - if (value_representation.IsNone()) break;
|
| - if (!value_representation.fits_into(representation)) {
|
| - MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation(
|
| - lookup.GetDescriptorIndex(), value_representation);
|
| - if (maybe_failure->IsFailure()) return maybe_failure;
|
| - DescriptorArray* desc = self->map()->instance_descriptors();
|
| - int descriptor = lookup.GetDescriptorIndex();
|
| - representation = desc->GetDetails(descriptor).representation();
|
| - }
|
| - if (FLAG_track_double_fields && representation.IsDouble()) {
|
| - HeapNumber* storage =
|
| - HeapNumber::cast(self->RawFastPropertyAt(
|
| - lookup.GetFieldIndex().field_index()));
|
| - storage->set_value(value->Number());
|
| - result = *value;
|
| - break;
|
| - }
|
| - self->FastPropertyAtPut(lookup.GetFieldIndex().field_index(), *value);
|
| - result = *value;
|
| + case FIELD:
|
| + if (value->IsUninitialized()) break;
|
| + result = SetPropertyToField(&lookup, name, value);
|
| break;
|
| - }
|
| case CONSTANT:
|
| - // Only replace the function if necessary.
|
| - if (*value != lookup.GetConstant()) {
|
| - // Preserve the attributes of this existing property.
|
| - attributes = lookup.GetAttributes();
|
| - result = self->ConvertDescriptorToField(*name, *value, attributes);
|
| - }
|
| + // Only replace the constant if necessary.
|
| + if (*value == lookup.GetConstant()) return *value;
|
| + if (value->IsUninitialized()) break;
|
| + result = SetPropertyToField(&lookup, name, value);
|
| break;
|
| case CALLBACKS:
|
| case INTERCEPTOR:
|
| // Override callback in clone
|
| result = self->ConvertDescriptorToField(*name, *value, attributes);
|
| break;
|
| - case TRANSITION: {
|
| - Map* transition_map = lookup.GetTransitionTarget();
|
| - int descriptor = transition_map->LastAdded();
|
| -
|
| - DescriptorArray* descriptors = transition_map->instance_descriptors();
|
| - PropertyDetails details = descriptors->GetDetails(descriptor);
|
| -
|
| - if (details.type() == FIELD) {
|
| - if (attributes == details.attributes()) {
|
| - Representation representation = details.representation();
|
| - Representation value_representation =
|
| - value->OptimalRepresentation(value_type);
|
| - if (!value_representation.fits_into(representation)) {
|
| - MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
|
| - descriptor, value_representation);
|
| - if (!maybe_map->To(&transition_map)) return maybe_map;
|
| - Object* back = transition_map->GetBackPointer();
|
| - if (back->IsMap()) {
|
| - MaybeObject* maybe_failure = self->MigrateToMap(Map::cast(back));
|
| - if (maybe_failure->IsFailure()) return maybe_failure;
|
| - }
|
| - DescriptorArray* desc = transition_map->instance_descriptors();
|
| - int descriptor = transition_map->LastAdded();
|
| - representation = desc->GetDetails(descriptor).representation();
|
| - }
|
| - int field_index = descriptors->GetFieldIndex(descriptor);
|
| - result = self->AddFastPropertyUsingMap(
|
| - transition_map, *name, *value, field_index, representation);
|
| - } else {
|
| - result = self->ConvertDescriptorToField(*name, *value, attributes);
|
| - }
|
| - } else if (details.type() == CALLBACKS) {
|
| - result = self->ConvertDescriptorToField(*name, *value, attributes);
|
| - } else {
|
| - ASSERT(details.type() == CONSTANT);
|
| -
|
| - // Replace transition to CONSTANT FUNCTION with a map transition to a
|
| - // new map with a FIELD, even if the value is a function.
|
| - result = self->ConvertTransitionToMapTransition(
|
| - lookup.GetTransitionIndex(), *name, *value, attributes);
|
| - }
|
| + case TRANSITION:
|
| + result = SetPropertyUsingTransition(&lookup, name, value, attributes);
|
| break;
|
| - }
|
| case HANDLER:
|
| case NONEXISTENT:
|
| UNREACHABLE();
|
| @@ -6675,7 +6614,7 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
| if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
| set_transitions(transitions);
|
| result->SetBackPointer(this);
|
| - } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) {
|
| + } else {
|
| descriptors->InitializeRepresentations(Representation::Tagged());
|
| }
|
|
|
| @@ -7803,6 +7742,8 @@ void DescriptorArray::CopyFrom(int dst_index,
|
| MaybeObject* DescriptorArray::Merge(int verbatim,
|
| int valid,
|
| int new_size,
|
| + int modify_index,
|
| + StoreMode store_mode,
|
| DescriptorArray* other) {
|
| ASSERT(verbatim <= valid);
|
| ASSERT(valid <= new_size);
|
| @@ -7836,6 +7777,7 @@ MaybeObject* DescriptorArray::Merge(int verbatim,
|
| PropertyDetails other_details = other->GetDetails(descriptor);
|
|
|
| if (details.type() == FIELD || other_details.type() == FIELD ||
|
| + (store_mode == FORCE_FIELD && descriptor == modify_index) ||
|
| (details.type() == CONSTANT &&
|
| other_details.type() == CONSTANT &&
|
| GetValue(descriptor) != other->GetValue(descriptor))) {
|
| @@ -7854,7 +7796,8 @@ MaybeObject* DescriptorArray::Merge(int verbatim,
|
| // |valid| -> |new_size|
|
| for (; descriptor < new_size; descriptor++) {
|
| PropertyDetails details = other->GetDetails(descriptor);
|
| - if (details.type() == FIELD) {
|
| + if (details.type() == FIELD ||
|
| + (store_mode == FORCE_FIELD && descriptor == modify_index)) {
|
| Name* key = other->GetKey(descriptor);
|
| FieldDescriptor d(key,
|
| current_offset++,
|
|
|