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

Side by Side Diff: src/objects.cc

Issue 2015513002: [runtime] Ensure that all elements kind transitions are chained to the root map. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebasing Created 4 years, 6 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-inl.h » ('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 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 3198 matching lines...) Expand 10 before | Expand all | Expand 10 after
3209 3209
3210 int Map::NumberOfFields() { 3210 int Map::NumberOfFields() {
3211 DescriptorArray* descriptors = instance_descriptors(); 3211 DescriptorArray* descriptors = instance_descriptors();
3212 int result = 0; 3212 int result = 0;
3213 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { 3213 for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
3214 if (descriptors->GetDetails(i).location() == kField) result++; 3214 if (descriptors->GetDetails(i).location() == kField) result++;
3215 } 3215 }
3216 return result; 3216 return result;
3217 } 3217 }
3218 3218
3219
3220 Handle<Map> Map::CopyGeneralizeAllRepresentations( 3219 Handle<Map> Map::CopyGeneralizeAllRepresentations(
3221 Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind, 3220 Handle<Map> map, ElementsKind elements_kind, int modify_index,
3222 PropertyAttributes attributes, const char* reason) { 3221 StoreMode store_mode, PropertyKind kind, PropertyAttributes attributes,
3222 const char* reason) {
3223 Isolate* isolate = map->GetIsolate(); 3223 Isolate* isolate = map->GetIsolate();
3224 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); 3224 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
3225 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 3225 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
3226 Handle<DescriptorArray> descriptors = 3226 Handle<DescriptorArray> descriptors =
3227 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors); 3227 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
3228 3228
3229 for (int i = 0; i < number_of_own_descriptors; i++) { 3229 for (int i = 0; i < number_of_own_descriptors; i++) {
3230 descriptors->SetRepresentation(i, Representation::Tagged()); 3230 descriptors->SetRepresentation(i, Representation::Tagged());
3231 if (descriptors->GetDetails(i).type() == DATA) { 3231 if (descriptors->GetDetails(i).type() == DATA) {
3232 descriptors->SetValue(i, FieldType::Any()); 3232 descriptors->SetValue(i, FieldType::Any());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3268 } 3268 }
3269 map->PrintGeneralization( 3269 map->PrintGeneralization(
3270 stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(), 3270 stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
3271 new_map->NumberOfOwnDescriptors(), 3271 new_map->NumberOfOwnDescriptors(),
3272 details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD, 3272 details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
3273 details.representation(), Representation::Tagged(), field_type, 3273 details.representation(), Representation::Tagged(), field_type,
3274 MaybeHandle<Object>(), FieldType::Any(isolate), 3274 MaybeHandle<Object>(), FieldType::Any(isolate),
3275 MaybeHandle<Object>()); 3275 MaybeHandle<Object>());
3276 } 3276 }
3277 } 3277 }
3278 new_map->set_elements_kind(elements_kind);
3278 return new_map; 3279 return new_map;
3279 } 3280 }
3280 3281
3281 3282
3282 void Map::DeprecateTransitionTree() { 3283 void Map::DeprecateTransitionTree() {
3283 if (is_deprecated()) return; 3284 if (is_deprecated()) return;
3284 Object* transitions = raw_transitions(); 3285 Object* transitions = raw_transitions();
3285 int num_transitions = TransitionArray::NumberOfTransitions(transitions); 3286 int num_transitions = TransitionArray::NumberOfTransitions(transitions);
3286 for (int i = 0; i < num_transitions; ++i) { 3287 for (int i = 0; i < num_transitions; ++i) {
3287 TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree(); 3288 TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
3520 DCHECK_EQ(details.location(), location); 3521 DCHECK_EQ(details.location(), location);
3521 #endif 3522 #endif
3522 if (location == kField) { 3523 if (location == kField) {
3523 return handle(descriptors->GetFieldType(descriptor), isolate); 3524 return handle(descriptors->GetFieldType(descriptor), isolate);
3524 } else { 3525 } else {
3525 return descriptors->GetValue(descriptor) 3526 return descriptors->GetValue(descriptor)
3526 ->OptimalType(isolate, representation); 3527 ->OptimalType(isolate, representation);
3527 } 3528 }
3528 } 3529 }
3529 3530
3530 3531 // Reconfigures elements kind to |new_elements_kind| and/or property at
3531 // Reconfigures property at |modify_index| with |new_kind|, |new_attributes|, 3532 // |modify_index| with |new_kind|, |new_attributes|, |store_mode| and/or
3532 // |store_mode| and/or |new_representation|/|new_field_type|. 3533 // |new_representation|/|new_field_type|.
3533 // If |modify_index| is negative then no properties are reconfigured but the 3534 // If |modify_index| is negative then no properties are reconfigured but the
3534 // map is migrated to the up-to-date non-deprecated state. 3535 // map is migrated to the up-to-date non-deprecated state.
3535 // 3536 //
3536 // This method rewrites or completes the transition tree to reflect the new 3537 // This method rewrites or completes the transition tree to reflect the new
3537 // change. To avoid high degrees over polymorphism, and to stabilize quickly, 3538 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
3538 // on every rewrite the new type is deduced by merging the current type with 3539 // on every rewrite the new type is deduced by merging the current type with
3539 // any potential new (partial) version of the type in the transition tree. 3540 // any potential new (partial) version of the type in the transition tree.
3540 // To do this, on each rewrite: 3541 // To do this, on each rewrite:
3541 // - Search the root of the transition tree using FindRootMap. 3542 // - Search the root of the transition tree using FindRootMap.
3543 // - Find/create a |root_map| with requested |new_elements_kind|.
3542 // - Find |target_map|, the newest matching version of this map using the 3544 // - Find |target_map|, the newest matching version of this map using the
3543 // virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at 3545 // virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
3544 // |modify_index| is considered to be of |new_kind| and having 3546 // |modify_index| is considered to be of |new_kind| and having
3545 // |new_attributes|) to walk the transition tree. 3547 // |new_attributes|) to walk the transition tree.
3546 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and 3548 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
3547 // descriptor array of the |target_map|. 3549 // descriptor array of the |target_map|.
3548 // - Generalize the |modify_index| descriptor using |new_representation| and 3550 // - Generalize the |modify_index| descriptor using |new_representation| and
3549 // |new_field_type|. 3551 // |new_field_type|.
3550 // - Walk the tree again starting from the root towards |target_map|. Stop at 3552 // - Walk the tree again starting from the root towards |target_map|. Stop at
3551 // |split_map|, the first map who's descriptor array does not match the merged 3553 // |split_map|, the first map who's descriptor array does not match the merged
3552 // descriptor array. 3554 // descriptor array.
3553 // - If |target_map| == |split_map|, |target_map| is in the expected state. 3555 // - If |target_map| == |split_map|, |target_map| is in the expected state.
3554 // Return it. 3556 // Return it.
3555 // - Otherwise, invalidate the outdated transition target from |target_map|, and 3557 // - Otherwise, invalidate the outdated transition target from |target_map|, and
3556 // replace its transition tree with a new branch for the updated descriptors. 3558 // replace its transition tree with a new branch for the updated descriptors.
3557 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index, 3559 Handle<Map> Map::Reconfigure(Handle<Map> old_map,
3558 PropertyKind new_kind, 3560 ElementsKind new_elements_kind, int modify_index,
3559 PropertyAttributes new_attributes, 3561 PropertyKind new_kind,
3560 Representation new_representation, 3562 PropertyAttributes new_attributes,
3561 Handle<FieldType> new_field_type, 3563 Representation new_representation,
3562 StoreMode store_mode) { 3564 Handle<FieldType> new_field_type,
3565 StoreMode store_mode) {
3563 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet. 3566 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet.
3564 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0); 3567 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
3565 Isolate* isolate = old_map->GetIsolate(); 3568 Isolate* isolate = old_map->GetIsolate();
3566 3569
3567 Handle<DescriptorArray> old_descriptors( 3570 Handle<DescriptorArray> old_descriptors(
3568 old_map->instance_descriptors(), isolate); 3571 old_map->instance_descriptors(), isolate);
3569 int old_nof = old_map->NumberOfOwnDescriptors(); 3572 int old_nof = old_map->NumberOfOwnDescriptors();
3570 3573
3571 // If it's just a representation generalization case (i.e. property kind and 3574 // If it's just a representation generalization case (i.e. property kind and
3572 // attributes stays unchanged) it's fine to transition from None to anything 3575 // attributes stays unchanged) it's fine to transition from None to anything
3573 // but double without any modification to the object, because the default 3576 // but double without any modification to the object, because the default
3574 // uninitialized value for representation None can be overwritten by both 3577 // uninitialized value for representation None can be overwritten by both
3575 // smi and tagged values. Doubles, however, would require a box allocation. 3578 // smi and tagged values. Doubles, however, would require a box allocation.
3576 if (modify_index >= 0 && !new_representation.IsNone() && 3579 if (modify_index >= 0 && !new_representation.IsNone() &&
3577 !new_representation.IsDouble()) { 3580 !new_representation.IsDouble() &&
3581 old_map->elements_kind() == new_elements_kind) {
3578 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 3582 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3579 Representation old_representation = old_details.representation(); 3583 Representation old_representation = old_details.representation();
3580 3584
3581 if (old_representation.IsNone()) { 3585 if (old_representation.IsNone()) {
3582 DCHECK_EQ(new_kind, old_details.kind()); 3586 DCHECK_EQ(new_kind, old_details.kind());
3583 DCHECK_EQ(new_attributes, old_details.attributes()); 3587 DCHECK_EQ(new_attributes, old_details.attributes());
3584 DCHECK_EQ(DATA, old_details.type()); 3588 DCHECK_EQ(DATA, old_details.type());
3585 if (FLAG_trace_generalization) { 3589 if (FLAG_trace_generalization) {
3586 old_map->PrintGeneralization( 3590 old_map->PrintGeneralization(
3587 stdout, "uninitialized field", modify_index, 3591 stdout, "uninitialized field", modify_index,
(...skipping 12 matching lines...) Expand all
3600 .Equals(new_representation)); 3604 .Equals(new_representation));
3601 DCHECK( 3605 DCHECK(
3602 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type)); 3606 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
3603 return old_map; 3607 return old_map;
3604 } 3608 }
3605 } 3609 }
3606 3610
3607 // Check the state of the root map. 3611 // Check the state of the root map.
3608 Handle<Map> root_map(old_map->FindRootMap(), isolate); 3612 Handle<Map> root_map(old_map->FindRootMap(), isolate);
3609 if (!old_map->EquivalentToForTransition(*root_map)) { 3613 if (!old_map->EquivalentToForTransition(*root_map)) {
3610 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3614 return CopyGeneralizeAllRepresentations(
3611 new_kind, new_attributes, 3615 old_map, new_elements_kind, modify_index, store_mode, new_kind,
3612 "GenAll_NotEquivalent"); 3616 new_attributes, "GenAll_NotEquivalent");
3613 } 3617 }
3614 3618
3615 ElementsKind from_kind = root_map->elements_kind(); 3619 ElementsKind from_kind = root_map->elements_kind();
3616 ElementsKind to_kind = old_map->elements_kind(); 3620 ElementsKind to_kind = new_elements_kind;
3617 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS. 3621 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
3618 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS && 3622 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
3623 to_kind != SLOW_STRING_WRAPPER_ELEMENTS &&
3619 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS && 3624 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
3620 !(IsTransitionableFastElementsKind(from_kind) && 3625 !(IsTransitionableFastElementsKind(from_kind) &&
3621 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) { 3626 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
3622 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3627 return CopyGeneralizeAllRepresentations(
3623 new_kind, new_attributes, 3628 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3624 "GenAll_InvalidElementsTransition"); 3629 "GenAll_InvalidElementsTransition");
3625 } 3630 }
3626 int root_nof = root_map->NumberOfOwnDescriptors(); 3631 int root_nof = root_map->NumberOfOwnDescriptors();
3627 if (modify_index >= 0 && modify_index < root_nof) { 3632 if (modify_index >= 0 && modify_index < root_nof) {
3628 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 3633 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3629 if (old_details.kind() != new_kind || 3634 if (old_details.kind() != new_kind ||
3630 old_details.attributes() != new_attributes) { 3635 old_details.attributes() != new_attributes) {
3631 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3636 return CopyGeneralizeAllRepresentations(
3632 new_kind, new_attributes, 3637 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3633 "GenAll_RootModification1"); 3638 "GenAll_RootModification1");
3634 } 3639 }
3635 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) || 3640 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
3636 (old_details.type() == DATA && 3641 (old_details.type() == DATA &&
3637 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || 3642 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
3638 !new_representation.fits_into(old_details.representation())))) { 3643 !new_representation.fits_into(old_details.representation())))) {
3639 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3644 return CopyGeneralizeAllRepresentations(
3640 new_kind, new_attributes, 3645 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3641 "GenAll_RootModification2"); 3646 "GenAll_RootModification2");
3642 } 3647 }
3643 } 3648 }
3644 3649
3645 // From here on, use the map with correct elements kind as root map. 3650 // From here on, use the map with correct elements kind as root map.
3646 if (from_kind != to_kind) { 3651 if (from_kind != to_kind) {
3647 root_map = Map::AsElementsKind(root_map, to_kind); 3652 root_map = Map::AsElementsKind(root_map, to_kind);
3648 } 3653 }
3649 3654
3650 Handle<Map> target_map = root_map; 3655 Handle<Map> target_map = root_map;
3651 for (int i = root_nof; i < old_nof; ++i) { 3656 for (int i = root_nof; i < old_nof; ++i) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3685 Handle<DescriptorArray> tmp_descriptors = handle( 3690 Handle<DescriptorArray> tmp_descriptors = handle(
3686 tmp_map->instance_descriptors(), isolate); 3691 tmp_map->instance_descriptors(), isolate);
3687 3692
3688 // Check if target map is incompatible. 3693 // Check if target map is incompatible.
3689 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); 3694 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3690 DCHECK_EQ(next_kind, tmp_details.kind()); 3695 DCHECK_EQ(next_kind, tmp_details.kind());
3691 DCHECK_EQ(next_attributes, tmp_details.attributes()); 3696 DCHECK_EQ(next_attributes, tmp_details.attributes());
3692 if (next_kind == kAccessor && 3697 if (next_kind == kAccessor &&
3693 !EqualImmutableValues(old_descriptors->GetValue(i), 3698 !EqualImmutableValues(old_descriptors->GetValue(i),
3694 tmp_descriptors->GetValue(i))) { 3699 tmp_descriptors->GetValue(i))) {
3695 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3700 return CopyGeneralizeAllRepresentations(
3696 new_kind, new_attributes, 3701 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3697 "GenAll_Incompatible"); 3702 "GenAll_Incompatible");
3698 } 3703 }
3699 if (next_location == kField && tmp_details.location() == kDescriptor) break; 3704 if (next_location == kField && tmp_details.location() == kDescriptor) break;
3700 3705
3701 Representation tmp_representation = tmp_details.representation(); 3706 Representation tmp_representation = tmp_details.representation();
3702 if (!next_representation.fits_into(tmp_representation)) break; 3707 if (!next_representation.fits_into(tmp_representation)) break;
3703 3708
3704 PropertyLocation old_location = old_details.location(); 3709 PropertyLocation old_location = old_details.location();
3705 PropertyLocation tmp_location = tmp_details.location(); 3710 PropertyLocation tmp_location = tmp_details.location();
3706 if (tmp_location == kField) { 3711 if (tmp_location == kField) {
3707 if (next_kind == kData) { 3712 if (next_kind == kData) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
3780 3785
3781 // Check if target map is compatible. 3786 // Check if target map is compatible.
3782 #ifdef DEBUG 3787 #ifdef DEBUG
3783 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); 3788 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3784 DCHECK_EQ(next_kind, tmp_details.kind()); 3789 DCHECK_EQ(next_kind, tmp_details.kind());
3785 DCHECK_EQ(next_attributes, tmp_details.attributes()); 3790 DCHECK_EQ(next_attributes, tmp_details.attributes());
3786 #endif 3791 #endif
3787 if (next_kind == kAccessor && 3792 if (next_kind == kAccessor &&
3788 !EqualImmutableValues(old_descriptors->GetValue(i), 3793 !EqualImmutableValues(old_descriptors->GetValue(i),
3789 tmp_descriptors->GetValue(i))) { 3794 tmp_descriptors->GetValue(i))) {
3790 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3795 return CopyGeneralizeAllRepresentations(
3791 new_kind, new_attributes, 3796 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3792 "GenAll_Incompatible"); 3797 "GenAll_Incompatible");
3793 } 3798 }
3794 DCHECK(!tmp_map->is_deprecated()); 3799 DCHECK(!tmp_map->is_deprecated());
3795 target_map = tmp_map; 3800 target_map = tmp_map;
3796 } 3801 }
3797 target_nof = target_map->NumberOfOwnDescriptors(); 3802 target_nof = target_map->NumberOfOwnDescriptors();
3798 target_descriptors = handle(target_map->instance_descriptors(), isolate); 3803 target_descriptors = handle(target_map->instance_descriptors(), isolate);
3799 3804
3800 // Allocate a new descriptor array large enough to hold the required 3805 // Allocate a new descriptor array large enough to hold the required
3801 // descriptors, with minimally the exact same size as the old descriptor 3806 // descriptors, with minimally the exact same size as the old descriptor
3802 // array. 3807 // array.
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
4013 split_attributes); 4018 split_attributes);
4014 if (maybe_transition != NULL) { 4019 if (maybe_transition != NULL) {
4015 maybe_transition->DeprecateTransitionTree(); 4020 maybe_transition->DeprecateTransitionTree();
4016 } 4021 }
4017 4022
4018 // If |maybe_transition| is not NULL then the transition array already 4023 // If |maybe_transition| is not NULL then the transition array already
4019 // contains entry for given descriptor. This means that the transition 4024 // contains entry for given descriptor. This means that the transition
4020 // could be inserted regardless of whether transitions array is full or not. 4025 // could be inserted regardless of whether transitions array is full or not.
4021 if (maybe_transition == NULL && 4026 if (maybe_transition == NULL &&
4022 !TransitionArray::CanHaveMoreTransitions(split_map)) { 4027 !TransitionArray::CanHaveMoreTransitions(split_map)) {
4023 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 4028 return CopyGeneralizeAllRepresentations(
4024 new_kind, new_attributes, 4029 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
4025 "GenAll_CantHaveMoreTransitions"); 4030 "GenAll_CantHaveMoreTransitions");
4026 } 4031 }
4027 4032
4028 old_map->NotifyLeafMapLayoutChange(); 4033 old_map->NotifyLeafMapLayoutChange();
4029 4034
4030 if (FLAG_trace_generalization && modify_index >= 0) { 4035 if (FLAG_trace_generalization && modify_index >= 0) {
4031 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 4036 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
4032 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); 4037 PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
4033 MaybeHandle<FieldType> old_field_type; 4038 MaybeHandle<FieldType> old_field_type;
4034 MaybeHandle<FieldType> new_field_type; 4039 MaybeHandle<FieldType> new_field_type;
4035 MaybeHandle<Object> old_value; 4040 MaybeHandle<Object> old_value;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
4096 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>(); 4101 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
4097 4102
4098 ElementsKind from_kind = root_map->elements_kind(); 4103 ElementsKind from_kind = root_map->elements_kind();
4099 ElementsKind to_kind = old_map->elements_kind(); 4104 ElementsKind to_kind = old_map->elements_kind();
4100 if (from_kind != to_kind) { 4105 if (from_kind != to_kind) {
4101 // Try to follow existing elements kind transitions. 4106 // Try to follow existing elements kind transitions.
4102 root_map = root_map->LookupElementsTransitionMap(to_kind); 4107 root_map = root_map->LookupElementsTransitionMap(to_kind);
4103 if (root_map == NULL) return MaybeHandle<Map>(); 4108 if (root_map == NULL) return MaybeHandle<Map>();
4104 // From here on, use the map with correct elements kind as root map. 4109 // From here on, use the map with correct elements kind as root map.
4105 } 4110 }
4106 int root_nof = root_map->NumberOfOwnDescriptors(); 4111 Map* new_map = root_map->TryReplayPropertyTransitions(*old_map);
4112 if (new_map == nullptr) return MaybeHandle<Map>();
4113 return handle(new_map);
4114 }
4115
4116 Map* Map::TryReplayPropertyTransitions(Map* old_map) {
4117 DisallowHeapAllocation no_allocation;
4118 DisallowDeoptimization no_deoptimization(GetIsolate());
4119
4120 int root_nof = NumberOfOwnDescriptors();
4107 4121
4108 int old_nof = old_map->NumberOfOwnDescriptors(); 4122 int old_nof = old_map->NumberOfOwnDescriptors();
4109 DescriptorArray* old_descriptors = old_map->instance_descriptors(); 4123 DescriptorArray* old_descriptors = old_map->instance_descriptors();
4110 4124
4111 Map* new_map = root_map; 4125 Map* new_map = this;
4112 for (int i = root_nof; i < old_nof; ++i) { 4126 for (int i = root_nof; i < old_nof; ++i) {
4113 PropertyDetails old_details = old_descriptors->GetDetails(i); 4127 PropertyDetails old_details = old_descriptors->GetDetails(i);
4114 Map* transition = TransitionArray::SearchTransition( 4128 Map* transition = TransitionArray::SearchTransition(
4115 new_map, old_details.kind(), old_descriptors->GetKey(i), 4129 new_map, old_details.kind(), old_descriptors->GetKey(i),
4116 old_details.attributes()); 4130 old_details.attributes());
4117 if (transition == NULL) return MaybeHandle<Map>(); 4131 if (transition == NULL) return nullptr;
4118 new_map = transition; 4132 new_map = transition;
4119 DescriptorArray* new_descriptors = new_map->instance_descriptors(); 4133 DescriptorArray* new_descriptors = new_map->instance_descriptors();
4120 4134
4121 PropertyDetails new_details = new_descriptors->GetDetails(i); 4135 PropertyDetails new_details = new_descriptors->GetDetails(i);
4122 DCHECK_EQ(old_details.kind(), new_details.kind()); 4136 DCHECK_EQ(old_details.kind(), new_details.kind());
4123 DCHECK_EQ(old_details.attributes(), new_details.attributes()); 4137 DCHECK_EQ(old_details.attributes(), new_details.attributes());
4124 if (!old_details.representation().fits_into(new_details.representation())) { 4138 if (!old_details.representation().fits_into(new_details.representation())) {
4125 return MaybeHandle<Map>(); 4139 return nullptr;
4126 } 4140 }
4127 switch (new_details.type()) { 4141 switch (new_details.type()) {
4128 case DATA: { 4142 case DATA: {
4129 FieldType* new_type = new_descriptors->GetFieldType(i); 4143 FieldType* new_type = new_descriptors->GetFieldType(i);
4130 // Cleared field types need special treatment. They represent lost 4144 // Cleared field types need special treatment. They represent lost
4131 // knowledge, so we must first generalize the new_type to "Any". 4145 // knowledge, so we must first generalize the new_type to "Any".
4132 if (FieldTypeIsCleared(new_details.representation(), new_type)) { 4146 if (FieldTypeIsCleared(new_details.representation(), new_type)) {
4133 return MaybeHandle<Map>(); 4147 return nullptr;
4134 } 4148 }
4135 PropertyType old_property_type = old_details.type(); 4149 PropertyType old_property_type = old_details.type();
4136 if (old_property_type == DATA) { 4150 if (old_property_type == DATA) {
4137 FieldType* old_type = old_descriptors->GetFieldType(i); 4151 FieldType* old_type = old_descriptors->GetFieldType(i);
4138 if (FieldTypeIsCleared(old_details.representation(), old_type) || 4152 if (FieldTypeIsCleared(old_details.representation(), old_type) ||
4139 !old_type->NowIs(new_type)) { 4153 !old_type->NowIs(new_type)) {
4140 return MaybeHandle<Map>(); 4154 return nullptr;
4141 } 4155 }
4142 } else { 4156 } else {
4143 DCHECK(old_property_type == DATA_CONSTANT); 4157 DCHECK(old_property_type == DATA_CONSTANT);
4144 Object* old_value = old_descriptors->GetValue(i); 4158 Object* old_value = old_descriptors->GetValue(i);
4145 if (!new_type->NowContains(old_value)) { 4159 if (!new_type->NowContains(old_value)) {
4146 return MaybeHandle<Map>(); 4160 return nullptr;
4147 } 4161 }
4148 } 4162 }
4149 break; 4163 break;
4150 } 4164 }
4151 case ACCESSOR: { 4165 case ACCESSOR: {
4152 #ifdef DEBUG 4166 #ifdef DEBUG
4153 FieldType* new_type = new_descriptors->GetFieldType(i); 4167 FieldType* new_type = new_descriptors->GetFieldType(i);
4154 DCHECK(new_type->IsAny()); 4168 DCHECK(new_type->IsAny());
4155 #endif 4169 #endif
4156 break; 4170 break;
4157 } 4171 }
4158 4172
4159 case DATA_CONSTANT: 4173 case DATA_CONSTANT:
4160 case ACCESSOR_CONSTANT: { 4174 case ACCESSOR_CONSTANT: {
4161 Object* old_value = old_descriptors->GetValue(i); 4175 Object* old_value = old_descriptors->GetValue(i);
4162 Object* new_value = new_descriptors->GetValue(i); 4176 Object* new_value = new_descriptors->GetValue(i);
4163 if (old_details.location() == kField || old_value != new_value) { 4177 if (old_details.location() == kField || old_value != new_value) {
4164 return MaybeHandle<Map>(); 4178 return nullptr;
4165 } 4179 }
4166 break; 4180 break;
4167 } 4181 }
4168 } 4182 }
4169 } 4183 }
4170 if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>(); 4184 if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr;
4171 return handle(new_map); 4185 return new_map;
4172 } 4186 }
4173 4187
4174 4188
4175 // static 4189 // static
4176 Handle<Map> Map::Update(Handle<Map> map) { 4190 Handle<Map> Map::Update(Handle<Map> map) {
4177 if (!map->is_deprecated()) return map; 4191 if (!map->is_deprecated()) return map;
4178 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), 4192 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
4179 FieldType::None(map->GetIsolate()), 4193 FieldType::None(map->GetIsolate()),
4180 ALLOW_IN_DESCRIPTOR); 4194 ALLOW_IN_DESCRIPTOR);
4181 } 4195 }
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
4754 4768
4755 4769
4756 static bool ContainsMap(MapHandleList* maps, Map* map) { 4770 static bool ContainsMap(MapHandleList* maps, Map* map) {
4757 DCHECK_NOT_NULL(map); 4771 DCHECK_NOT_NULL(map);
4758 for (int i = 0; i < maps->length(); ++i) { 4772 for (int i = 0; i < maps->length(); ++i) {
4759 if (!maps->at(i).is_null() && *maps->at(i) == map) return true; 4773 if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
4760 } 4774 }
4761 return false; 4775 return false;
4762 } 4776 }
4763 4777
4778 Map* Map::FindElementsKindTransitionedMap(MapHandleList* candidates) {
4779 DisallowHeapAllocation no_allocation;
4780 DisallowDeoptimization no_deoptimization(GetIsolate());
4764 4781
4765 Handle<Map> Map::FindTransitionedMap(Handle<Map> map, 4782 ElementsKind kind = elements_kind();
4766 MapHandleList* candidates) {
4767 ElementsKind kind = map->elements_kind();
4768 bool packed = IsFastPackedElementsKind(kind); 4783 bool packed = IsFastPackedElementsKind(kind);
4769 4784
4770 Map* transition = nullptr; 4785 Map* transition = nullptr;
4771 if (IsTransitionableFastElementsKind(kind)) { 4786 if (IsTransitionableFastElementsKind(kind)) {
4772 for (Map* current = map->ElementsTransitionMap(); 4787 // Check the state of the root map.
4773 current != nullptr && current->has_fast_elements(); 4788 Map* root_map = FindRootMap();
4774 current = current->ElementsTransitionMap()) { 4789 if (!EquivalentToForTransition(root_map)) return nullptr;
4790 root_map = root_map->LookupElementsTransitionMap(kind);
4791 DCHECK_NOT_NULL(root_map);
4792 // Starting from the next existing elements kind transition try to
4793 // replay the property transitions.
4794 for (root_map = root_map->ElementsTransitionMap();
4795 root_map != nullptr && root_map->has_fast_elements();
4796 root_map = root_map->ElementsTransitionMap()) {
4797 Map* current = root_map->TryReplayPropertyTransitions(this);
4798 if (current == nullptr) continue;
4799
4775 if (ContainsMap(candidates, current) && 4800 if (ContainsMap(candidates, current) &&
4776 (packed || !IsFastPackedElementsKind(current->elements_kind()))) { 4801 (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
4777 transition = current; 4802 transition = current;
4778 packed = packed && IsFastPackedElementsKind(current->elements_kind()); 4803 packed = packed && IsFastPackedElementsKind(current->elements_kind());
4779 } 4804 }
4780 } 4805 }
4781 } 4806 }
4782 return transition == nullptr ? Handle<Map>() : handle(transition); 4807 return transition;
4783 } 4808 }
4784 4809
4785 4810
4786 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { 4811 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
4812 // Ensure we are requested to search elements kind transition "near the root".
4813 DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
4814 map->NumberOfOwnDescriptors());
4787 Map* current_map = map; 4815 Map* current_map = map;
4788 4816
4789 ElementsKind kind = map->elements_kind(); 4817 ElementsKind kind = map->elements_kind();
4790 while (kind != to_kind) { 4818 while (kind != to_kind) {
4791 Map* next_map = current_map->ElementsTransitionMap(); 4819 Map* next_map = current_map->ElementsTransitionMap();
4792 if (next_map == nullptr) return current_map; 4820 if (next_map == nullptr) return current_map;
4793 kind = next_map->elements_kind(); 4821 kind = next_map->elements_kind();
4794 current_map = next_map; 4822 current_map = next_map;
4795 } 4823 }
4796 4824
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
4905 if (IsFastElementsKind(to_kind)) { 4933 if (IsFastElementsKind(to_kind)) {
4906 allow_store_transition = 4934 allow_store_transition =
4907 allow_store_transition && IsTransitionableFastElementsKind(from_kind) && 4935 allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
4908 IsMoreGeneralElementsKindTransition(from_kind, to_kind); 4936 IsMoreGeneralElementsKindTransition(from_kind, to_kind);
4909 } 4937 }
4910 4938
4911 if (!allow_store_transition) { 4939 if (!allow_store_transition) {
4912 return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION); 4940 return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
4913 } 4941 }
4914 4942
4915 return Map::AsElementsKind(map, to_kind); 4943 return Map::ReconfigureElementsKind(map, to_kind);
4916 } 4944 }
4917 4945
4918 4946
4919 // static 4947 // static
4920 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) { 4948 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
4921 Handle<Map> closest_map(FindClosestElementsTransition(*map, kind)); 4949 Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
4922 4950
4923 if (closest_map->elements_kind() == kind) { 4951 if (closest_map->elements_kind() == kind) {
4924 return closest_map; 4952 return closest_map;
4925 } 4953 }
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
5267 if (map_kind != obj_kind) { 5295 if (map_kind != obj_kind) {
5268 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind); 5296 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
5269 if (IsDictionaryElementsKind(obj_kind)) { 5297 if (IsDictionaryElementsKind(obj_kind)) {
5270 to_kind = obj_kind; 5298 to_kind = obj_kind;
5271 } 5299 }
5272 if (IsDictionaryElementsKind(to_kind)) { 5300 if (IsDictionaryElementsKind(to_kind)) {
5273 NormalizeElements(object); 5301 NormalizeElements(object);
5274 } else { 5302 } else {
5275 TransitionElementsKind(object, to_kind); 5303 TransitionElementsKind(object, to_kind);
5276 } 5304 }
5277 map = Map::AsElementsKind(map, to_kind); 5305 map = Map::ReconfigureElementsKind(map, to_kind);
5278 } 5306 }
5279 JSObject::MigrateToMap(object, map); 5307 JSObject::MigrateToMap(object, map);
5280 } 5308 }
5281 5309
5282 5310
5283 void JSObject::MigrateInstance(Handle<JSObject> object) { 5311 void JSObject::MigrateInstance(Handle<JSObject> object) {
5284 Handle<Map> original_map(object->map()); 5312 Handle<Map> original_map(object->map());
5285 Handle<Map> map = Map::Update(original_map); 5313 Handle<Map> map = Map::Update(original_map);
5286 map->set_migration_target(true); 5314 map->set_migration_target(true);
5287 MigrateToMap(object, map); 5315 MigrateToMap(object, map);
(...skipping 3562 matching lines...) Expand 10 before | Expand all | Expand 10 after
8850 8878
8851 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); 8879 Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
8852 ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION); 8880 ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION);
8853 } 8881 }
8854 8882
8855 8883
8856 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, 8884 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
8857 TransitionFlag flag) { 8885 TransitionFlag flag) {
8858 Map* maybe_elements_transition_map = NULL; 8886 Map* maybe_elements_transition_map = NULL;
8859 if (flag == INSERT_TRANSITION) { 8887 if (flag == INSERT_TRANSITION) {
8888 // Ensure we are requested to add elements kind transition "near the root".
8889 DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
8890 map->NumberOfOwnDescriptors());
8891
8860 maybe_elements_transition_map = map->ElementsTransitionMap(); 8892 maybe_elements_transition_map = map->ElementsTransitionMap();
8861 DCHECK(maybe_elements_transition_map == NULL || 8893 DCHECK(maybe_elements_transition_map == NULL ||
8862 (maybe_elements_transition_map->elements_kind() == 8894 (maybe_elements_transition_map->elements_kind() ==
8863 DICTIONARY_ELEMENTS && 8895 DICTIONARY_ELEMENTS &&
8864 kind == DICTIONARY_ELEMENTS)); 8896 kind == DICTIONARY_ELEMENTS));
8865 DCHECK(!IsFastElementsKind(kind) || 8897 DCHECK(!IsFastElementsKind(kind) ||
8866 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); 8898 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
8867 DCHECK(kind != map->elements_kind()); 8899 DCHECK(kind != map->elements_kind());
8868 } 8900 }
8869 8901
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
9154 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor, 9186 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
9155 PropertyKind kind, 9187 PropertyKind kind,
9156 PropertyAttributes attributes) { 9188 PropertyAttributes attributes) {
9157 // Dictionaries have to be reconfigured in-place. 9189 // Dictionaries have to be reconfigured in-place.
9158 DCHECK(!map->is_dictionary_map()); 9190 DCHECK(!map->is_dictionary_map());
9159 9191
9160 if (!map->GetBackPointer()->IsMap()) { 9192 if (!map->GetBackPointer()->IsMap()) {
9161 // There is no benefit from reconstructing transition tree for maps without 9193 // There is no benefit from reconstructing transition tree for maps without
9162 // back pointers. 9194 // back pointers.
9163 return CopyGeneralizeAllRepresentations( 9195 return CopyGeneralizeAllRepresentations(
9164 map, descriptor, FORCE_FIELD, kind, attributes, 9196 map, map->elements_kind(), descriptor, FORCE_FIELD, kind, attributes,
9165 "GenAll_AttributesMismatchProtoMap"); 9197 "GenAll_AttributesMismatchProtoMap");
9166 } 9198 }
9167 9199
9168 if (FLAG_trace_generalization) { 9200 if (FLAG_trace_generalization) {
9169 map->PrintReconfiguration(stdout, descriptor, kind, attributes); 9201 map->PrintReconfiguration(stdout, descriptor, kind, attributes);
9170 } 9202 }
9171 9203
9172 Isolate* isolate = map->GetIsolate(); 9204 Isolate* isolate = map->GetIsolate();
9173 Handle<Map> new_map = ReconfigureProperty( 9205 Handle<Map> new_map = ReconfigureProperty(
9174 map, descriptor, kind, attributes, Representation::None(), 9206 map, descriptor, kind, attributes, Representation::None(),
(...skipping 9290 matching lines...) Expand 10 before | Expand all | Expand 10 after
18465 if (cell->value() != *new_value) { 18497 if (cell->value() != *new_value) {
18466 cell->set_value(*new_value); 18498 cell->set_value(*new_value);
18467 Isolate* isolate = cell->GetIsolate(); 18499 Isolate* isolate = cell->GetIsolate();
18468 cell->dependent_code()->DeoptimizeDependentCodeGroup( 18500 cell->dependent_code()->DeoptimizeDependentCodeGroup(
18469 isolate, DependentCode::kPropertyCellChangedGroup); 18501 isolate, DependentCode::kPropertyCellChangedGroup);
18470 } 18502 }
18471 } 18503 }
18472 18504
18473 } // namespace internal 18505 } // namespace internal
18474 } // namespace v8 18506 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698