OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 Factory* factory = isolate->factory(); | 119 Factory* factory = isolate->factory(); |
120 return factory->LookupSingleCharacterStringFromCode( | 120 return factory->LookupSingleCharacterStringFromCode( |
121 String::Flatten(str)->Get(index)); | 121 String::Flatten(str)->Get(index)); |
122 } | 122 } |
123 } | 123 } |
124 | 124 |
125 // Fall back to GetObjectProperty. | 125 // Fall back to GetObjectProperty. |
126 return Runtime::GetObjectProperty(isolate, receiver_obj, key_obj); | 126 return Runtime::GetObjectProperty(isolate, receiver_obj, key_obj); |
127 } | 127 } |
128 | 128 |
| 129 namespace { |
| 130 |
| 131 bool DeleteObjectPropertyFast(Isolate* isolate, Handle<JSReceiver> receiver, |
| 132 Handle<Object> raw_key) { |
| 133 // This implements a special case for fast property deletion: when the |
| 134 // last property in an object is deleted, then instead of normalizing |
| 135 // the properties, we can undo the last map transition, with a few |
| 136 // prerequisites: |
| 137 // (1) The receiver must be a regular object and the key a unique name. |
| 138 Map* map = receiver->map(); |
| 139 if (map->IsSpecialReceiverMap()) return false; |
| 140 if (!raw_key->IsUniqueName()) return false; |
| 141 Handle<Name> key = Handle<Name>::cast(raw_key); |
| 142 // (2) The property to be deleted must be the last property. |
| 143 int nof = map->NumberOfOwnDescriptors(); |
| 144 if (nof == 0) return false; |
| 145 int descriptor = nof - 1; |
| 146 DescriptorArray* descriptors = map->instance_descriptors(); |
| 147 if (descriptors->GetKey(descriptor) != *key) return false; |
| 148 // (3) The property to be deleted must be deletable. |
| 149 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 150 if (!details.IsConfigurable()) return false; |
| 151 // (4) The map must have a back pointer. |
| 152 Object* backpointer = map->GetBackPointer(); |
| 153 if (!backpointer->IsMap()) return false; |
| 154 // (5) The last transition must have been caused by adding a property |
| 155 // (and not any kind of special transition). |
| 156 if (Map::cast(backpointer)->NumberOfOwnDescriptors() != nof - 1) return false; |
| 157 |
| 158 // Preconditions successful. No more bailouts after this point. |
| 159 |
| 160 // Zap the property to avoid keeping objects alive. Zapping is not necessary |
| 161 // for properties stored in the descriptor array. |
| 162 if (details.location() == kField) { |
| 163 Object* filler = isolate->heap()->one_pointer_filler_map(); |
| 164 FieldIndex index = FieldIndex::ForPropertyIndex(map, details.field_index()); |
| 165 JSObject::cast(*receiver)->RawFastPropertyAtPut(index, filler); |
| 166 // We must clear any recorded slot for the deleted property, because |
| 167 // subsequent object modifications might put a raw double there. |
| 168 // Slot clearing is the reason why this entire function cannot currently |
| 169 // be implemented in the DeleteProperty stub. |
| 170 if (index.is_inobject() && !map->IsUnboxedDoubleField(index)) { |
| 171 isolate->heap()->ClearRecordedSlot( |
| 172 *receiver, HeapObject::RawField(*receiver, index.offset())); |
| 173 } |
| 174 } |
| 175 // If the map was marked stable before, then there could be optimized code |
| 176 // that depends on the assumption that no object that reached this map |
| 177 // transitions away from it without triggering the "deoptimize dependent |
| 178 // code" mechanism. |
| 179 map->NotifyLeafMapLayoutChange(); |
| 180 // Finally, perform the map rollback. |
| 181 receiver->synchronized_set_map(Map::cast(backpointer)); |
| 182 return true; |
| 183 } |
| 184 |
| 185 } // namespace |
129 | 186 |
130 Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate, | 187 Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate, |
131 Handle<JSReceiver> receiver, | 188 Handle<JSReceiver> receiver, |
132 Handle<Object> key, | 189 Handle<Object> key, |
133 LanguageMode language_mode) { | 190 LanguageMode language_mode) { |
| 191 if (DeleteObjectPropertyFast(isolate, receiver, key)) return Just(true); |
| 192 |
134 bool success = false; | 193 bool success = false; |
135 LookupIterator it = LookupIterator::PropertyOrElement( | 194 LookupIterator it = LookupIterator::PropertyOrElement( |
136 isolate, receiver, key, &success, LookupIterator::OWN); | 195 isolate, receiver, key, &success, LookupIterator::OWN); |
137 if (!success) return Nothing<bool>(); | 196 if (!success) return Nothing<bool>(); |
138 | 197 |
139 return JSReceiver::DeleteProperty(&it, language_mode); | 198 return JSReceiver::DeleteProperty(&it, language_mode); |
140 } | 199 } |
141 | 200 |
142 // ES6 19.1.3.2 | 201 // ES6 19.1.3.2 |
143 RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) { | 202 RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) { |
(...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1037 // While iteration alone may not have observable side-effects, calling | 1096 // While iteration alone may not have observable side-effects, calling |
1038 // toNumber on an object will. Make sure the arg is not an array of objects. | 1097 // toNumber on an object will. Make sure the arg is not an array of objects. |
1039 ElementsKind kind = JSObject::cast(*obj)->GetElementsKind(); | 1098 ElementsKind kind = JSObject::cast(*obj)->GetElementsKind(); |
1040 if (!IsFastNumberElementsKind(kind)) return isolate->heap()->ToBoolean(false); | 1099 if (!IsFastNumberElementsKind(kind)) return isolate->heap()->ToBoolean(false); |
1041 | 1100 |
1042 return isolate->heap()->ToBoolean(!obj->IterationHasObservableEffects()); | 1101 return isolate->heap()->ToBoolean(!obj->IterationHasObservableEffects()); |
1043 } | 1102 } |
1044 | 1103 |
1045 } // namespace internal | 1104 } // namespace internal |
1046 } // namespace v8 | 1105 } // namespace v8 |
OLD | NEW |