| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 <iomanip> | 5 #include <iomanip> |
| 6 #include <sstream> | 6 #include <sstream> |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
| (...skipping 2405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2416 // Check the state of the root map. | 2416 // Check the state of the root map. |
| 2417 Handle<Map> root_map(old_map->FindRootMap(), isolate); | 2417 Handle<Map> root_map(old_map->FindRootMap(), isolate); |
| 2418 if (!old_map->EquivalentToForTransition(*root_map)) { | 2418 if (!old_map->EquivalentToForTransition(*root_map)) { |
| 2419 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2419 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2420 new_kind, new_attributes, | 2420 new_kind, new_attributes, |
| 2421 "GenAll_NotEquivalent"); | 2421 "GenAll_NotEquivalent"); |
| 2422 } | 2422 } |
| 2423 | 2423 |
| 2424 ElementsKind from_kind = root_map->elements_kind(); | 2424 ElementsKind from_kind = root_map->elements_kind(); |
| 2425 ElementsKind to_kind = old_map->elements_kind(); | 2425 ElementsKind to_kind = old_map->elements_kind(); |
| 2426 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS. |
| 2426 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS && | 2427 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS && |
| 2428 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS && |
| 2427 !(IsTransitionableFastElementsKind(from_kind) && | 2429 !(IsTransitionableFastElementsKind(from_kind) && |
| 2428 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) { | 2430 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) { |
| 2429 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2431 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2430 new_kind, new_attributes, | 2432 new_kind, new_attributes, |
| 2431 "GenAll_InvalidElementsTransition"); | 2433 "GenAll_InvalidElementsTransition"); |
| 2432 } | 2434 } |
| 2433 int root_nof = root_map->NumberOfOwnDescriptors(); | 2435 int root_nof = root_map->NumberOfOwnDescriptors(); |
| 2434 if (modify_index >= 0 && modify_index < root_nof) { | 2436 if (modify_index >= 0 && modify_index < root_nof) { |
| 2435 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2437 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2436 if (old_details.kind() != new_kind || | 2438 if (old_details.kind() != new_kind || |
| (...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3552 Handle<FixedArray> array, | 3554 Handle<FixedArray> array, |
| 3553 int valid_descriptors) { | 3555 int valid_descriptors) { |
| 3554 NeanderArray callbacks(descriptors); | 3556 NeanderArray callbacks(descriptors); |
| 3555 DCHECK(array->length() >= callbacks.length() + valid_descriptors); | 3557 DCHECK(array->length() >= callbacks.length() + valid_descriptors); |
| 3556 return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks, | 3558 return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks, |
| 3557 array, | 3559 array, |
| 3558 valid_descriptors); | 3560 valid_descriptors); |
| 3559 } | 3561 } |
| 3560 | 3562 |
| 3561 | 3563 |
| 3562 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { | 3564 static bool ContainsMap(MapHandleList* maps, Map* map) { |
| 3563 DCHECK(!map.is_null()); | 3565 DCHECK_NOT_NULL(map); |
| 3564 for (int i = 0; i < maps->length(); ++i) { | 3566 for (int i = 0; i < maps->length(); ++i) { |
| 3565 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true; | 3567 if (!maps->at(i).is_null() && *maps->at(i) == map) return true; |
| 3566 } | 3568 } |
| 3567 return false; | 3569 return false; |
| 3568 } | 3570 } |
| 3569 | 3571 |
| 3570 | 3572 |
| 3571 template <class T> | 3573 Handle<Map> Map::FindTransitionedMap(Handle<Map> map, |
| 3572 static Handle<T> MaybeNull(T* p) { | 3574 MapHandleList* candidates) { |
| 3573 if (p == NULL) return Handle<T>::null(); | 3575 ElementsKind kind = map->elements_kind(); |
| 3574 return Handle<T>(p); | 3576 bool packed = IsFastPackedElementsKind(kind); |
| 3575 } | |
| 3576 | 3577 |
| 3577 | 3578 Map* transition = nullptr; |
| 3578 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { | |
| 3579 ElementsKind kind = elements_kind(); | |
| 3580 Handle<Map> transitioned_map = Handle<Map>::null(); | |
| 3581 Handle<Map> current_map(this); | |
| 3582 bool packed = IsFastPackedElementsKind(kind); | |
| 3583 if (IsTransitionableFastElementsKind(kind)) { | 3579 if (IsTransitionableFastElementsKind(kind)) { |
| 3584 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) { | 3580 for (Map* current = map->ElementsTransitionMap(); |
| 3585 kind = GetNextMoreGeneralFastElementsKind(kind, false); | 3581 current != nullptr && current->has_fast_elements(); |
| 3586 Handle<Map> maybe_transitioned_map = | 3582 current = current->ElementsTransitionMap()) { |
| 3587 MaybeNull(current_map->LookupElementsTransitionMap(kind)); | 3583 if (ContainsMap(candidates, current) && |
| 3588 if (maybe_transitioned_map.is_null()) break; | 3584 (packed || !IsFastPackedElementsKind(current->elements_kind()))) { |
| 3589 if (ContainsMap(candidates, maybe_transitioned_map) && | 3585 transition = current; |
| 3590 (packed || !IsFastPackedElementsKind(kind))) { | 3586 packed = packed && IsFastPackedElementsKind(current->elements_kind()); |
| 3591 transitioned_map = maybe_transitioned_map; | |
| 3592 if (!IsFastPackedElementsKind(kind)) packed = false; | |
| 3593 } | 3587 } |
| 3594 current_map = maybe_transitioned_map; | |
| 3595 } | 3588 } |
| 3596 } | 3589 } |
| 3597 return transitioned_map; | 3590 return transition == nullptr ? Handle<Map>() : handle(transition); |
| 3598 } | 3591 } |
| 3599 | 3592 |
| 3600 | 3593 |
| 3601 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { | 3594 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { |
| 3602 Map* current_map = map; | 3595 Map* current_map = map; |
| 3603 int target_kind = | |
| 3604 IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind) | |
| 3605 ? to_kind | |
| 3606 : TERMINAL_FAST_ELEMENTS_KIND; | |
| 3607 | 3596 |
| 3608 // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data | 3597 // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data |
| 3609 // allows to change elements from arbitrary kind to any ExternalArray | 3598 // allows to change elements from arbitrary kind to any ExternalArray |
| 3610 // elements kind. Satisfy its requirements, checking whether we already | 3599 // elements kind. Satisfy its requirements, checking whether we already |
| 3611 // have the cached transition. | 3600 // have the cached transition. |
| 3612 if (IsExternalArrayElementsKind(to_kind) && | 3601 if (IsExternalArrayElementsKind(to_kind) && |
| 3613 !IsFixedTypedArrayElementsKind(map->elements_kind())) { | 3602 !IsFixedTypedArrayElementsKind(map->elements_kind())) { |
| 3614 Map* next_map = map->ElementsTransitionMap(); | 3603 Map* next_map = map->ElementsTransitionMap(); |
| 3615 if (next_map != NULL && next_map->elements_kind() == to_kind) { | 3604 if (next_map != NULL && next_map->elements_kind() == to_kind) { |
| 3616 return next_map; | 3605 return next_map; |
| 3617 } | 3606 } |
| 3618 return map; | 3607 return map; |
| 3619 } | 3608 } |
| 3620 | 3609 |
| 3621 ElementsKind kind = map->elements_kind(); | 3610 ElementsKind kind = map->elements_kind(); |
| 3622 while (kind != target_kind) { | 3611 while (kind != to_kind) { |
| 3623 kind = GetNextTransitionElementsKind(kind); | |
| 3624 Map* next_map = current_map->ElementsTransitionMap(); | 3612 Map* next_map = current_map->ElementsTransitionMap(); |
| 3625 if (next_map == NULL) return current_map; | 3613 if (next_map == nullptr) return current_map; |
| 3614 kind = next_map->elements_kind(); |
| 3626 current_map = next_map; | 3615 current_map = next_map; |
| 3627 } | 3616 } |
| 3628 | 3617 |
| 3629 Map* next_map = current_map->ElementsTransitionMap(); | 3618 DCHECK_EQ(to_kind, current_map->elements_kind()); |
| 3630 if (to_kind != kind && next_map != NULL) { | |
| 3631 DCHECK(to_kind == DICTIONARY_ELEMENTS); | |
| 3632 if (next_map->elements_kind() == to_kind) return next_map; | |
| 3633 } | |
| 3634 | |
| 3635 DCHECK(current_map->elements_kind() == target_kind); | |
| 3636 return current_map; | 3619 return current_map; |
| 3637 } | 3620 } |
| 3638 | 3621 |
| 3639 | 3622 |
| 3640 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { | 3623 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { |
| 3641 Map* to_map = FindClosestElementsTransition(this, to_kind); | 3624 Map* to_map = FindClosestElementsTransition(this, to_kind); |
| 3642 if (to_map->elements_kind() == to_kind) return to_map; | 3625 if (to_map->elements_kind() == to_kind) return to_map; |
| 3643 return NULL; | 3626 return nullptr; |
| 3644 } | 3627 } |
| 3645 | 3628 |
| 3646 | 3629 |
| 3647 bool Map::IsMapInArrayPrototypeChain() { | 3630 bool Map::IsMapInArrayPrototypeChain() { |
| 3648 Isolate* isolate = GetIsolate(); | 3631 Isolate* isolate = GetIsolate(); |
| 3649 if (isolate->initial_array_prototype()->map() == this) { | 3632 if (isolate->initial_array_prototype()->map() == this) { |
| 3650 return true; | 3633 return true; |
| 3651 } | 3634 } |
| 3652 | 3635 |
| 3653 if (isolate->initial_object_prototype()->map() == this) { | 3636 if (isolate->initial_object_prototype()->map() == this) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3674 DCHECK(IsTransitionElementsKind(map->elements_kind())); | 3657 DCHECK(IsTransitionElementsKind(map->elements_kind())); |
| 3675 | 3658 |
| 3676 Handle<Map> current_map = map; | 3659 Handle<Map> current_map = map; |
| 3677 | 3660 |
| 3678 ElementsKind kind = map->elements_kind(); | 3661 ElementsKind kind = map->elements_kind(); |
| 3679 TransitionFlag flag; | 3662 TransitionFlag flag; |
| 3680 if (map->is_prototype_map()) { | 3663 if (map->is_prototype_map()) { |
| 3681 flag = OMIT_TRANSITION; | 3664 flag = OMIT_TRANSITION; |
| 3682 } else { | 3665 } else { |
| 3683 flag = INSERT_TRANSITION; | 3666 flag = INSERT_TRANSITION; |
| 3684 while (kind != to_kind && !IsTerminalElementsKind(kind)) { | 3667 if (IsFastElementsKind(kind)) { |
| 3685 kind = GetNextTransitionElementsKind(kind); | 3668 while (kind != to_kind && !IsTerminalElementsKind(kind)) { |
| 3686 current_map = Map::CopyAsElementsKind(current_map, kind, flag); | 3669 kind = GetNextTransitionElementsKind(kind); |
| 3670 current_map = Map::CopyAsElementsKind(current_map, kind, flag); |
| 3671 } |
| 3687 } | 3672 } |
| 3688 } | 3673 } |
| 3689 | 3674 |
| 3690 // In case we are exiting the fast elements kind system, just add the map in | 3675 // In case we are exiting the fast elements kind system, just add the map in |
| 3691 // the end. | 3676 // the end. |
| 3692 if (kind != to_kind) { | 3677 if (kind != to_kind) { |
| 3693 current_map = Map::CopyAsElementsKind(current_map, to_kind, flag); | 3678 current_map = Map::CopyAsElementsKind(current_map, to_kind, flag); |
| 3694 } | 3679 } |
| 3695 | 3680 |
| 3696 DCHECK(current_map->elements_kind() == to_kind); | 3681 DCHECK(current_map->elements_kind() == to_kind); |
| 3697 return current_map; | 3682 return current_map; |
| 3698 } | 3683 } |
| 3699 | 3684 |
| 3700 | 3685 |
| 3701 Handle<Map> Map::TransitionElementsTo(Handle<Map> map, | 3686 Handle<Map> Map::TransitionElementsTo(Handle<Map> map, |
| 3702 ElementsKind to_kind) { | 3687 ElementsKind to_kind) { |
| 3703 ElementsKind from_kind = map->elements_kind(); | 3688 ElementsKind from_kind = map->elements_kind(); |
| 3704 if (from_kind == to_kind) return map; | 3689 if (from_kind == to_kind) return map; |
| 3705 | 3690 |
| 3706 Isolate* isolate = map->GetIsolate(); | 3691 Isolate* isolate = map->GetIsolate(); |
| 3707 Context* native_context = isolate->context()->native_context(); | 3692 Context* native_context = isolate->context()->native_context(); |
| 3708 Object* maybe_array_maps = map->is_strong() | 3693 if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) { |
| 3709 ? native_context->js_array_strong_maps() | 3694 if (*map == native_context->fast_aliased_arguments_map()) { |
| 3710 : native_context->js_array_maps(); | 3695 DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind); |
| 3711 if (maybe_array_maps->IsFixedArray()) { | 3696 return handle(native_context->slow_aliased_arguments_map()); |
| 3712 DisallowHeapAllocation no_gc; | 3697 } |
| 3713 FixedArray* array_maps = FixedArray::cast(maybe_array_maps); | 3698 } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) { |
| 3714 if (array_maps->get(from_kind) == *map) { | 3699 if (*map == native_context->slow_aliased_arguments_map()) { |
| 3715 Object* maybe_transitioned_map = array_maps->get(to_kind); | 3700 DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind); |
| 3716 if (maybe_transitioned_map->IsMap()) { | 3701 return handle(native_context->fast_aliased_arguments_map()); |
| 3717 return handle(Map::cast(maybe_transitioned_map)); | 3702 } |
| 3703 } else { |
| 3704 Object* maybe_array_maps = map->is_strong() |
| 3705 ? native_context->js_array_strong_maps() |
| 3706 : native_context->js_array_maps(); |
| 3707 if (maybe_array_maps->IsFixedArray()) { |
| 3708 DisallowHeapAllocation no_gc; |
| 3709 FixedArray* array_maps = FixedArray::cast(maybe_array_maps); |
| 3710 if (array_maps->get(from_kind) == *map) { |
| 3711 Object* maybe_transitioned_map = array_maps->get(to_kind); |
| 3712 if (maybe_transitioned_map->IsMap()) { |
| 3713 return handle(Map::cast(maybe_transitioned_map)); |
| 3714 } |
| 3718 } | 3715 } |
| 3719 } | 3716 } |
| 3720 } | 3717 } |
| 3721 | 3718 |
| 3722 DCHECK(!map->IsUndefined()); | 3719 DCHECK(!map->IsUndefined()); |
| 3723 bool allow_store_transition = IsTransitionElementsKind(from_kind); | 3720 bool allow_store_transition = IsTransitionElementsKind(from_kind); |
| 3724 // Only store fast element maps in ascending generality. | 3721 // Only store fast element maps in ascending generality. |
| 3725 if (IsFastElementsKind(to_kind)) { | 3722 if (IsFastElementsKind(to_kind)) { |
| 3726 allow_store_transition &= | 3723 allow_store_transition = |
| 3727 IsTransitionableFastElementsKind(from_kind) && | 3724 allow_store_transition && IsTransitionableFastElementsKind(from_kind) && |
| 3728 IsMoreGeneralElementsKindTransition(from_kind, to_kind); | 3725 IsMoreGeneralElementsKindTransition(from_kind, to_kind); |
| 3729 } | 3726 } |
| 3730 | 3727 |
| 3731 if (!allow_store_transition) { | 3728 if (!allow_store_transition) { |
| 3732 return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION); | 3729 return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION); |
| 3733 } | 3730 } |
| 3734 | 3731 |
| 3735 return Map::AsElementsKind(map, to_kind); | 3732 return Map::AsElementsKind(map, to_kind); |
| 3736 } | 3733 } |
| 3737 | 3734 |
| (...skipping 1072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4810 : array->length(); | 4807 : array->length(); |
| 4811 int old_capacity = 0; | 4808 int old_capacity = 0; |
| 4812 int used_elements = 0; | 4809 int used_elements = 0; |
| 4813 object->GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 4810 object->GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 4814 Handle<SeededNumberDictionary> dictionary = | 4811 Handle<SeededNumberDictionary> dictionary = |
| 4815 SeededNumberDictionary::New(isolate, used_elements); | 4812 SeededNumberDictionary::New(isolate, used_elements); |
| 4816 | 4813 |
| 4817 dictionary = CopyFastElementsToDictionary(array, length, dictionary); | 4814 dictionary = CopyFastElementsToDictionary(array, length, dictionary); |
| 4818 | 4815 |
| 4819 // Switch to using the dictionary as the backing storage for elements. | 4816 // Switch to using the dictionary as the backing storage for elements. |
| 4817 ElementsKind target_kind = |
| 4818 is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS; |
| 4819 Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind); |
| 4820 // Set the new map first to satify the elements type assert in set_elements(). |
| 4821 JSObject::MigrateToMap(object, new_map); |
| 4822 |
| 4820 if (is_arguments) { | 4823 if (is_arguments) { |
| 4821 FixedArray::cast(object->elements())->set(1, *dictionary); | 4824 FixedArray::cast(object->elements())->set(1, *dictionary); |
| 4822 } else { | 4825 } else { |
| 4823 // Set the new map first to satify the elements type assert in | |
| 4824 // set_elements(). | |
| 4825 Handle<Map> new_map = | |
| 4826 JSObject::GetElementsTransitionMap(object, DICTIONARY_ELEMENTS); | |
| 4827 | |
| 4828 JSObject::MigrateToMap(object, new_map); | |
| 4829 object->set_elements(*dictionary); | 4826 object->set_elements(*dictionary); |
| 4830 } | 4827 } |
| 4831 | 4828 |
| 4832 isolate->counters()->elements_to_dictionary()->Increment(); | 4829 isolate->counters()->elements_to_dictionary()->Increment(); |
| 4833 | 4830 |
| 4834 #ifdef DEBUG | 4831 #ifdef DEBUG |
| 4835 if (FLAG_trace_normalization) { | 4832 if (FLAG_trace_normalization) { |
| 4836 OFStream os(stdout); | 4833 OFStream os(stdout); |
| 4837 os << "Object elements have been normalized:\n"; | 4834 os << "Object elements have been normalized:\n"; |
| 4838 object->Print(os); | 4835 object->Print(os); |
| 4839 } | 4836 } |
| 4840 #endif | 4837 #endif |
| 4841 | 4838 |
| 4842 DCHECK(object->HasDictionaryElements() || | 4839 DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements()); |
| 4843 object->HasDictionaryArgumentsElements()); | |
| 4844 return dictionary; | 4840 return dictionary; |
| 4845 } | 4841 } |
| 4846 | 4842 |
| 4847 | 4843 |
| 4848 static Smi* GenerateIdentityHash(Isolate* isolate) { | 4844 static Smi* GenerateIdentityHash(Isolate* isolate) { |
| 4849 int hash_value; | 4845 int hash_value; |
| 4850 int attempts = 0; | 4846 int attempts = 0; |
| 4851 do { | 4847 do { |
| 4852 // Generate a random 32-bit hash value but limit range to fit | 4848 // Generate a random 32-bit hash value but limit range to fit |
| 4853 // within a smi. | 4849 // within a smi. |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5330 case FAST_SMI_ELEMENTS: | 5326 case FAST_SMI_ELEMENTS: |
| 5331 case FAST_HOLEY_SMI_ELEMENTS: | 5327 case FAST_HOLEY_SMI_ELEMENTS: |
| 5332 break; | 5328 break; |
| 5333 case FAST_ELEMENTS: | 5329 case FAST_ELEMENTS: |
| 5334 case FAST_HOLEY_ELEMENTS: | 5330 case FAST_HOLEY_ELEMENTS: |
| 5335 case DICTIONARY_ELEMENTS: { | 5331 case DICTIONARY_ELEMENTS: { |
| 5336 FixedArray* elements = FixedArray::cast(this->elements()); | 5332 FixedArray* elements = FixedArray::cast(this->elements()); |
| 5337 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 5333 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
| 5338 break; | 5334 break; |
| 5339 } | 5335 } |
| 5340 case SLOPPY_ARGUMENTS_ELEMENTS: { | 5336 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 5337 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { |
| 5341 FixedArray* parameter_map = FixedArray::cast(elements()); | 5338 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 5342 // Check the mapped parameters. | 5339 // Check the mapped parameters. |
| 5343 int length = parameter_map->length(); | 5340 int length = parameter_map->length(); |
| 5344 for (int i = 2; i < length; ++i) { | 5341 for (int i = 2; i < length; ++i) { |
| 5345 Object* value = parameter_map->get(i); | 5342 Object* value = parameter_map->get(i); |
| 5346 if (!value->IsTheHole() && value == obj) return true; | 5343 if (!value->IsTheHole() && value == obj) return true; |
| 5347 } | 5344 } |
| 5348 // Check the arguments. | 5345 // Check the arguments. |
| 5349 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 5346 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 5350 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : | 5347 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5428 // It's not possible to seal objects with external array elements | 5425 // It's not possible to seal objects with external array elements |
| 5429 if (object->HasExternalArrayElements() || | 5426 if (object->HasExternalArrayElements() || |
| 5430 object->HasFixedTypedArrayElements()) { | 5427 object->HasFixedTypedArrayElements()) { |
| 5431 THROW_NEW_ERROR( | 5428 THROW_NEW_ERROR( |
| 5432 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray), | 5429 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray), |
| 5433 Object); | 5430 Object); |
| 5434 } | 5431 } |
| 5435 | 5432 |
| 5436 // If there are fast elements we normalize. | 5433 // If there are fast elements we normalize. |
| 5437 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 5434 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 5438 DCHECK(object->HasDictionaryElements() || | 5435 DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements()); |
| 5439 object->HasDictionaryArgumentsElements()); | |
| 5440 | 5436 |
| 5441 // Make sure that we never go back to fast case. | 5437 // Make sure that we never go back to fast case. |
| 5442 dictionary->set_requires_slow_elements(); | 5438 dictionary->set_requires_slow_elements(); |
| 5443 | 5439 |
| 5444 // Do a map transition, other objects with this map may still | 5440 // Do a map transition, other objects with this map may still |
| 5445 // be extensible. | 5441 // be extensible. |
| 5446 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5442 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5447 Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions"); | 5443 Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions"); |
| 5448 | 5444 |
| 5449 new_map->set_is_extensible(false); | 5445 new_map->set_is_extensible(false); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5857 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), | 5853 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), |
| 5858 JSObject); | 5854 JSObject); |
| 5859 if (copying) { | 5855 if (copying) { |
| 5860 element_dictionary->ValueAtPut(i, *result); | 5856 element_dictionary->ValueAtPut(i, *result); |
| 5861 } | 5857 } |
| 5862 } | 5858 } |
| 5863 } | 5859 } |
| 5864 } | 5860 } |
| 5865 break; | 5861 break; |
| 5866 } | 5862 } |
| 5867 case SLOPPY_ARGUMENTS_ELEMENTS: | 5863 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 5864 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
| 5868 UNIMPLEMENTED(); | 5865 UNIMPLEMENTED(); |
| 5869 break; | 5866 break; |
| 5870 | 5867 |
| 5871 | 5868 |
| 5872 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 5869 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 5873 case EXTERNAL_##TYPE##_ELEMENTS: \ | 5870 case EXTERNAL_##TYPE##_ELEMENTS: \ |
| 5874 case TYPE##_ELEMENTS: \ | 5871 case TYPE##_ELEMENTS: \ |
| 5875 | 5872 |
| 5876 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 5873 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 5877 #undef TYPED_ARRAY_CASE | 5874 #undef TYPED_ARRAY_CASE |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6274 | 6271 |
| 6275 case DICTIONARY_ELEMENTS: | 6272 case DICTIONARY_ELEMENTS: |
| 6276 if (UpdateGetterSetterInDictionary(object->element_dictionary(), | 6273 if (UpdateGetterSetterInDictionary(object->element_dictionary(), |
| 6277 index, | 6274 index, |
| 6278 *getter, | 6275 *getter, |
| 6279 *setter, | 6276 *setter, |
| 6280 attributes)) { | 6277 attributes)) { |
| 6281 return; | 6278 return; |
| 6282 } | 6279 } |
| 6283 break; | 6280 break; |
| 6284 case SLOPPY_ARGUMENTS_ELEMENTS: { | 6281 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 6282 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { |
| 6285 // Ascertain whether we have read-only properties or an existing | 6283 // Ascertain whether we have read-only properties or an existing |
| 6286 // getter/setter pair in an arguments elements dictionary backing | 6284 // getter/setter pair in an arguments elements dictionary backing |
| 6287 // store. | 6285 // store. |
| 6288 FixedArray* parameter_map = FixedArray::cast(object->elements()); | 6286 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
| 6289 uint32_t length = parameter_map->length(); | 6287 uint32_t length = parameter_map->length(); |
| 6290 Object* probe = | 6288 Object* probe = |
| 6291 index < (length - 2) ? parameter_map->get(index + 2) : NULL; | 6289 index < (length - 2) ? parameter_map->get(index + 2) : NULL; |
| 6292 if (probe == NULL || probe->IsTheHole()) { | 6290 if (probe == NULL || probe->IsTheHole()) { |
| 6293 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 6291 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 6294 if (arguments->IsDictionary()) { | 6292 if (arguments->IsDictionary()) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6340 uint32_t index, | 6338 uint32_t index, |
| 6341 Handle<Object> structure, | 6339 Handle<Object> structure, |
| 6342 PropertyAttributes attributes) { | 6340 PropertyAttributes attributes) { |
| 6343 Heap* heap = object->GetHeap(); | 6341 Heap* heap = object->GetHeap(); |
| 6344 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, | 6342 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, |
| 6345 PropertyCellType::kNoCell); | 6343 PropertyCellType::kNoCell); |
| 6346 | 6344 |
| 6347 // Normalize elements to make this operation simple. | 6345 // Normalize elements to make this operation simple. |
| 6348 bool had_dictionary_elements = object->HasDictionaryElements(); | 6346 bool had_dictionary_elements = object->HasDictionaryElements(); |
| 6349 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6347 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 6350 DCHECK(object->HasDictionaryElements() || | 6348 DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements()); |
| 6351 object->HasDictionaryArgumentsElements()); | |
| 6352 // Update the dictionary with the new ACCESSOR_CONSTANT property. | 6349 // Update the dictionary with the new ACCESSOR_CONSTANT property. |
| 6353 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6350 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
| 6354 details); | 6351 details); |
| 6355 dictionary->set_requires_slow_elements(); | 6352 dictionary->set_requires_slow_elements(); |
| 6356 | 6353 |
| 6357 // Update the dictionary backing store on the object. | 6354 // Update the dictionary backing store on the object. |
| 6358 if (object->elements()->map() == heap->sloppy_arguments_elements_map()) { | 6355 if (object->elements()->map() == heap->sloppy_arguments_elements_map()) { |
| 6359 // Also delete any parameter alias. | 6356 // Also delete any parameter alias. |
| 6360 // | 6357 // |
| 6361 // TODO(kmillikin): when deleting the last parameter alias we could | 6358 // TODO(kmillikin): when deleting the last parameter alias we could |
| (...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7123 | 7120 |
| 7124 case FAST_DOUBLE_ELEMENTS: | 7121 case FAST_DOUBLE_ELEMENTS: |
| 7125 case FAST_HOLEY_DOUBLE_ELEMENTS: | 7122 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 7126 if (value->IsNumber()) return map; | 7123 if (value->IsNumber()) return map; |
| 7127 kind = FAST_ELEMENTS; | 7124 kind = FAST_ELEMENTS; |
| 7128 break; | 7125 break; |
| 7129 | 7126 |
| 7130 case FAST_ELEMENTS: | 7127 case FAST_ELEMENTS: |
| 7131 case FAST_HOLEY_ELEMENTS: | 7128 case FAST_HOLEY_ELEMENTS: |
| 7132 case DICTIONARY_ELEMENTS: | 7129 case DICTIONARY_ELEMENTS: |
| 7133 case SLOPPY_ARGUMENTS_ELEMENTS: | 7130 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 7131 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
| 7134 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 7132 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 7135 case EXTERNAL_##TYPE##_ELEMENTS: \ | 7133 case EXTERNAL_##TYPE##_ELEMENTS: \ |
| 7136 case TYPE##_ELEMENTS: | 7134 case TYPE##_ELEMENTS: |
| 7137 | 7135 |
| 7138 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 7136 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 7139 #undef TYPED_ARRAY_CASE | 7137 #undef TYPED_ARRAY_CASE |
| 7140 return map; | 7138 return map; |
| 7141 } | 7139 } |
| 7142 | 7140 |
| 7143 if (holey) kind = GetHoleyElementsKind(kind); | 7141 if (holey) kind = GetHoleyElementsKind(kind); |
| (...skipping 5149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12293 uint32_t arg_count, | 12291 uint32_t arg_count, |
| 12294 EnsureElementsMode mode) { | 12292 EnsureElementsMode mode) { |
| 12295 // Elements in |Arguments| are ordered backwards (because they're on the | 12293 // Elements in |Arguments| are ordered backwards (because they're on the |
| 12296 // stack), but the method that's called here iterates over them in forward | 12294 // stack), but the method that's called here iterates over them in forward |
| 12297 // direction. | 12295 // direction. |
| 12298 return EnsureCanContainElements( | 12296 return EnsureCanContainElements( |
| 12299 object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode); | 12297 object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode); |
| 12300 } | 12298 } |
| 12301 | 12299 |
| 12302 | 12300 |
| 12303 bool JSObject::HasFastArgumentsElements() { | |
| 12304 Heap* heap = GetHeap(); | |
| 12305 if (!elements()->IsFixedArray()) return false; | |
| 12306 FixedArray* elements = FixedArray::cast(this->elements()); | |
| 12307 if (elements->map() != heap->sloppy_arguments_elements_map()) { | |
| 12308 return false; | |
| 12309 } | |
| 12310 FixedArray* arguments = FixedArray::cast(elements->get(1)); | |
| 12311 return !arguments->IsDictionary(); | |
| 12312 } | |
| 12313 | |
| 12314 | |
| 12315 bool JSObject::HasDictionaryArgumentsElements() { | |
| 12316 Heap* heap = GetHeap(); | |
| 12317 if (!elements()->IsFixedArray()) return false; | |
| 12318 FixedArray* elements = FixedArray::cast(this->elements()); | |
| 12319 if (elements->map() != heap->sloppy_arguments_elements_map()) { | |
| 12320 return false; | |
| 12321 } | |
| 12322 FixedArray* arguments = FixedArray::cast(elements->get(1)); | |
| 12323 return arguments->IsDictionary(); | |
| 12324 } | |
| 12325 | |
| 12326 | |
| 12327 ElementsAccessor* JSObject::GetElementsAccessor() { | 12301 ElementsAccessor* JSObject::GetElementsAccessor() { |
| 12328 return ElementsAccessor::ForKind(GetElementsKind()); | 12302 return ElementsAccessor::ForKind(GetElementsKind()); |
| 12329 } | 12303 } |
| 12330 | 12304 |
| 12331 | 12305 |
| 12332 void JSObject::ValidateElements(Handle<JSObject> object) { | 12306 void JSObject::ValidateElements(Handle<JSObject> object) { |
| 12333 #ifdef ENABLE_SLOW_DCHECKS | 12307 #ifdef ENABLE_SLOW_DCHECKS |
| 12334 if (FLAG_enable_slow_asserts) { | 12308 if (FLAG_enable_slow_asserts) { |
| 12335 ElementsAccessor* accessor = object->GetElementsAccessor(); | 12309 ElementsAccessor* accessor = object->GetElementsAccessor(); |
| 12336 accessor->Validate(object); | 12310 accessor->Validate(object); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12383 Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements())); | 12357 Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements())); |
| 12384 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); | 12358 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
| 12385 uint32_t new_capacity; | 12359 uint32_t new_capacity; |
| 12386 return ShouldConvertToSlowElements(this, capacity, index, &new_capacity); | 12360 return ShouldConvertToSlowElements(this, capacity, index, &new_capacity); |
| 12387 } | 12361 } |
| 12388 return false; | 12362 return false; |
| 12389 } | 12363 } |
| 12390 | 12364 |
| 12391 | 12365 |
| 12392 static ElementsKind BestFittingFastElementsKind(JSObject* object) { | 12366 static ElementsKind BestFittingFastElementsKind(JSObject* object) { |
| 12393 if (object->HasSloppyArgumentsElements()) return SLOPPY_ARGUMENTS_ELEMENTS; | 12367 if (object->HasSloppyArgumentsElements()) { |
| 12368 return FAST_SLOPPY_ARGUMENTS_ELEMENTS; |
| 12369 } |
| 12394 DCHECK(object->HasDictionaryElements()); | 12370 DCHECK(object->HasDictionaryElements()); |
| 12395 SeededNumberDictionary* dictionary = object->element_dictionary(); | 12371 SeededNumberDictionary* dictionary = object->element_dictionary(); |
| 12396 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS; | 12372 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS; |
| 12397 for (int i = 0; i < dictionary->Capacity(); i++) { | 12373 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 12398 Object* key = dictionary->KeyAt(i); | 12374 Object* key = dictionary->KeyAt(i); |
| 12399 if (key->IsNumber()) { | 12375 if (key->IsNumber()) { |
| 12400 Object* value = dictionary->ValueAt(i); | 12376 Object* value = dictionary->ValueAt(i); |
| 12401 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS; | 12377 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS; |
| 12402 if (!value->IsSmi()) { | 12378 if (!value->IsSmi()) { |
| 12403 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS; | 12379 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12450 Handle<Object> old_length_handle; | 12426 Handle<Object> old_length_handle; |
| 12451 if (object->IsJSArray()) { | 12427 if (object->IsJSArray()) { |
| 12452 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length)); | 12428 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length)); |
| 12453 if (object->map()->is_observed()) { | 12429 if (object->map()->is_observed()) { |
| 12454 old_length_handle = handle(JSArray::cast(*object)->length(), isolate); | 12430 old_length_handle = handle(JSArray::cast(*object)->length(), isolate); |
| 12455 } | 12431 } |
| 12456 } | 12432 } |
| 12457 | 12433 |
| 12458 ElementsKind kind = object->GetElementsKind(); | 12434 ElementsKind kind = object->GetElementsKind(); |
| 12459 FixedArrayBase* elements = object->elements(); | 12435 FixedArrayBase* elements = object->elements(); |
| 12436 ElementsKind dictionary_kind = DICTIONARY_ELEMENTS; |
| 12460 if (IsSloppyArgumentsElements(kind)) { | 12437 if (IsSloppyArgumentsElements(kind)) { |
| 12461 elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1)); | 12438 elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1)); |
| 12439 dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS; |
| 12462 } | 12440 } |
| 12463 | 12441 |
| 12464 if (attributes != NONE) { | 12442 if (attributes != NONE) { |
| 12465 kind = DICTIONARY_ELEMENTS; | 12443 kind = dictionary_kind; |
| 12466 } else if (elements->IsSeededNumberDictionary()) { | 12444 } else if (elements->IsSeededNumberDictionary()) { |
| 12467 kind = ShouldConvertToFastElements(*object, | 12445 kind = ShouldConvertToFastElements(*object, |
| 12468 SeededNumberDictionary::cast(elements), | 12446 SeededNumberDictionary::cast(elements), |
| 12469 index, &new_capacity) | 12447 index, &new_capacity) |
| 12470 ? BestFittingFastElementsKind(*object) | 12448 ? BestFittingFastElementsKind(*object) |
| 12471 : DICTIONARY_ELEMENTS; // Overwrite in case of arguments. | 12449 : dictionary_kind; // Overwrite in case of arguments. |
| 12472 } else if (ShouldConvertToSlowElements( | 12450 } else if (ShouldConvertToSlowElements( |
| 12473 *object, static_cast<uint32_t>(elements->length()), index, | 12451 *object, static_cast<uint32_t>(elements->length()), index, |
| 12474 &new_capacity)) { | 12452 &new_capacity)) { |
| 12475 kind = DICTIONARY_ELEMENTS; | 12453 kind = dictionary_kind; |
| 12476 } | 12454 } |
| 12477 | 12455 |
| 12478 if (kind == DICTIONARY_ELEMENTS && object->HasSloppyArgumentsElements()) { | 12456 ElementsKind to = value->OptimalElementsKind(); |
| 12479 // TODO(verwaest): Distinguish fast/slow sloppy elements in ElementsKind. | 12457 if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) { |
| 12480 Handle<SeededNumberDictionary> dictionary = | 12458 to = GetHoleyElementsKind(to); |
| 12481 elements->IsSeededNumberDictionary() | 12459 kind = GetHoleyElementsKind(kind); |
| 12482 ? handle(SeededNumberDictionary::cast(elements)) | |
| 12483 : NormalizeElements(object); | |
| 12484 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | |
| 12485 Handle<SeededNumberDictionary> new_dictionary = | |
| 12486 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, | |
| 12487 details); | |
| 12488 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); | |
| 12489 if (*dictionary != *new_dictionary) { | |
| 12490 FixedArray::cast(object->elements())->set(1, *new_dictionary); | |
| 12491 } | |
| 12492 } else { | |
| 12493 ElementsKind to = value->OptimalElementsKind(); | |
| 12494 if (IsHoleyElementsKind(kind) || !object->IsJSArray() || | |
| 12495 index > old_length) { | |
| 12496 to = GetHoleyElementsKind(to); | |
| 12497 kind = GetHoleyElementsKind(kind); | |
| 12498 } | |
| 12499 to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind; | |
| 12500 ElementsAccessor* accessor = ElementsAccessor::ForKind(to); | |
| 12501 accessor->Add(object, index, value, attributes, new_capacity); | |
| 12502 } | 12460 } |
| 12461 to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind; |
| 12462 ElementsAccessor* accessor = ElementsAccessor::ForKind(to); |
| 12463 accessor->Add(object, index, value, attributes, new_capacity); |
| 12503 | 12464 |
| 12504 uint32_t new_length = old_length; | 12465 uint32_t new_length = old_length; |
| 12505 Handle<Object> new_length_handle; | 12466 Handle<Object> new_length_handle; |
| 12506 if (object->IsJSArray() && index >= old_length) { | 12467 if (object->IsJSArray() && index >= old_length) { |
| 12507 new_length = index + 1; | 12468 new_length = index + 1; |
| 12508 new_length_handle = isolate->factory()->NewNumberFromUint(new_length); | 12469 new_length_handle = isolate->factory()->NewNumberFromUint(new_length); |
| 12509 JSArray::cast(*object)->set_length(*new_length_handle); | 12470 JSArray::cast(*object)->set_length(*new_length_handle); |
| 12510 } | 12471 } |
| 12511 | 12472 |
| 12512 if (!old_length_handle.is_null() && new_length != old_length) { | 12473 if (!old_length_handle.is_null() && new_length != old_length) { |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12751 } | 12712 } |
| 12752 | 12713 |
| 12753 | 12714 |
| 12754 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { | 12715 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { |
| 12755 *capacity = 0; | 12716 *capacity = 0; |
| 12756 *used = 0; | 12717 *used = 0; |
| 12757 | 12718 |
| 12758 FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements()); | 12719 FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements()); |
| 12759 FixedArray* backing_store = NULL; | 12720 FixedArray* backing_store = NULL; |
| 12760 switch (GetElementsKind()) { | 12721 switch (GetElementsKind()) { |
| 12761 case SLOPPY_ARGUMENTS_ELEMENTS: | 12722 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 12723 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
| 12762 backing_store_base = | 12724 backing_store_base = |
| 12763 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 12725 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
| 12764 backing_store = FixedArray::cast(backing_store_base); | 12726 backing_store = FixedArray::cast(backing_store_base); |
| 12765 if (backing_store->IsDictionary()) { | 12727 if (backing_store->IsDictionary()) { |
| 12766 SeededNumberDictionary* dictionary = | 12728 SeededNumberDictionary* dictionary = |
| 12767 SeededNumberDictionary::cast(backing_store); | 12729 SeededNumberDictionary::cast(backing_store); |
| 12768 *capacity = dictionary->Capacity(); | 12730 *capacity = dictionary->Capacity(); |
| 12769 *used = dictionary->NumberOfElements(); | 12731 *used = dictionary->NumberOfElements(); |
| 12770 break; | 12732 break; |
| 12771 } | 12733 } |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13248 } | 13210 } |
| 13249 | 13211 |
| 13250 case DICTIONARY_ELEMENTS: { | 13212 case DICTIONARY_ELEMENTS: { |
| 13251 if (storage != NULL) { | 13213 if (storage != NULL) { |
| 13252 element_dictionary()->CopyKeysTo(storage, filter, | 13214 element_dictionary()->CopyKeysTo(storage, filter, |
| 13253 SeededNumberDictionary::SORTED); | 13215 SeededNumberDictionary::SORTED); |
| 13254 } | 13216 } |
| 13255 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); | 13217 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); |
| 13256 break; | 13218 break; |
| 13257 } | 13219 } |
| 13258 case SLOPPY_ARGUMENTS_ELEMENTS: { | 13220 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 13221 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { |
| 13259 FixedArray* parameter_map = FixedArray::cast(elements()); | 13222 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 13260 int mapped_length = parameter_map->length() - 2; | 13223 int mapped_length = parameter_map->length() - 2; |
| 13261 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 13224 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 13262 if (arguments->IsDictionary()) { | 13225 if (arguments->IsDictionary()) { |
| 13263 // Copy the keys from arguments first, because Dictionary::CopyKeysTo | 13226 // Copy the keys from arguments first, because Dictionary::CopyKeysTo |
| 13264 // will insert in storage starting at index 0. | 13227 // will insert in storage starting at index 0. |
| 13265 SeededNumberDictionary* dictionary = | 13228 SeededNumberDictionary* dictionary = |
| 13266 SeededNumberDictionary::cast(arguments); | 13229 SeededNumberDictionary::cast(arguments); |
| 13267 if (storage != NULL) { | 13230 if (storage != NULL) { |
| 13268 dictionary->CopyKeysTo(storage, filter, | 13231 dictionary->CopyKeysTo(storage, filter, |
| (...skipping 2881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16150 Handle<Object> new_value) { | 16113 Handle<Object> new_value) { |
| 16151 if (cell->value() != *new_value) { | 16114 if (cell->value() != *new_value) { |
| 16152 cell->set_value(*new_value); | 16115 cell->set_value(*new_value); |
| 16153 Isolate* isolate = cell->GetIsolate(); | 16116 Isolate* isolate = cell->GetIsolate(); |
| 16154 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16117 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 16155 isolate, DependentCode::kPropertyCellChangedGroup); | 16118 isolate, DependentCode::kPropertyCellChangedGroup); |
| 16156 } | 16119 } |
| 16157 } | 16120 } |
| 16158 } // namespace internal | 16121 } // namespace internal |
| 16159 } // namespace v8 | 16122 } // namespace v8 |
| OLD | NEW |