@@ -99,6 +99,41 @@ Handle<Map> MapUpdater::ReconfigureToDataField(int descriptor,
9999 PropertyDetails old_details =
100100 old_descriptors_->GetDetails (modified_descriptor_);
101101
102+ // If the {descriptor} was "const" data field so far, we need to update the
103+ // {old_map_} here, otherwise we could get the constants wrong, i.e.
104+ //
105+ // o.x = 1;
106+ // change o.x's attributes to something else
107+ // delete o.x;
108+ // o.x = 2;
109+ //
110+ // could trick V8 into thinking that `o.x` is still 1 even after the second
111+ // assignment.
112+ // This situation is similar to what might happen with property deletion.
113+ if (old_details.constness () == PropertyConstness::kConst &&
114+ old_details.location () == kField &&
115+ old_details.attributes () != new_attributes_) {
116+ Handle<FieldType> field_type (
117+ old_descriptors_->GetFieldType (modified_descriptor_), isolate_);
118+ Map::GeneralizeField (isolate_, old_map_, descriptor,
119+ PropertyConstness::kMutable ,
120+ old_details.representation (), field_type);
121+ // The old_map_'s property must become mutable.
122+ // Note, that the {old_map_} and {old_descriptors_} are not expected to be
123+ // updated by the generalization if the map is already deprecated.
124+ DCHECK_IMPLIES (
125+ !old_map_->is_deprecated (),
126+ PropertyConstness::kMutable ==
127+ old_descriptors_->GetDetails (modified_descriptor_).constness ());
128+ // Although the property in the old map is marked as mutable we still
129+ // treat it as constant when merging with the new path in transition tree.
130+ // This is fine because up until this reconfiguration the field was
131+ // known to be constant, so it's fair to proceed treating it as such
132+ // during this reconfiguration session. The issue is that after the
133+ // reconfiguration the original field might become mutable (see the delete
134+ // example above).
135+ }
136+
102137 // If property kind is not reconfigured merge the result with
103138 // representation/field type from the old descriptor.
104139 if (old_details.kind () == new_kind_) {
0 commit comments