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

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

Powered by Google App Engine
This is Rietveld 408576698