| Index: src/compiler/js-native-context-specialization.cc
|
| diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
|
| index 602446f651622fc4aa7d071d7feea2b7f51740d9..842b002da7d68dca87c3df8f8f762ec214c5cc09 100644
|
| --- a/src/compiler/js-native-context-specialization.cc
|
| +++ b/src/compiler/js-native-context-specialization.cc
|
| @@ -1623,19 +1623,42 @@ JSNativeContextSpecialization::BuildPropertyAccess(
|
| UNREACHABLE();
|
| break;
|
| }
|
| + // Check if we need to perform a transitioning store.
|
| Handle<Map> transition_map;
|
| if (access_info.transition_map().ToHandle(&transition_map)) {
|
| + // Check if we need to grow the properties backing store
|
| + // with this transitioning store.
|
| + Handle<Map> original_map(Map::cast(transition_map->GetBackPointer()),
|
| + isolate());
|
| + if (original_map->unused_property_fields() == 0) {
|
| + DCHECK(!field_index.is_inobject());
|
| +
|
| + // Reallocate the properties {storage}.
|
| + storage = effect = BuildExtendPropertiesBackingStore(
|
| + original_map, storage, effect, control);
|
| +
|
| + // Perform the actual store.
|
| + effect = graph()->NewNode(simplified()->StoreField(field_access),
|
| + storage, value, effect, control);
|
| +
|
| + // Atomically switch to the new properties below.
|
| + field_access = AccessBuilder::ForJSObjectProperties();
|
| + value = storage;
|
| + storage = receiver;
|
| + }
|
| effect = graph()->NewNode(
|
| common()->BeginRegion(RegionObservability::kObservable), effect);
|
| effect = graph()->NewNode(
|
| simplified()->StoreField(AccessBuilder::ForMap()), receiver,
|
| jsgraph()->Constant(transition_map), effect, control);
|
| - }
|
| - effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
|
| - value, effect, control);
|
| - if (access_info.HasTransitionMap()) {
|
| + effect = graph()->NewNode(simplified()->StoreField(field_access),
|
| + storage, value, effect, control);
|
| effect = graph()->NewNode(common()->FinishRegion(),
|
| jsgraph()->UndefinedConstant(), effect);
|
| + } else {
|
| + // Regular non-transitioning field store.
|
| + effect = graph()->NewNode(simplified()->StoreField(field_access),
|
| + storage, value, effect, control);
|
| }
|
| }
|
| } else {
|
| @@ -2163,6 +2186,45 @@ Node* JSNativeContextSpecialization::BuildCheckMaps(
|
| effect, control);
|
| }
|
|
|
| +Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore(
|
| + Handle<Map> map, Node* properties, Node* effect, Node* control) {
|
| + DCHECK_EQ(0, map->unused_property_fields());
|
| + // Compute the length of the old {properties} and the new properties.
|
| + int length = map->NextFreePropertyIndex() - map->GetInObjectProperties();
|
| + int new_length = length + JSObject::kFieldsAdded;
|
| + // Collect the field values from the {properties}.
|
| + ZoneVector<Node*> values(zone());
|
| + values.reserve(new_length);
|
| + for (int i = 0; i < length; ++i) {
|
| + Node* value = effect = graph()->NewNode(
|
| + simplified()->LoadField(AccessBuilder::ForFixedArraySlot(i)),
|
| + properties, effect, control);
|
| + values.push_back(value);
|
| + }
|
| + // Initialize the new fields to undefined.
|
| + for (int i = 0; i < JSObject::kFieldsAdded; ++i) {
|
| + values.push_back(jsgraph()->UndefinedConstant());
|
| + }
|
| + // Allocate and initialize the new properties.
|
| + effect = graph()->NewNode(
|
| + common()->BeginRegion(RegionObservability::kNotObservable), effect);
|
| + Node* new_properties = effect = graph()->NewNode(
|
| + simplified()->Allocate(Type::OtherInternal(), NOT_TENURED),
|
| + jsgraph()->Constant(FixedArray::SizeFor(new_length)), effect, control);
|
| + effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
|
| + new_properties, jsgraph()->FixedArrayMapConstant(),
|
| + effect, control);
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(AccessBuilder::ForFixedArrayLength()),
|
| + new_properties, jsgraph()->Constant(new_length), effect, control);
|
| + for (int i = 0; i < new_length; ++i) {
|
| + effect = graph()->NewNode(
|
| + simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)),
|
| + new_properties, values[i], effect, control);
|
| + }
|
| + return graph()->NewNode(common()->FinishRegion(), new_properties, effect);
|
| +}
|
| +
|
| void JSNativeContextSpecialization::AssumePrototypesStable(
|
| std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) {
|
| // Determine actual holder and perform prototype chain checks.
|
|
|