Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: src/objects.cc

Issue 1221713003: Distinguish slow from fast sloppy arguments (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698