@@ -99,6 +99,41 @@ Handle<Map> MapUpdater::ReconfigureToDataField(int descriptor,
99
99
PropertyDetails old_details =
100
100
old_descriptors_->GetDetails (modified_descriptor_);
101
101
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
+
102
137
// If property kind is not reconfigured merge the result with
103
138
// representation/field type from the old descriptor.
104
139
if (old_details.kind () == new_kind_) {
0 commit comments