Chromium Code Reviews| Index: src/runtime/runtime-object.cc |
| diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc |
| index 55154fa504b1c13b5e3c89fad52f140644e89837..fafcd63fd9243713a47acb22c81f8588daa8e122 100644 |
| --- a/src/runtime/runtime-object.cc |
| +++ b/src/runtime/runtime-object.cc |
| @@ -126,11 +126,67 @@ static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate, |
| return Runtime::GetObjectProperty(isolate, receiver_obj, key_obj); |
| } |
| +namespace { |
| + |
| +bool DeleteObjectPropertyFast(Isolate* isolate, Handle<JSReceiver> receiver, |
| + Handle<Object> raw_key) { |
| + Map* map = receiver->map(); |
| + if (map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) return false; |
|
Igor Sheludko
2017/05/03 14:39:25
map->IsSpecialReceiverMap()
Jakob Kummerow
2017/05/03 14:49:27
Done.
|
| + if (!raw_key->IsUniqueName()) return false; |
| + Handle<Name> key = Handle<Name>::cast(raw_key); |
| + // This implements a special case for fast property deletion: when the |
| + // last property in an object is deleted, then instead of normalizing |
| + // the properties, we can undo the last map transition, with a few |
| + // prerequisites: |
| + // (1) The current map must not be marked stable. Otherwise there could be |
| + // optimized code that depends on the assumption that no object that reached |
| + // this map transitions away from it (without triggering the "deoptimize |
| + // dependent code" mechanism). |
| + if (map->is_stable()) return false; |
| + // (2) The property to be deleted must be the last property. |
| + int nof = map->NumberOfOwnDescriptors(); |
| + if (nof == 0) return false; |
| + int descriptor = nof - 1; |
| + DescriptorArray* descriptors = map->instance_descriptors(); |
| + if (descriptors->GetKey(descriptor) != *key) return false; |
| + // (3) The property to be deleted must be deletable. |
| + PropertyDetails details = descriptors->GetDetails(descriptor); |
| + if (!details.IsConfigurable()) return false; |
| + // (4) The map must have a back pointer. |
| + Object* backpointer = map->GetBackPointer(); |
| + if (!backpointer->IsMap()) return false; |
| + // (5) The last transition must hvae been caused by adding a property |
|
Igor Sheludko
2017/05/03 14:39:25
s/hvae/have/
Jakob Kummerow
2017/05/03 14:49:27
Done.
|
| + // (and not any kind of special transition). |
| + if (Map::cast(backpointer)->NumberOfOwnDescriptors() != nof - 1) return false; |
| + |
| + // Preconditions successful, perform the map rollback! |
| + // Zap the property to avoid keeping objects alive. Zapping is not necessary |
| + // for properties stored in the descriptor array. |
| + if (details.location() == kField) { |
| + Object* filler = isolate->heap()->one_pointer_filler_map(); |
| + FieldIndex index = FieldIndex::ForPropertyIndex(map, details.field_index()); |
| + JSObject::cast(*receiver)->RawFastPropertyAtPut(index, filler); |
| + // We must clear any recorded slot for the deleted property, because |
| + // subsequent object modifications might put a raw double there. |
| + // Slot clearing is the reason why this entire function cannot currently |
| + // be implemented in the DeleteProperty stub. |
| + if (index.is_inobject() && !map->IsUnboxedDoubleField(index)) { |
|
Igor Sheludko
2017/05/03 14:39:25
"index.is_inobject() &&" is not necessary because
Jakob Kummerow
2017/05/03 14:49:27
Nope, it's necessary. For out-of-object fields, "I
Igor Sheludko
2017/05/03 14:53:26
Acknowledged.
|
| + isolate->heap()->ClearRecordedSlot( |
| + *receiver, HeapObject::RawField(*receiver, index.offset())); |
| + } |
| + } |
| + receiver->synchronized_set_map(Map::cast(backpointer)); |
| + return true; |
| +} |
| + |
| +} // namespace |
| Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate, |
| Handle<JSReceiver> receiver, |
| Handle<Object> key, |
| LanguageMode language_mode) { |
| + if (DeleteObjectPropertyFast(isolate, receiver, key)) return Just(true); |
| + |
| bool success = false; |
| LookupIterator it = LookupIterator::PropertyOrElement( |
| isolate, receiver, key, &success, LookupIterator::OWN); |