OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |