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

Side by Side Diff: src/objects.cc

Issue 2062783002: Version 5.2.361.22 (cherry-pick) (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@5.2
Patch Set: 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 2734 matching lines...) Expand 10 before | Expand all | Expand 10 after
2745 case kDouble: return "d"; 2745 case kDouble: return "d";
2746 case kInteger32: return "i"; 2746 case kInteger32: return "i";
2747 case kHeapObject: return "h"; 2747 case kHeapObject: return "h";
2748 case kExternal: return "x"; 2748 case kExternal: return "x";
2749 default: 2749 default:
2750 UNREACHABLE(); 2750 UNREACHABLE();
2751 return NULL; 2751 return NULL;
2752 } 2752 }
2753 } 2753 }
2754 2754
2755 bool Map::InstancesNeedRewriting(Map* target) {
2756 int target_number_of_fields = target->NumberOfFields();
2757 int target_inobject = target->GetInObjectProperties();
2758 int target_unused = target->unused_property_fields();
2759 int old_number_of_fields;
2760
2761 return InstancesNeedRewriting(target, target_number_of_fields,
2762 target_inobject, target_unused,
2763 &old_number_of_fields);
2764 }
2755 2765
2756 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields, 2766 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
2757 int target_inobject, int target_unused, 2767 int target_inobject, int target_unused,
2758 int* old_number_of_fields) { 2768 int* old_number_of_fields) {
2759 // If fields were added (or removed), rewrite the instance. 2769 // If fields were added (or removed), rewrite the instance.
2760 *old_number_of_fields = NumberOfFields(); 2770 *old_number_of_fields = NumberOfFields();
2761 DCHECK(target_number_of_fields >= *old_number_of_fields); 2771 DCHECK(target_number_of_fields >= *old_number_of_fields);
2762 if (target_number_of_fields != *old_number_of_fields) return true; 2772 if (target_number_of_fields != *old_number_of_fields) return true;
2763 2773
2764 // If smi descriptors were replaced by double descriptors, rewrite. 2774 // If smi descriptors were replaced by double descriptors, rewrite.
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
3205 3215
3206 int Map::NumberOfFields() { 3216 int Map::NumberOfFields() {
3207 DescriptorArray* descriptors = instance_descriptors(); 3217 DescriptorArray* descriptors = instance_descriptors();
3208 int result = 0; 3218 int result = 0;
3209 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { 3219 for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
3210 if (descriptors->GetDetails(i).location() == kField) result++; 3220 if (descriptors->GetDetails(i).location() == kField) result++;
3211 } 3221 }
3212 return result; 3222 return result;
3213 } 3223 }
3214 3224
3215
3216 Handle<Map> Map::CopyGeneralizeAllRepresentations( 3225 Handle<Map> Map::CopyGeneralizeAllRepresentations(
3217 Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind, 3226 Handle<Map> map, ElementsKind elements_kind, int modify_index,
3218 PropertyAttributes attributes, const char* reason) { 3227 StoreMode store_mode, PropertyKind kind, PropertyAttributes attributes,
3228 const char* reason) {
3219 Isolate* isolate = map->GetIsolate(); 3229 Isolate* isolate = map->GetIsolate();
3220 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); 3230 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
3221 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 3231 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
3222 Handle<DescriptorArray> descriptors = 3232 Handle<DescriptorArray> descriptors =
3223 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors); 3233 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
3224 3234
3225 for (int i = 0; i < number_of_own_descriptors; i++) { 3235 for (int i = 0; i < number_of_own_descriptors; i++) {
3226 descriptors->SetRepresentation(i, Representation::Tagged()); 3236 descriptors->SetRepresentation(i, Representation::Tagged());
3227 if (descriptors->GetDetails(i).type() == DATA) { 3237 if (descriptors->GetDetails(i).type() == DATA) {
3228 descriptors->SetValue(i, FieldType::Any()); 3238 descriptors->SetValue(i, FieldType::Any());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3264 } 3274 }
3265 map->PrintGeneralization( 3275 map->PrintGeneralization(
3266 stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(), 3276 stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
3267 new_map->NumberOfOwnDescriptors(), 3277 new_map->NumberOfOwnDescriptors(),
3268 details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD, 3278 details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
3269 details.representation(), Representation::Tagged(), field_type, 3279 details.representation(), Representation::Tagged(), field_type,
3270 MaybeHandle<Object>(), FieldType::Any(isolate), 3280 MaybeHandle<Object>(), FieldType::Any(isolate),
3271 MaybeHandle<Object>()); 3281 MaybeHandle<Object>());
3272 } 3282 }
3273 } 3283 }
3284 new_map->set_elements_kind(elements_kind);
3274 return new_map; 3285 return new_map;
3275 } 3286 }
3276 3287
3277 3288
3278 void Map::DeprecateTransitionTree() { 3289 void Map::DeprecateTransitionTree() {
3279 if (is_deprecated()) return; 3290 if (is_deprecated()) return;
3280 Object* transitions = raw_transitions(); 3291 Object* transitions = raw_transitions();
3281 int num_transitions = TransitionArray::NumberOfTransitions(transitions); 3292 int num_transitions = TransitionArray::NumberOfTransitions(transitions);
3282 for (int i = 0; i < num_transitions; ++i) { 3293 for (int i = 0; i < num_transitions; ++i) {
3283 TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree(); 3294 TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
3516 DCHECK_EQ(details.location(), location); 3527 DCHECK_EQ(details.location(), location);
3517 #endif 3528 #endif
3518 if (location == kField) { 3529 if (location == kField) {
3519 return handle(descriptors->GetFieldType(descriptor), isolate); 3530 return handle(descriptors->GetFieldType(descriptor), isolate);
3520 } else { 3531 } else {
3521 return descriptors->GetValue(descriptor) 3532 return descriptors->GetValue(descriptor)
3522 ->OptimalType(isolate, representation); 3533 ->OptimalType(isolate, representation);
3523 } 3534 }
3524 } 3535 }
3525 3536
3526 3537 // Reconfigures elements kind to |new_elements_kind| and/or property at
3527 // Reconfigures property at |modify_index| with |new_kind|, |new_attributes|, 3538 // |modify_index| with |new_kind|, |new_attributes|, |store_mode| and/or
3528 // |store_mode| and/or |new_representation|/|new_field_type|. 3539 // |new_representation|/|new_field_type|.
3529 // If |modify_index| is negative then no properties are reconfigured but the 3540 // If |modify_index| is negative then no properties are reconfigured but the
3530 // map is migrated to the up-to-date non-deprecated state. 3541 // map is migrated to the up-to-date non-deprecated state.
3531 // 3542 //
3532 // This method rewrites or completes the transition tree to reflect the new 3543 // This method rewrites or completes the transition tree to reflect the new
3533 // change. To avoid high degrees over polymorphism, and to stabilize quickly, 3544 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
3534 // on every rewrite the new type is deduced by merging the current type with 3545 // on every rewrite the new type is deduced by merging the current type with
3535 // any potential new (partial) version of the type in the transition tree. 3546 // any potential new (partial) version of the type in the transition tree.
3536 // To do this, on each rewrite: 3547 // To do this, on each rewrite:
3537 // - Search the root of the transition tree using FindRootMap. 3548 // - Search the root of the transition tree using FindRootMap.
3549 // - Find/create a |root_map| with requested |new_elements_kind|.
3538 // - Find |target_map|, the newest matching version of this map using the 3550 // - Find |target_map|, the newest matching version of this map using the
3539 // virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at 3551 // virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
3540 // |modify_index| is considered to be of |new_kind| and having 3552 // |modify_index| is considered to be of |new_kind| and having
3541 // |new_attributes|) to walk the transition tree. 3553 // |new_attributes|) to walk the transition tree.
3542 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and 3554 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
3543 // descriptor array of the |target_map|. 3555 // descriptor array of the |target_map|.
3544 // - Generalize the |modify_index| descriptor using |new_representation| and 3556 // - Generalize the |modify_index| descriptor using |new_representation| and
3545 // |new_field_type|. 3557 // |new_field_type|.
3546 // - Walk the tree again starting from the root towards |target_map|. Stop at 3558 // - Walk the tree again starting from the root towards |target_map|. Stop at
3547 // |split_map|, the first map who's descriptor array does not match the merged 3559 // |split_map|, the first map who's descriptor array does not match the merged
3548 // descriptor array. 3560 // descriptor array.
3549 // - If |target_map| == |split_map|, |target_map| is in the expected state. 3561 // - If |target_map| == |split_map|, |target_map| is in the expected state.
3550 // Return it. 3562 // Return it.
3551 // - Otherwise, invalidate the outdated transition target from |target_map|, and 3563 // - Otherwise, invalidate the outdated transition target from |target_map|, and
3552 // replace its transition tree with a new branch for the updated descriptors. 3564 // replace its transition tree with a new branch for the updated descriptors.
3553 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index, 3565 Handle<Map> Map::Reconfigure(Handle<Map> old_map,
3554 PropertyKind new_kind, 3566 ElementsKind new_elements_kind, int modify_index,
3555 PropertyAttributes new_attributes, 3567 PropertyKind new_kind,
3556 Representation new_representation, 3568 PropertyAttributes new_attributes,
3557 Handle<FieldType> new_field_type, 3569 Representation new_representation,
3558 StoreMode store_mode) { 3570 Handle<FieldType> new_field_type,
3571 StoreMode store_mode) {
3559 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet. 3572 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet.
3560 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0); 3573 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
3561 Isolate* isolate = old_map->GetIsolate(); 3574 Isolate* isolate = old_map->GetIsolate();
3562 3575
3563 Handle<DescriptorArray> old_descriptors( 3576 Handle<DescriptorArray> old_descriptors(
3564 old_map->instance_descriptors(), isolate); 3577 old_map->instance_descriptors(), isolate);
3565 int old_nof = old_map->NumberOfOwnDescriptors(); 3578 int old_nof = old_map->NumberOfOwnDescriptors();
3566 3579
3567 // If it's just a representation generalization case (i.e. property kind and 3580 // If it's just a representation generalization case (i.e. property kind and
3568 // attributes stays unchanged) it's fine to transition from None to anything 3581 // attributes stays unchanged) it's fine to transition from None to anything
3569 // but double without any modification to the object, because the default 3582 // but double without any modification to the object, because the default
3570 // uninitialized value for representation None can be overwritten by both 3583 // uninitialized value for representation None can be overwritten by both
3571 // smi and tagged values. Doubles, however, would require a box allocation. 3584 // smi and tagged values. Doubles, however, would require a box allocation.
3572 if (modify_index >= 0 && !new_representation.IsNone() && 3585 if (modify_index >= 0 && !new_representation.IsNone() &&
3573 !new_representation.IsDouble()) { 3586 !new_representation.IsDouble() &&
3587 old_map->elements_kind() == new_elements_kind) {
3574 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 3588 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3575 Representation old_representation = old_details.representation(); 3589 Representation old_representation = old_details.representation();
3576 3590
3577 if (old_representation.IsNone()) { 3591 if (old_representation.IsNone()) {
3578 DCHECK_EQ(new_kind, old_details.kind()); 3592 DCHECK_EQ(new_kind, old_details.kind());
3579 DCHECK_EQ(new_attributes, old_details.attributes()); 3593 DCHECK_EQ(new_attributes, old_details.attributes());
3580 DCHECK_EQ(DATA, old_details.type()); 3594 DCHECK_EQ(DATA, old_details.type());
3581 if (FLAG_trace_generalization) { 3595 if (FLAG_trace_generalization) {
3582 old_map->PrintGeneralization( 3596 old_map->PrintGeneralization(
3583 stdout, "uninitialized field", modify_index, 3597 stdout, "uninitialized field", modify_index,
(...skipping 12 matching lines...) Expand all
3596 .Equals(new_representation)); 3610 .Equals(new_representation));
3597 DCHECK( 3611 DCHECK(
3598 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type)); 3612 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
3599 return old_map; 3613 return old_map;
3600 } 3614 }
3601 } 3615 }
3602 3616
3603 // Check the state of the root map. 3617 // Check the state of the root map.
3604 Handle<Map> root_map(old_map->FindRootMap(), isolate); 3618 Handle<Map> root_map(old_map->FindRootMap(), isolate);
3605 if (!old_map->EquivalentToForTransition(*root_map)) { 3619 if (!old_map->EquivalentToForTransition(*root_map)) {
3606 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3620 return CopyGeneralizeAllRepresentations(
3607 new_kind, new_attributes, 3621 old_map, new_elements_kind, modify_index, store_mode, new_kind,
3608 "GenAll_NotEquivalent"); 3622 new_attributes, "GenAll_NotEquivalent");
3609 } 3623 }
3610 3624
3611 ElementsKind from_kind = root_map->elements_kind(); 3625 ElementsKind from_kind = root_map->elements_kind();
3612 ElementsKind to_kind = old_map->elements_kind(); 3626 ElementsKind to_kind = new_elements_kind;
3613 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS. 3627 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
3614 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS && 3628 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
3629 to_kind != SLOW_STRING_WRAPPER_ELEMENTS &&
3615 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS && 3630 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
3616 !(IsTransitionableFastElementsKind(from_kind) && 3631 !(IsTransitionableFastElementsKind(from_kind) &&
3617 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) { 3632 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
3618 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3633 return CopyGeneralizeAllRepresentations(
3619 new_kind, new_attributes, 3634 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3620 "GenAll_InvalidElementsTransition"); 3635 "GenAll_InvalidElementsTransition");
3621 } 3636 }
3622 int root_nof = root_map->NumberOfOwnDescriptors(); 3637 int root_nof = root_map->NumberOfOwnDescriptors();
3623 if (modify_index >= 0 && modify_index < root_nof) { 3638 if (modify_index >= 0 && modify_index < root_nof) {
3624 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 3639 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3625 if (old_details.kind() != new_kind || 3640 if (old_details.kind() != new_kind ||
3626 old_details.attributes() != new_attributes) { 3641 old_details.attributes() != new_attributes) {
3627 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3642 return CopyGeneralizeAllRepresentations(
3628 new_kind, new_attributes, 3643 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3629 "GenAll_RootModification1"); 3644 "GenAll_RootModification1");
3630 } 3645 }
3631 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) || 3646 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
3632 (old_details.type() == DATA && 3647 (old_details.type() == DATA &&
3633 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || 3648 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
3634 !new_representation.fits_into(old_details.representation())))) { 3649 !new_representation.fits_into(old_details.representation())))) {
3635 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3650 return CopyGeneralizeAllRepresentations(
3636 new_kind, new_attributes, 3651 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3637 "GenAll_RootModification2"); 3652 "GenAll_RootModification2");
3638 } 3653 }
3639 } 3654 }
3640 3655
3641 // From here on, use the map with correct elements kind as root map. 3656 // From here on, use the map with correct elements kind as root map.
3642 if (from_kind != to_kind) { 3657 if (from_kind != to_kind) {
3643 root_map = Map::AsElementsKind(root_map, to_kind); 3658 root_map = Map::AsElementsKind(root_map, to_kind);
3644 } 3659 }
3645 3660
3646 Handle<Map> target_map = root_map; 3661 Handle<Map> target_map = root_map;
3647 for (int i = root_nof; i < old_nof; ++i) { 3662 for (int i = root_nof; i < old_nof; ++i) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3681 Handle<DescriptorArray> tmp_descriptors = handle( 3696 Handle<DescriptorArray> tmp_descriptors = handle(
3682 tmp_map->instance_descriptors(), isolate); 3697 tmp_map->instance_descriptors(), isolate);
3683 3698
3684 // Check if target map is incompatible. 3699 // Check if target map is incompatible.
3685 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); 3700 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3686 DCHECK_EQ(next_kind, tmp_details.kind()); 3701 DCHECK_EQ(next_kind, tmp_details.kind());
3687 DCHECK_EQ(next_attributes, tmp_details.attributes()); 3702 DCHECK_EQ(next_attributes, tmp_details.attributes());
3688 if (next_kind == kAccessor && 3703 if (next_kind == kAccessor &&
3689 !EqualImmutableValues(old_descriptors->GetValue(i), 3704 !EqualImmutableValues(old_descriptors->GetValue(i),
3690 tmp_descriptors->GetValue(i))) { 3705 tmp_descriptors->GetValue(i))) {
3691 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3706 return CopyGeneralizeAllRepresentations(
3692 new_kind, new_attributes, 3707 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3693 "GenAll_Incompatible"); 3708 "GenAll_Incompatible");
3694 } 3709 }
3695 if (next_location == kField && tmp_details.location() == kDescriptor) break; 3710 if (next_location == kField && tmp_details.location() == kDescriptor) break;
3696 3711
3697 Representation tmp_representation = tmp_details.representation(); 3712 Representation tmp_representation = tmp_details.representation();
3698 if (!next_representation.fits_into(tmp_representation)) break; 3713 if (!next_representation.fits_into(tmp_representation)) break;
3699 3714
3700 PropertyLocation old_location = old_details.location(); 3715 PropertyLocation old_location = old_details.location();
3701 PropertyLocation tmp_location = tmp_details.location(); 3716 PropertyLocation tmp_location = tmp_details.location();
3702 if (tmp_location == kField) { 3717 if (tmp_location == kField) {
3703 if (next_kind == kData) { 3718 if (next_kind == kData) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
3776 3791
3777 // Check if target map is compatible. 3792 // Check if target map is compatible.
3778 #ifdef DEBUG 3793 #ifdef DEBUG
3779 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); 3794 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3780 DCHECK_EQ(next_kind, tmp_details.kind()); 3795 DCHECK_EQ(next_kind, tmp_details.kind());
3781 DCHECK_EQ(next_attributes, tmp_details.attributes()); 3796 DCHECK_EQ(next_attributes, tmp_details.attributes());
3782 #endif 3797 #endif
3783 if (next_kind == kAccessor && 3798 if (next_kind == kAccessor &&
3784 !EqualImmutableValues(old_descriptors->GetValue(i), 3799 !EqualImmutableValues(old_descriptors->GetValue(i),
3785 tmp_descriptors->GetValue(i))) { 3800 tmp_descriptors->GetValue(i))) {
3786 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3801 return CopyGeneralizeAllRepresentations(
3787 new_kind, new_attributes, 3802 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3788 "GenAll_Incompatible"); 3803 "GenAll_Incompatible");
3789 } 3804 }
3790 DCHECK(!tmp_map->is_deprecated()); 3805 DCHECK(!tmp_map->is_deprecated());
3791 target_map = tmp_map; 3806 target_map = tmp_map;
3792 } 3807 }
3793 target_nof = target_map->NumberOfOwnDescriptors(); 3808 target_nof = target_map->NumberOfOwnDescriptors();
3794 target_descriptors = handle(target_map->instance_descriptors(), isolate); 3809 target_descriptors = handle(target_map->instance_descriptors(), isolate);
3795 3810
3796 // Allocate a new descriptor array large enough to hold the required 3811 // Allocate a new descriptor array large enough to hold the required
3797 // descriptors, with minimally the exact same size as the old descriptor 3812 // descriptors, with minimally the exact same size as the old descriptor
3798 // array. 3813 // array.
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
4009 split_attributes); 4024 split_attributes);
4010 if (maybe_transition != NULL) { 4025 if (maybe_transition != NULL) {
4011 maybe_transition->DeprecateTransitionTree(); 4026 maybe_transition->DeprecateTransitionTree();
4012 } 4027 }
4013 4028
4014 // If |maybe_transition| is not NULL then the transition array already 4029 // If |maybe_transition| is not NULL then the transition array already
4015 // contains entry for given descriptor. This means that the transition 4030 // contains entry for given descriptor. This means that the transition
4016 // could be inserted regardless of whether transitions array is full or not. 4031 // could be inserted regardless of whether transitions array is full or not.
4017 if (maybe_transition == NULL && 4032 if (maybe_transition == NULL &&
4018 !TransitionArray::CanHaveMoreTransitions(split_map)) { 4033 !TransitionArray::CanHaveMoreTransitions(split_map)) {
4019 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 4034 return CopyGeneralizeAllRepresentations(
4020 new_kind, new_attributes, 4035 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
4021 "GenAll_CantHaveMoreTransitions"); 4036 "GenAll_CantHaveMoreTransitions");
4022 } 4037 }
4023 4038
4024 old_map->NotifyLeafMapLayoutChange(); 4039 old_map->NotifyLeafMapLayoutChange();
4025 4040
4026 if (FLAG_trace_generalization && modify_index >= 0) { 4041 if (FLAG_trace_generalization && modify_index >= 0) {
4027 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 4042 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
4028 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); 4043 PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
4029 MaybeHandle<FieldType> old_field_type; 4044 MaybeHandle<FieldType> old_field_type;
4030 MaybeHandle<FieldType> new_field_type; 4045 MaybeHandle<FieldType> new_field_type;
4031 MaybeHandle<Object> old_value; 4046 MaybeHandle<Object> old_value;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
4092 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>(); 4107 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
4093 4108
4094 ElementsKind from_kind = root_map->elements_kind(); 4109 ElementsKind from_kind = root_map->elements_kind();
4095 ElementsKind to_kind = old_map->elements_kind(); 4110 ElementsKind to_kind = old_map->elements_kind();
4096 if (from_kind != to_kind) { 4111 if (from_kind != to_kind) {
4097 // Try to follow existing elements kind transitions. 4112 // Try to follow existing elements kind transitions.
4098 root_map = root_map->LookupElementsTransitionMap(to_kind); 4113 root_map = root_map->LookupElementsTransitionMap(to_kind);
4099 if (root_map == NULL) return MaybeHandle<Map>(); 4114 if (root_map == NULL) return MaybeHandle<Map>();
4100 // From here on, use the map with correct elements kind as root map. 4115 // From here on, use the map with correct elements kind as root map.
4101 } 4116 }
4102 int root_nof = root_map->NumberOfOwnDescriptors(); 4117 Map* new_map = root_map->TryReplayPropertyTransitions(*old_map);
4118 if (new_map == nullptr) return MaybeHandle<Map>();
4119 return handle(new_map);
4120 }
4121
4122 Map* Map::TryReplayPropertyTransitions(Map* old_map) {
4123 DisallowHeapAllocation no_allocation;
4124 DisallowDeoptimization no_deoptimization(GetIsolate());
4125
4126 int root_nof = NumberOfOwnDescriptors();
4103 4127
4104 int old_nof = old_map->NumberOfOwnDescriptors(); 4128 int old_nof = old_map->NumberOfOwnDescriptors();
4105 DescriptorArray* old_descriptors = old_map->instance_descriptors(); 4129 DescriptorArray* old_descriptors = old_map->instance_descriptors();
4106 4130
4107 Map* new_map = root_map; 4131 Map* new_map = this;
4108 for (int i = root_nof; i < old_nof; ++i) { 4132 for (int i = root_nof; i < old_nof; ++i) {
4109 PropertyDetails old_details = old_descriptors->GetDetails(i); 4133 PropertyDetails old_details = old_descriptors->GetDetails(i);
4110 Map* transition = TransitionArray::SearchTransition( 4134 Map* transition = TransitionArray::SearchTransition(
4111 new_map, old_details.kind(), old_descriptors->GetKey(i), 4135 new_map, old_details.kind(), old_descriptors->GetKey(i),
4112 old_details.attributes()); 4136 old_details.attributes());
4113 if (transition == NULL) return MaybeHandle<Map>(); 4137 if (transition == NULL) return nullptr;
4114 new_map = transition; 4138 new_map = transition;
4115 DescriptorArray* new_descriptors = new_map->instance_descriptors(); 4139 DescriptorArray* new_descriptors = new_map->instance_descriptors();
4116 4140
4117 PropertyDetails new_details = new_descriptors->GetDetails(i); 4141 PropertyDetails new_details = new_descriptors->GetDetails(i);
4118 DCHECK_EQ(old_details.kind(), new_details.kind()); 4142 DCHECK_EQ(old_details.kind(), new_details.kind());
4119 DCHECK_EQ(old_details.attributes(), new_details.attributes()); 4143 DCHECK_EQ(old_details.attributes(), new_details.attributes());
4120 if (!old_details.representation().fits_into(new_details.representation())) { 4144 if (!old_details.representation().fits_into(new_details.representation())) {
4121 return MaybeHandle<Map>(); 4145 return nullptr;
4122 } 4146 }
4123 switch (new_details.type()) { 4147 switch (new_details.type()) {
4124 case DATA: { 4148 case DATA: {
4125 FieldType* new_type = new_descriptors->GetFieldType(i); 4149 FieldType* new_type = new_descriptors->GetFieldType(i);
4126 // Cleared field types need special treatment. They represent lost 4150 // Cleared field types need special treatment. They represent lost
4127 // knowledge, so we must first generalize the new_type to "Any". 4151 // knowledge, so we must first generalize the new_type to "Any".
4128 if (FieldTypeIsCleared(new_details.representation(), new_type)) { 4152 if (FieldTypeIsCleared(new_details.representation(), new_type)) {
4129 return MaybeHandle<Map>(); 4153 return nullptr;
4130 } 4154 }
4131 PropertyType old_property_type = old_details.type(); 4155 PropertyType old_property_type = old_details.type();
4132 if (old_property_type == DATA) { 4156 if (old_property_type == DATA) {
4133 FieldType* old_type = old_descriptors->GetFieldType(i); 4157 FieldType* old_type = old_descriptors->GetFieldType(i);
4134 if (FieldTypeIsCleared(old_details.representation(), old_type) || 4158 if (FieldTypeIsCleared(old_details.representation(), old_type) ||
4135 !old_type->NowIs(new_type)) { 4159 !old_type->NowIs(new_type)) {
4136 return MaybeHandle<Map>(); 4160 return nullptr;
4137 } 4161 }
4138 } else { 4162 } else {
4139 DCHECK(old_property_type == DATA_CONSTANT); 4163 DCHECK(old_property_type == DATA_CONSTANT);
4140 Object* old_value = old_descriptors->GetValue(i); 4164 Object* old_value = old_descriptors->GetValue(i);
4141 if (!new_type->NowContains(old_value)) { 4165 if (!new_type->NowContains(old_value)) {
4142 return MaybeHandle<Map>(); 4166 return nullptr;
4143 } 4167 }
4144 } 4168 }
4145 break; 4169 break;
4146 } 4170 }
4147 case ACCESSOR: { 4171 case ACCESSOR: {
4148 #ifdef DEBUG 4172 #ifdef DEBUG
4149 FieldType* new_type = new_descriptors->GetFieldType(i); 4173 FieldType* new_type = new_descriptors->GetFieldType(i);
4150 DCHECK(new_type->IsAny()); 4174 DCHECK(new_type->IsAny());
4151 #endif 4175 #endif
4152 break; 4176 break;
4153 } 4177 }
4154 4178
4155 case DATA_CONSTANT: 4179 case DATA_CONSTANT:
4156 case ACCESSOR_CONSTANT: { 4180 case ACCESSOR_CONSTANT: {
4157 Object* old_value = old_descriptors->GetValue(i); 4181 Object* old_value = old_descriptors->GetValue(i);
4158 Object* new_value = new_descriptors->GetValue(i); 4182 Object* new_value = new_descriptors->GetValue(i);
4159 if (old_details.location() == kField || old_value != new_value) { 4183 if (old_details.location() == kField || old_value != new_value) {
4160 return MaybeHandle<Map>(); 4184 return nullptr;
4161 } 4185 }
4162 break; 4186 break;
4163 } 4187 }
4164 } 4188 }
4165 } 4189 }
4166 if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>(); 4190 if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr;
4167 return handle(new_map); 4191 return new_map;
4168 } 4192 }
4169 4193
4170 4194
4171 // static 4195 // static
4172 Handle<Map> Map::Update(Handle<Map> map) { 4196 Handle<Map> Map::Update(Handle<Map> map) {
4173 if (!map->is_deprecated()) return map; 4197 if (!map->is_deprecated()) return map;
4174 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), 4198 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
4175 FieldType::None(map->GetIsolate()), 4199 FieldType::None(map->GetIsolate()),
4176 ALLOW_IN_DESCRIPTOR); 4200 ALLOW_IN_DESCRIPTOR);
4177 } 4201 }
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
4750 4774
4751 4775
4752 static bool ContainsMap(MapHandleList* maps, Map* map) { 4776 static bool ContainsMap(MapHandleList* maps, Map* map) {
4753 DCHECK_NOT_NULL(map); 4777 DCHECK_NOT_NULL(map);
4754 for (int i = 0; i < maps->length(); ++i) { 4778 for (int i = 0; i < maps->length(); ++i) {
4755 if (!maps->at(i).is_null() && *maps->at(i) == map) return true; 4779 if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
4756 } 4780 }
4757 return false; 4781 return false;
4758 } 4782 }
4759 4783
4784 Map* Map::FindElementsKindTransitionedMap(MapHandleList* candidates) {
4785 DisallowHeapAllocation no_allocation;
4786 DisallowDeoptimization no_deoptimization(GetIsolate());
4760 4787
4761 Handle<Map> Map::FindTransitionedMap(Handle<Map> map, 4788 ElementsKind kind = elements_kind();
4762 MapHandleList* candidates) {
4763 ElementsKind kind = map->elements_kind();
4764 bool packed = IsFastPackedElementsKind(kind); 4789 bool packed = IsFastPackedElementsKind(kind);
4765 4790
4766 Map* transition = nullptr; 4791 Map* transition = nullptr;
4767 if (IsTransitionableFastElementsKind(kind)) { 4792 if (IsTransitionableFastElementsKind(kind)) {
4768 for (Map* current = map->ElementsTransitionMap(); 4793 // Check the state of the root map.
4769 current != nullptr && current->has_fast_elements(); 4794 Map* root_map = FindRootMap();
4770 current = current->ElementsTransitionMap()) { 4795 if (!EquivalentToForTransition(root_map)) return nullptr;
4796 root_map = root_map->LookupElementsTransitionMap(kind);
4797 DCHECK_NOT_NULL(root_map);
4798 // Starting from the next existing elements kind transition try to
4799 // replay the property transitions that does not involve instance rewriting
4800 // (ElementsTransitionAndStoreStub does not support that).
4801 for (root_map = root_map->ElementsTransitionMap();
4802 root_map != nullptr && root_map->has_fast_elements();
4803 root_map = root_map->ElementsTransitionMap()) {
4804 Map* current = root_map->TryReplayPropertyTransitions(this);
4805 if (current == nullptr) continue;
4806 if (InstancesNeedRewriting(current)) continue;
4807
4771 if (ContainsMap(candidates, current) && 4808 if (ContainsMap(candidates, current) &&
4772 (packed || !IsFastPackedElementsKind(current->elements_kind()))) { 4809 (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
4773 transition = current; 4810 transition = current;
4774 packed = packed && IsFastPackedElementsKind(current->elements_kind()); 4811 packed = packed && IsFastPackedElementsKind(current->elements_kind());
4775 } 4812 }
4776 } 4813 }
4777 } 4814 }
4778 return transition == nullptr ? Handle<Map>() : handle(transition); 4815 return transition;
4779 } 4816 }
4780 4817
4781 4818
4782 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { 4819 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
4820 // Ensure we are requested to search elements kind transition "near the root".
4821 DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
4822 map->NumberOfOwnDescriptors());
4783 Map* current_map = map; 4823 Map* current_map = map;
4784 4824
4785 ElementsKind kind = map->elements_kind(); 4825 ElementsKind kind = map->elements_kind();
4786 while (kind != to_kind) { 4826 while (kind != to_kind) {
4787 Map* next_map = current_map->ElementsTransitionMap(); 4827 Map* next_map = current_map->ElementsTransitionMap();
4788 if (next_map == nullptr) return current_map; 4828 if (next_map == nullptr) return current_map;
4789 kind = next_map->elements_kind(); 4829 kind = next_map->elements_kind();
4790 current_map = next_map; 4830 current_map = next_map;
4791 } 4831 }
4792 4832
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
4901 if (IsFastElementsKind(to_kind)) { 4941 if (IsFastElementsKind(to_kind)) {
4902 allow_store_transition = 4942 allow_store_transition =
4903 allow_store_transition && IsTransitionableFastElementsKind(from_kind) && 4943 allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
4904 IsMoreGeneralElementsKindTransition(from_kind, to_kind); 4944 IsMoreGeneralElementsKindTransition(from_kind, to_kind);
4905 } 4945 }
4906 4946
4907 if (!allow_store_transition) { 4947 if (!allow_store_transition) {
4908 return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION); 4948 return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
4909 } 4949 }
4910 4950
4911 return Map::AsElementsKind(map, to_kind); 4951 return Map::ReconfigureElementsKind(map, to_kind);
4912 } 4952 }
4913 4953
4914 4954
4915 // static 4955 // static
4916 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) { 4956 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
4917 Handle<Map> closest_map(FindClosestElementsTransition(*map, kind)); 4957 Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
4918 4958
4919 if (closest_map->elements_kind() == kind) { 4959 if (closest_map->elements_kind() == kind) {
4920 return closest_map; 4960 return closest_map;
4921 } 4961 }
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
5263 if (map_kind != obj_kind) { 5303 if (map_kind != obj_kind) {
5264 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind); 5304 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
5265 if (IsDictionaryElementsKind(obj_kind)) { 5305 if (IsDictionaryElementsKind(obj_kind)) {
5266 to_kind = obj_kind; 5306 to_kind = obj_kind;
5267 } 5307 }
5268 if (IsDictionaryElementsKind(to_kind)) { 5308 if (IsDictionaryElementsKind(to_kind)) {
5269 NormalizeElements(object); 5309 NormalizeElements(object);
5270 } else { 5310 } else {
5271 TransitionElementsKind(object, to_kind); 5311 TransitionElementsKind(object, to_kind);
5272 } 5312 }
5273 map = Map::AsElementsKind(map, to_kind); 5313 map = Map::ReconfigureElementsKind(map, to_kind);
5274 } 5314 }
5275 JSObject::MigrateToMap(object, map); 5315 JSObject::MigrateToMap(object, map);
5276 } 5316 }
5277 5317
5278 5318
5279 void JSObject::MigrateInstance(Handle<JSObject> object) { 5319 void JSObject::MigrateInstance(Handle<JSObject> object) {
5280 Handle<Map> original_map(object->map()); 5320 Handle<Map> original_map(object->map());
5281 Handle<Map> map = Map::Update(original_map); 5321 Handle<Map> map = Map::Update(original_map);
5282 map->set_migration_target(true); 5322 map->set_migration_target(true);
5283 MigrateToMap(object, map); 5323 MigrateToMap(object, map);
(...skipping 3572 matching lines...) Expand 10 before | Expand all | Expand 10 after
8856 8896
8857 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); 8897 Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
8858 ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION); 8898 ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION);
8859 } 8899 }
8860 8900
8861 8901
8862 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, 8902 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
8863 TransitionFlag flag) { 8903 TransitionFlag flag) {
8864 Map* maybe_elements_transition_map = NULL; 8904 Map* maybe_elements_transition_map = NULL;
8865 if (flag == INSERT_TRANSITION) { 8905 if (flag == INSERT_TRANSITION) {
8906 // Ensure we are requested to add elements kind transition "near the root".
8907 DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
8908 map->NumberOfOwnDescriptors());
8909
8866 maybe_elements_transition_map = map->ElementsTransitionMap(); 8910 maybe_elements_transition_map = map->ElementsTransitionMap();
8867 DCHECK(maybe_elements_transition_map == NULL || 8911 DCHECK(maybe_elements_transition_map == NULL ||
8868 (maybe_elements_transition_map->elements_kind() == 8912 (maybe_elements_transition_map->elements_kind() ==
8869 DICTIONARY_ELEMENTS && 8913 DICTIONARY_ELEMENTS &&
8870 kind == DICTIONARY_ELEMENTS)); 8914 kind == DICTIONARY_ELEMENTS));
8871 DCHECK(!IsFastElementsKind(kind) || 8915 DCHECK(!IsFastElementsKind(kind) ||
8872 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); 8916 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
8873 DCHECK(kind != map->elements_kind()); 8917 DCHECK(kind != map->elements_kind());
8874 } 8918 }
8875 8919
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
9160 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor, 9204 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
9161 PropertyKind kind, 9205 PropertyKind kind,
9162 PropertyAttributes attributes) { 9206 PropertyAttributes attributes) {
9163 // Dictionaries have to be reconfigured in-place. 9207 // Dictionaries have to be reconfigured in-place.
9164 DCHECK(!map->is_dictionary_map()); 9208 DCHECK(!map->is_dictionary_map());
9165 9209
9166 if (!map->GetBackPointer()->IsMap()) { 9210 if (!map->GetBackPointer()->IsMap()) {
9167 // There is no benefit from reconstructing transition tree for maps without 9211 // There is no benefit from reconstructing transition tree for maps without
9168 // back pointers. 9212 // back pointers.
9169 return CopyGeneralizeAllRepresentations( 9213 return CopyGeneralizeAllRepresentations(
9170 map, descriptor, FORCE_FIELD, kind, attributes, 9214 map, map->elements_kind(), descriptor, FORCE_FIELD, kind, attributes,
9171 "GenAll_AttributesMismatchProtoMap"); 9215 "GenAll_AttributesMismatchProtoMap");
9172 } 9216 }
9173 9217
9174 if (FLAG_trace_generalization) { 9218 if (FLAG_trace_generalization) {
9175 map->PrintReconfiguration(stdout, descriptor, kind, attributes); 9219 map->PrintReconfiguration(stdout, descriptor, kind, attributes);
9176 } 9220 }
9177 9221
9178 Isolate* isolate = map->GetIsolate(); 9222 Isolate* isolate = map->GetIsolate();
9179 Handle<Map> new_map = ReconfigureProperty( 9223 Handle<Map> new_map = ReconfigureProperty(
9180 map, descriptor, kind, attributes, Representation::None(), 9224 map, descriptor, kind, attributes, Representation::None(),
(...skipping 9188 matching lines...) Expand 10 before | Expand all | Expand 10 after
18369 if (cell->value() != *new_value) { 18413 if (cell->value() != *new_value) {
18370 cell->set_value(*new_value); 18414 cell->set_value(*new_value);
18371 Isolate* isolate = cell->GetIsolate(); 18415 Isolate* isolate = cell->GetIsolate();
18372 cell->dependent_code()->DeoptimizeDependentCodeGroup( 18416 cell->dependent_code()->DeoptimizeDependentCodeGroup(
18373 isolate, DependentCode::kPropertyCellChangedGroup); 18417 isolate, DependentCode::kPropertyCellChangedGroup);
18374 } 18418 }
18375 } 18419 }
18376 18420
18377 } // namespace internal 18421 } // namespace internal
18378 } // namespace v8 18422 } // 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