@@ -71,184 +71,10 @@ MaybeHandle<Object> Runtime::HasProperty(Isolate* isolate,
71
71
return ReadOnlyRoots (isolate).boolean_value_handle (maybe.FromJust ());
72
72
}
73
73
74
- namespace {
75
-
76
- // This function sets the sentinel value in a deleted field. Thes sentinel has
77
- // to look like a proper standalone object because the slack tracking may
78
- // complete at any time. For this reason we use the filler map word.
79
- // If V8_MAP_PACKING is enabled, then the filler map word is a packed filler
80
- // map. Otherwise, the filler map word is the same as the filler map.
81
- inline void ClearField (Isolate* isolate, JSObject object, FieldIndex index) {
82
- if (index.is_inobject ()) {
83
- MapWord filler_map_word =
84
- ReadOnlyRoots (isolate).one_pointer_filler_map_word ();
85
- #ifndef V8_MAP_PACKING
86
- DCHECK_EQ (filler_map_word.ToMap (),
87
- ReadOnlyRoots (isolate).one_pointer_filler_map ());
88
- #endif
89
- int offset = index.offset ();
90
- TaggedField<MapWord>::Release_Store (object, offset, filler_map_word);
91
- } else {
92
- object->property_array ()->set (
93
- index.outobject_array_index (),
94
- ReadOnlyRoots (isolate).one_pointer_filler_map ());
95
- }
96
- }
97
-
98
- void GeneralizeAllTransitionsToFieldAsMutable (Isolate* isolate, Handle<Map> map,
99
- Handle<Name> name) {
100
- InternalIndex descriptor (map->NumberOfOwnDescriptors ());
101
-
102
- Handle<Map> target_maps[kPropertyAttributesCombinationsCount ];
103
- int target_maps_count = 0 ;
104
-
105
- // Collect all outgoing field transitions.
106
- {
107
- DisallowGarbageCollection no_gc;
108
- TransitionsAccessor transitions (isolate, *map);
109
- transitions.ForEachTransitionTo (
110
- *name,
111
- [&](Map target) {
112
- DCHECK_EQ (descriptor, target->LastAdded ());
113
- DCHECK_EQ (*name, target->GetLastDescriptorName (isolate));
114
- PropertyDetails details = target->GetLastDescriptorDetails (isolate);
115
- // Currently, we track constness only for fields.
116
- if (details.kind () == PropertyKind::kData &&
117
- details.constness () == PropertyConstness::kConst ) {
118
- target_maps[target_maps_count++] = handle (target, isolate);
119
- }
120
- DCHECK_IMPLIES (details.kind () == PropertyKind::kAccessor ,
121
- details.constness () == PropertyConstness::kConst );
122
- },
123
- &no_gc);
124
- CHECK_LE (target_maps_count, kPropertyAttributesCombinationsCount );
125
- }
126
-
127
- for (int i = 0 ; i < target_maps_count; i++) {
128
- Handle<Map> target = target_maps[i];
129
- PropertyDetails details =
130
- target->instance_descriptors (isolate)->GetDetails (descriptor);
131
- Handle<FieldType> field_type (
132
- target->instance_descriptors (isolate)->GetFieldType (descriptor),
133
- isolate);
134
- MapUpdater::GeneralizeField (isolate, target, descriptor,
135
- PropertyConstness::kMutable ,
136
- details.representation (), field_type);
137
- DCHECK_EQ (PropertyConstness::kMutable , target->instance_descriptors (isolate)
138
- ->GetDetails (descriptor)
139
- .constness ());
140
- }
141
- }
142
-
143
- bool DeleteObjectPropertyFast (Isolate* isolate, Handle<JSReceiver> receiver,
144
- Handle<Object> raw_key) {
145
- // This implements a special case for fast property deletion: when the
146
- // last property in an object is deleted, then instead of normalizing
147
- // the properties, we can undo the last map transition, with a few
148
- // prerequisites:
149
- // (1) The receiver must be a regular object and the key a unique name.
150
- Handle<Map> receiver_map (receiver->map (), isolate);
151
- if (IsSpecialReceiverMap (*receiver_map)) return false ;
152
- DCHECK (IsJSObjectMap (*receiver_map));
153
-
154
- if (!IsUniqueName (*raw_key)) return false ;
155
- Handle<Name> key = Handle<Name>::cast (raw_key);
156
- // (2) The property to be deleted must be the last property.
157
- int nof = receiver_map->NumberOfOwnDescriptors ();
158
- if (nof == 0 ) return false ;
159
- InternalIndex descriptor (nof - 1 );
160
- Handle<DescriptorArray> descriptors (
161
- receiver_map->instance_descriptors (isolate), isolate);
162
- if (descriptors->GetKey (descriptor) != *key) return false ;
163
- // (3) The property to be deleted must be deletable.
164
- PropertyDetails details = descriptors->GetDetails (descriptor);
165
- if (!details.IsConfigurable ()) return false ;
166
- // (4) The map must have a back pointer.
167
- Handle<Object> backpointer (receiver_map->GetBackPointer (), isolate);
168
- if (!IsMap (*backpointer)) return false ;
169
- Handle<Map> parent_map = Handle<Map>::cast (backpointer);
170
- // (5) The last transition must have been caused by adding a property
171
- // (and not any kind of special transition).
172
- if (parent_map->NumberOfOwnDescriptors () != nof - 1 ) return false ;
173
-
174
- // Preconditions successful. No more bailouts after this point.
175
-
176
- // Zap the property to avoid keeping objects alive. Zapping is not necessary
177
- // for properties stored in the descriptor array.
178
- if (details.location () == PropertyLocation::kField ) {
179
- DisallowGarbageCollection no_gc;
180
-
181
- // Invalidate slots manually later in case we delete an in-object tagged
182
- // property. In this case we might later store an untagged value in the
183
- // recorded slot.
184
- isolate->heap ()->NotifyObjectLayoutChange (*receiver, no_gc,
185
- InvalidateRecordedSlots::kNo );
186
- FieldIndex index =
187
- FieldIndex::ForPropertyIndex (*receiver_map, details.field_index ());
188
- // Special case deleting the last out-of object property.
189
- if (!index.is_inobject () && index.outobject_array_index () == 0 ) {
190
- DCHECK (!parent_map->HasOutOfObjectProperties ());
191
- // Clear out the properties backing store.
192
- receiver->SetProperties (ReadOnlyRoots (isolate).empty_fixed_array ());
193
- } else {
194
- ClearField (isolate, JSObject::cast (*receiver), index);
195
- if (index.is_inobject ()) {
196
- // We need to clear the recorded slot in this case because in-object
197
- // slack tracking might not be finished. This ensures that we don't
198
- // have recorded slots in free space.
199
- isolate->heap ()->ClearRecordedSlot (*receiver,
200
- receiver->RawField (index.offset ()));
201
- }
202
- }
203
- }
204
- // If the {receiver_map} was marked stable before, then there could be
205
- // optimized code that depends on the assumption that no object that
206
- // reached this {receiver_map} transitions away from it without triggering
207
- // the "deoptimize dependent code" mechanism.
208
- receiver_map->NotifyLeafMapLayoutChange (isolate);
209
- // Finally, perform the map rollback.
210
- receiver->set_map (*parent_map, kReleaseStore );
211
- #if VERIFY_HEAP
212
- if (v8_flags.verify_heap ) {
213
- receiver->HeapObjectVerify (isolate);
214
- receiver->property_array ()->PropertyArrayVerify (isolate);
215
- }
216
- #endif
217
-
218
- // If the {descriptor} was "const" so far, we need to update the
219
- // {receiver_map} here, otherwise we could get the constants wrong, i.e.
220
- //
221
- // o.x = 1;
222
- // [change o.x's attributes or reconfigure property kind]
223
- // delete o.x;
224
- // o.x = 2;
225
- //
226
- // could trick V8 into thinking that `o.x` is still 1 even after the second
227
- // assignment.
228
-
229
- // Step 1: Migrate object to an up-to-date shape.
230
- if (parent_map->is_deprecated ()) {
231
- JSObject::MigrateInstance (isolate, Handle<JSObject>::cast (receiver));
232
- parent_map = handle (receiver->map (), isolate);
233
- }
234
-
235
- // Step 2: Mark outgoing transitions from the up-to-date version of the
236
- // parent_map to same property name of any kind or attributes as mutable.
237
- // Also migrate object to the up-to-date map to make the object shapes
238
- // converge sooner.
239
- GeneralizeAllTransitionsToFieldAsMutable (isolate, parent_map, key);
240
-
241
- return true ;
242
- }
243
-
244
- } // namespace
245
-
246
74
Maybe<bool > Runtime::DeleteObjectProperty (Isolate* isolate,
247
75
Handle<JSReceiver> receiver,
248
76
Handle<Object> key,
249
77
LanguageMode language_mode) {
250
- if (DeleteObjectPropertyFast (isolate, receiver, key)) return Just (true );
251
-
252
78
bool success = false ;
253
79
PropertyKey lookup_key (isolate, key, &success);
254
80
if (!success) return Nothing<bool >();
0 commit comments