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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
9 #include "src/lookup.h" | 9 #include "src/lookup.h" |
10 #include "src/lookup-inl.h" | 10 #include "src/lookup-inl.h" |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 | 270 |
271 | 271 |
272 void LookupIterator::TransitionToAccessorProperty( | 272 void LookupIterator::TransitionToAccessorProperty( |
273 AccessorComponent component, Handle<Object> accessor, | 273 AccessorComponent component, Handle<Object> accessor, |
274 PropertyAttributes attributes) { | 274 PropertyAttributes attributes) { |
275 DCHECK(!accessor->IsNull()); | 275 DCHECK(!accessor->IsNull()); |
276 // Can only be called when the receiver is a JSObject. JSProxy has to be | 276 // Can only be called when the receiver is a JSObject. JSProxy has to be |
277 // handled via a trap. Adding properties to primitive values is not | 277 // handled via a trap. Adding properties to primitive values is not |
278 // observable. | 278 // observable. |
279 Handle<JSObject> receiver = GetStoreTarget(); | 279 Handle<JSObject> receiver = GetStoreTarget(); |
280 holder_ = receiver; | |
281 | 280 |
282 if (!IsElement() && !receiver->map()->is_dictionary_map()) { | 281 if (!IsElement() && !receiver->map()->is_dictionary_map()) { |
| 282 holder_ = receiver; |
283 holder_map_ = Map::TransitionToAccessorProperty( | 283 holder_map_ = Map::TransitionToAccessorProperty( |
284 handle(receiver->map(), isolate_), name_, component, accessor, | 284 handle(receiver->map(), isolate_), name_, component, accessor, |
285 attributes); | 285 attributes); |
286 JSObject::MigrateToMap(receiver, holder_map_); | 286 JSObject::MigrateToMap(receiver, holder_map_); |
287 | 287 |
288 ReloadPropertyInformation(); | 288 ReloadPropertyInformation(); |
289 | 289 |
290 if (!holder_map_->is_dictionary_map()) return; | 290 if (!holder_map_->is_dictionary_map()) return; |
291 } | 291 } |
292 | 292 |
293 PropertyDetails details(attributes, ACCESSOR_CONSTANT, 0, | |
294 PropertyCellType::kMutable); | |
295 Handle<AccessorPair> pair; | 293 Handle<AccessorPair> pair; |
296 if (state() == ACCESSOR && GetAccessors()->IsAccessorPair()) { | 294 if (state() == ACCESSOR && GetAccessors()->IsAccessorPair()) { |
297 pair = Handle<AccessorPair>::cast(GetAccessors()); | 295 pair = Handle<AccessorPair>::cast(GetAccessors()); |
298 // If the component and attributes are identical, nothing has to be done. | 296 // If the component and attributes are identical, nothing has to be done. |
299 if (pair->get(component) == *accessor) { | 297 if (pair->get(component) == *accessor) { |
300 if (property_details().attributes() == attributes) return; | 298 if (property_details().attributes() == attributes) return; |
301 } else { | 299 } else { |
302 pair = AccessorPair::Copy(pair); | 300 pair = AccessorPair::Copy(pair); |
303 pair->set(component, *accessor); | 301 pair->set(component, *accessor); |
304 } | 302 } |
305 } else { | 303 } else { |
306 pair = factory()->NewAccessorPair(); | 304 pair = factory()->NewAccessorPair(); |
307 pair->set(component, *accessor); | 305 pair->set(component, *accessor); |
308 } | 306 } |
309 | 307 |
| 308 TransitionToAccessorPair(pair, attributes); |
| 309 } |
| 310 |
| 311 |
| 312 void LookupIterator::TransitionToAccessorPair(Handle<Object> pair, |
| 313 PropertyAttributes attributes) { |
| 314 Handle<JSObject> receiver = GetStoreTarget(); |
| 315 holder_ = receiver; |
| 316 |
| 317 PropertyDetails details(attributes, ACCESSOR_CONSTANT, 0, |
| 318 PropertyCellType::kMutable); |
| 319 |
310 if (IsElement()) { | 320 if (IsElement()) { |
311 // TODO(verwaest): Remove this hack once we have a quick way to check the | 321 // TODO(verwaest): Remove this hack once we have a quick way to check the |
312 // prototype chain in element setters. | 322 // prototype chain in element setters. |
313 // TODO(verwaest): Move code into the element accessor. | 323 // TODO(verwaest): Move code into the element accessor. |
314 bool was_dictionary = receiver->HasDictionaryElements(); | 324 bool was_dictionary = receiver->HasDictionaryElements(); |
315 Handle<SeededNumberDictionary> dictionary = | 325 Handle<SeededNumberDictionary> dictionary = |
316 JSObject::NormalizeElements(receiver); | 326 JSObject::NormalizeElements(receiver); |
317 was_dictionary = was_dictionary && dictionary->requires_slow_elements(); | 327 was_dictionary = was_dictionary && dictionary->requires_slow_elements(); |
318 | 328 |
319 dictionary = SeededNumberDictionary::Set(dictionary, index_, pair, details); | 329 dictionary = SeededNumberDictionary::Set(dictionary, index_, pair, details); |
320 dictionary->set_requires_slow_elements(); | 330 dictionary->set_requires_slow_elements(); |
321 | 331 |
322 if (receiver->HasSlowArgumentsElements()) { | 332 if (receiver->HasSlowArgumentsElements()) { |
323 FixedArray* parameter_map = FixedArray::cast(receiver->elements()); | 333 FixedArray* parameter_map = FixedArray::cast(receiver->elements()); |
324 uint32_t length = parameter_map->length() - 2; | 334 uint32_t length = parameter_map->length() - 2; |
325 if (number_ < length) { | 335 if (number_ < length) { |
326 parameter_map->set(number_ + 2, heap()->the_hole_value()); | 336 parameter_map->set(number_ + 2, heap()->the_hole_value()); |
327 } | 337 } |
328 FixedArray::cast(receiver->elements())->set(1, *dictionary); | 338 FixedArray::cast(receiver->elements())->set(1, *dictionary); |
329 } else { | 339 } else { |
330 receiver->set_elements(*dictionary); | 340 receiver->set_elements(*dictionary); |
331 if (!was_dictionary) heap()->ClearAllICsByKind(Code::KEYED_STORE_IC); | 341 if (!was_dictionary) heap()->ClearAllICsByKind(Code::KEYED_STORE_IC); |
332 } | 342 } |
333 } else { | 343 } else { |
| 344 PropertyNormalizationMode mode = receiver->map()->is_prototype_map() |
| 345 ? KEEP_INOBJECT_PROPERTIES |
| 346 : CLEAR_INOBJECT_PROPERTIES; |
| 347 // Normalize object to make this operation simple. |
| 348 JSObject::NormalizeProperties(receiver, mode, 0, |
| 349 "TransitionToAccessorPair"); |
| 350 |
334 JSObject::SetNormalizedProperty(receiver, name_, pair, details); | 351 JSObject::SetNormalizedProperty(receiver, name_, pair, details); |
335 JSObject::ReoptimizeIfPrototype(receiver); | 352 JSObject::ReoptimizeIfPrototype(receiver); |
336 } | 353 } |
337 | 354 |
338 holder_map_ = handle(receiver->map(), isolate_); | 355 holder_map_ = handle(receiver->map(), isolate_); |
339 ReloadPropertyInformation(); | 356 ReloadPropertyInformation(); |
340 } | 357 } |
341 | 358 |
342 | 359 |
343 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { | 360 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 case InterceptorState::kSkipNonMasking: | 560 case InterceptorState::kSkipNonMasking: |
544 return true; | 561 return true; |
545 case InterceptorState::kProcessNonMasking: | 562 case InterceptorState::kProcessNonMasking: |
546 return false; | 563 return false; |
547 } | 564 } |
548 } | 565 } |
549 return interceptor_state_ == InterceptorState::kProcessNonMasking; | 566 return interceptor_state_ == InterceptorState::kProcessNonMasking; |
550 } | 567 } |
551 } // namespace internal | 568 } // namespace internal |
552 } // namespace v8 | 569 } // namespace v8 |
OLD | NEW |