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

Side by Side Diff: src/objects.cc

Issue 2086483005: Version 5.1.281.68 (cherry-pick) (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@5.1
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 2659 matching lines...) Expand 10 before | Expand all | Expand 10 after
2670 case kDouble: return "d"; 2670 case kDouble: return "d";
2671 case kInteger32: return "i"; 2671 case kInteger32: return "i";
2672 case kHeapObject: return "h"; 2672 case kHeapObject: return "h";
2673 case kExternal: return "x"; 2673 case kExternal: return "x";
2674 default: 2674 default:
2675 UNREACHABLE(); 2675 UNREACHABLE();
2676 return NULL; 2676 return NULL;
2677 } 2677 }
2678 } 2678 }
2679 2679
2680 bool Map::InstancesNeedRewriting(Map* target) {
2681 int target_number_of_fields = target->NumberOfFields();
2682 int target_inobject = target->GetInObjectProperties();
2683 int target_unused = target->unused_property_fields();
2684 int old_number_of_fields;
2685
2686 return InstancesNeedRewriting(target, target_number_of_fields,
2687 target_inobject, target_unused,
2688 &old_number_of_fields);
2689 }
2680 2690
2681 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields, 2691 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
2682 int target_inobject, int target_unused, 2692 int target_inobject, int target_unused,
2683 int* old_number_of_fields) { 2693 int* old_number_of_fields) {
2684 // If fields were added (or removed), rewrite the instance. 2694 // If fields were added (or removed), rewrite the instance.
2685 *old_number_of_fields = NumberOfFields(); 2695 *old_number_of_fields = NumberOfFields();
2686 DCHECK(target_number_of_fields >= *old_number_of_fields); 2696 DCHECK(target_number_of_fields >= *old_number_of_fields);
2687 if (target_number_of_fields != *old_number_of_fields) return true; 2697 if (target_number_of_fields != *old_number_of_fields) return true;
2688 2698
2689 // If smi descriptors were replaced by double descriptors, rewrite. 2699 // If smi descriptors were replaced by double descriptors, rewrite.
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
3130 3140
3131 int Map::NumberOfFields() { 3141 int Map::NumberOfFields() {
3132 DescriptorArray* descriptors = instance_descriptors(); 3142 DescriptorArray* descriptors = instance_descriptors();
3133 int result = 0; 3143 int result = 0;
3134 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { 3144 for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
3135 if (descriptors->GetDetails(i).location() == kField) result++; 3145 if (descriptors->GetDetails(i).location() == kField) result++;
3136 } 3146 }
3137 return result; 3147 return result;
3138 } 3148 }
3139 3149
3140
3141 Handle<Map> Map::CopyGeneralizeAllRepresentations( 3150 Handle<Map> Map::CopyGeneralizeAllRepresentations(
3142 Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind, 3151 Handle<Map> map, ElementsKind elements_kind, int modify_index,
3143 PropertyAttributes attributes, const char* reason) { 3152 StoreMode store_mode, PropertyKind kind, PropertyAttributes attributes,
3153 const char* reason) {
3144 Isolate* isolate = map->GetIsolate(); 3154 Isolate* isolate = map->GetIsolate();
3145 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); 3155 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
3146 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 3156 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
3147 Handle<DescriptorArray> descriptors = 3157 Handle<DescriptorArray> descriptors =
3148 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors); 3158 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
3149 3159
3150 for (int i = 0; i < number_of_own_descriptors; i++) { 3160 for (int i = 0; i < number_of_own_descriptors; i++) {
3151 descriptors->SetRepresentation(i, Representation::Tagged()); 3161 descriptors->SetRepresentation(i, Representation::Tagged());
3152 if (descriptors->GetDetails(i).type() == DATA) { 3162 if (descriptors->GetDetails(i).type() == DATA) {
3153 descriptors->SetValue(i, FieldType::Any()); 3163 descriptors->SetValue(i, FieldType::Any());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3189 } 3199 }
3190 map->PrintGeneralization( 3200 map->PrintGeneralization(
3191 stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(), 3201 stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
3192 new_map->NumberOfOwnDescriptors(), 3202 new_map->NumberOfOwnDescriptors(),
3193 details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD, 3203 details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
3194 details.representation(), Representation::Tagged(), field_type, 3204 details.representation(), Representation::Tagged(), field_type,
3195 MaybeHandle<Object>(), FieldType::Any(isolate), 3205 MaybeHandle<Object>(), FieldType::Any(isolate),
3196 MaybeHandle<Object>()); 3206 MaybeHandle<Object>());
3197 } 3207 }
3198 } 3208 }
3209 new_map->set_elements_kind(elements_kind);
3199 return new_map; 3210 return new_map;
3200 } 3211 }
3201 3212
3202 3213
3203 void Map::DeprecateTransitionTree() { 3214 void Map::DeprecateTransitionTree() {
3204 if (is_deprecated()) return; 3215 if (is_deprecated()) return;
3205 Object* transitions = raw_transitions(); 3216 Object* transitions = raw_transitions();
3206 int num_transitions = TransitionArray::NumberOfTransitions(transitions); 3217 int num_transitions = TransitionArray::NumberOfTransitions(transitions);
3207 for (int i = 0; i < num_transitions; ++i) { 3218 for (int i = 0; i < num_transitions; ++i) {
3208 TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree(); 3219 TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
3441 DCHECK_EQ(details.location(), location); 3452 DCHECK_EQ(details.location(), location);
3442 #endif 3453 #endif
3443 if (location == kField) { 3454 if (location == kField) {
3444 return handle(descriptors->GetFieldType(descriptor), isolate); 3455 return handle(descriptors->GetFieldType(descriptor), isolate);
3445 } else { 3456 } else {
3446 return descriptors->GetValue(descriptor) 3457 return descriptors->GetValue(descriptor)
3447 ->OptimalType(isolate, representation); 3458 ->OptimalType(isolate, representation);
3448 } 3459 }
3449 } 3460 }
3450 3461
3451 3462 // Reconfigures elements kind to |new_elements_kind| and/or property at
3452 // Reconfigures property at |modify_index| with |new_kind|, |new_attributes|, 3463 // |modify_index| with |new_kind|, |new_attributes|, |store_mode| and/or
3453 // |store_mode| and/or |new_representation|/|new_field_type|. 3464 // |new_representation|/|new_field_type|.
3454 // If |modify_index| is negative then no properties are reconfigured but the 3465 // If |modify_index| is negative then no properties are reconfigured but the
3455 // map is migrated to the up-to-date non-deprecated state. 3466 // map is migrated to the up-to-date non-deprecated state.
3456 // 3467 //
3457 // This method rewrites or completes the transition tree to reflect the new 3468 // This method rewrites or completes the transition tree to reflect the new
3458 // change. To avoid high degrees over polymorphism, and to stabilize quickly, 3469 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
3459 // on every rewrite the new type is deduced by merging the current type with 3470 // on every rewrite the new type is deduced by merging the current type with
3460 // any potential new (partial) version of the type in the transition tree. 3471 // any potential new (partial) version of the type in the transition tree.
3461 // To do this, on each rewrite: 3472 // To do this, on each rewrite:
3462 // - Search the root of the transition tree using FindRootMap. 3473 // - Search the root of the transition tree using FindRootMap.
3474 // - Find/create a |root_map| with requested |new_elements_kind|.
3463 // - Find |target_map|, the newest matching version of this map using the 3475 // - Find |target_map|, the newest matching version of this map using the
3464 // virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at 3476 // virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
3465 // |modify_index| is considered to be of |new_kind| and having 3477 // |modify_index| is considered to be of |new_kind| and having
3466 // |new_attributes|) to walk the transition tree. 3478 // |new_attributes|) to walk the transition tree.
3467 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and 3479 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
3468 // descriptor array of the |target_map|. 3480 // descriptor array of the |target_map|.
3469 // - Generalize the |modify_index| descriptor using |new_representation| and 3481 // - Generalize the |modify_index| descriptor using |new_representation| and
3470 // |new_field_type|. 3482 // |new_field_type|.
3471 // - Walk the tree again starting from the root towards |target_map|. Stop at 3483 // - Walk the tree again starting from the root towards |target_map|. Stop at
3472 // |split_map|, the first map who's descriptor array does not match the merged 3484 // |split_map|, the first map who's descriptor array does not match the merged
3473 // descriptor array. 3485 // descriptor array.
3474 // - If |target_map| == |split_map|, |target_map| is in the expected state. 3486 // - If |target_map| == |split_map|, |target_map| is in the expected state.
3475 // Return it. 3487 // Return it.
3476 // - Otherwise, invalidate the outdated transition target from |target_map|, and 3488 // - Otherwise, invalidate the outdated transition target from |target_map|, and
3477 // replace its transition tree with a new branch for the updated descriptors. 3489 // replace its transition tree with a new branch for the updated descriptors.
3478 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index, 3490 Handle<Map> Map::Reconfigure(Handle<Map> old_map,
3479 PropertyKind new_kind, 3491 ElementsKind new_elements_kind, int modify_index,
3480 PropertyAttributes new_attributes, 3492 PropertyKind new_kind,
3481 Representation new_representation, 3493 PropertyAttributes new_attributes,
3482 Handle<FieldType> new_field_type, 3494 Representation new_representation,
3483 StoreMode store_mode) { 3495 Handle<FieldType> new_field_type,
3496 StoreMode store_mode) {
3484 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet. 3497 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet.
3485 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0); 3498 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
3486 Isolate* isolate = old_map->GetIsolate(); 3499 Isolate* isolate = old_map->GetIsolate();
3487 3500
3488 Handle<DescriptorArray> old_descriptors( 3501 Handle<DescriptorArray> old_descriptors(
3489 old_map->instance_descriptors(), isolate); 3502 old_map->instance_descriptors(), isolate);
3490 int old_nof = old_map->NumberOfOwnDescriptors(); 3503 int old_nof = old_map->NumberOfOwnDescriptors();
3491 3504
3492 // If it's just a representation generalization case (i.e. property kind and 3505 // If it's just a representation generalization case (i.e. property kind and
3493 // attributes stays unchanged) it's fine to transition from None to anything 3506 // attributes stays unchanged) it's fine to transition from None to anything
3494 // but double without any modification to the object, because the default 3507 // but double without any modification to the object, because the default
3495 // uninitialized value for representation None can be overwritten by both 3508 // uninitialized value for representation None can be overwritten by both
3496 // smi and tagged values. Doubles, however, would require a box allocation. 3509 // smi and tagged values. Doubles, however, would require a box allocation.
3497 if (modify_index >= 0 && !new_representation.IsNone() && 3510 if (modify_index >= 0 && !new_representation.IsNone() &&
3498 !new_representation.IsDouble()) { 3511 !new_representation.IsDouble() &&
3512 old_map->elements_kind() == new_elements_kind) {
3499 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 3513 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3500 Representation old_representation = old_details.representation(); 3514 Representation old_representation = old_details.representation();
3501 3515
3502 if (old_representation.IsNone()) { 3516 if (old_representation.IsNone()) {
3503 DCHECK_EQ(new_kind, old_details.kind()); 3517 DCHECK_EQ(new_kind, old_details.kind());
3504 DCHECK_EQ(new_attributes, old_details.attributes()); 3518 DCHECK_EQ(new_attributes, old_details.attributes());
3505 DCHECK_EQ(DATA, old_details.type()); 3519 DCHECK_EQ(DATA, old_details.type());
3506 if (FLAG_trace_generalization) { 3520 if (FLAG_trace_generalization) {
3507 old_map->PrintGeneralization( 3521 old_map->PrintGeneralization(
3508 stdout, "uninitialized field", modify_index, 3522 stdout, "uninitialized field", modify_index,
(...skipping 12 matching lines...) Expand all
3521 .Equals(new_representation)); 3535 .Equals(new_representation));
3522 DCHECK( 3536 DCHECK(
3523 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type)); 3537 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
3524 return old_map; 3538 return old_map;
3525 } 3539 }
3526 } 3540 }
3527 3541
3528 // Check the state of the root map. 3542 // Check the state of the root map.
3529 Handle<Map> root_map(old_map->FindRootMap(), isolate); 3543 Handle<Map> root_map(old_map->FindRootMap(), isolate);
3530 if (!old_map->EquivalentToForTransition(*root_map)) { 3544 if (!old_map->EquivalentToForTransition(*root_map)) {
3531 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3545 return CopyGeneralizeAllRepresentations(
3532 new_kind, new_attributes, 3546 old_map, new_elements_kind, modify_index, store_mode, new_kind,
3533 "GenAll_NotEquivalent"); 3547 new_attributes, "GenAll_NotEquivalent");
3534 } 3548 }
3535 3549
3536 ElementsKind from_kind = root_map->elements_kind(); 3550 ElementsKind from_kind = root_map->elements_kind();
3537 ElementsKind to_kind = old_map->elements_kind(); 3551 ElementsKind to_kind = new_elements_kind;
3538 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS. 3552 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
3539 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS && 3553 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
3554 to_kind != SLOW_STRING_WRAPPER_ELEMENTS &&
3540 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS && 3555 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
3541 !(IsTransitionableFastElementsKind(from_kind) && 3556 !(IsTransitionableFastElementsKind(from_kind) &&
3542 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) { 3557 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
3543 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3558 return CopyGeneralizeAllRepresentations(
3544 new_kind, new_attributes, 3559 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3545 "GenAll_InvalidElementsTransition"); 3560 "GenAll_InvalidElementsTransition");
3546 } 3561 }
3547 int root_nof = root_map->NumberOfOwnDescriptors(); 3562 int root_nof = root_map->NumberOfOwnDescriptors();
3548 if (modify_index >= 0 && modify_index < root_nof) { 3563 if (modify_index >= 0 && modify_index < root_nof) {
3549 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 3564 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3550 if (old_details.kind() != new_kind || 3565 if (old_details.kind() != new_kind ||
3551 old_details.attributes() != new_attributes) { 3566 old_details.attributes() != new_attributes) {
3552 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3567 return CopyGeneralizeAllRepresentations(
3553 new_kind, new_attributes, 3568 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3554 "GenAll_RootModification1"); 3569 "GenAll_RootModification1");
3555 } 3570 }
3556 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) || 3571 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
3557 (old_details.type() == DATA && 3572 (old_details.type() == DATA &&
3558 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || 3573 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
3559 !new_representation.fits_into(old_details.representation())))) { 3574 !new_representation.fits_into(old_details.representation())))) {
3560 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3575 return CopyGeneralizeAllRepresentations(
3561 new_kind, new_attributes, 3576 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3562 "GenAll_RootModification2"); 3577 "GenAll_RootModification2");
3563 } 3578 }
3564 } 3579 }
3565 3580
3566 // From here on, use the map with correct elements kind as root map. 3581 // From here on, use the map with correct elements kind as root map.
3567 if (from_kind != to_kind) { 3582 if (from_kind != to_kind) {
3568 root_map = Map::AsElementsKind(root_map, to_kind); 3583 root_map = Map::AsElementsKind(root_map, to_kind);
3569 } 3584 }
3570 3585
3571 Handle<Map> target_map = root_map; 3586 Handle<Map> target_map = root_map;
3572 for (int i = root_nof; i < old_nof; ++i) { 3587 for (int i = root_nof; i < old_nof; ++i) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3606 Handle<DescriptorArray> tmp_descriptors = handle( 3621 Handle<DescriptorArray> tmp_descriptors = handle(
3607 tmp_map->instance_descriptors(), isolate); 3622 tmp_map->instance_descriptors(), isolate);
3608 3623
3609 // Check if target map is incompatible. 3624 // Check if target map is incompatible.
3610 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); 3625 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3611 DCHECK_EQ(next_kind, tmp_details.kind()); 3626 DCHECK_EQ(next_kind, tmp_details.kind());
3612 DCHECK_EQ(next_attributes, tmp_details.attributes()); 3627 DCHECK_EQ(next_attributes, tmp_details.attributes());
3613 if (next_kind == kAccessor && 3628 if (next_kind == kAccessor &&
3614 !EqualImmutableValues(old_descriptors->GetValue(i), 3629 !EqualImmutableValues(old_descriptors->GetValue(i),
3615 tmp_descriptors->GetValue(i))) { 3630 tmp_descriptors->GetValue(i))) {
3616 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3631 return CopyGeneralizeAllRepresentations(
3617 new_kind, new_attributes, 3632 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3618 "GenAll_Incompatible"); 3633 "GenAll_Incompatible");
3619 } 3634 }
3620 if (next_location == kField && tmp_details.location() == kDescriptor) break; 3635 if (next_location == kField && tmp_details.location() == kDescriptor) break;
3621 3636
3622 Representation tmp_representation = tmp_details.representation(); 3637 Representation tmp_representation = tmp_details.representation();
3623 if (!next_representation.fits_into(tmp_representation)) break; 3638 if (!next_representation.fits_into(tmp_representation)) break;
3624 3639
3625 PropertyLocation old_location = old_details.location(); 3640 PropertyLocation old_location = old_details.location();
3626 PropertyLocation tmp_location = tmp_details.location(); 3641 PropertyLocation tmp_location = tmp_details.location();
3627 if (tmp_location == kField) { 3642 if (tmp_location == kField) {
3628 if (next_kind == kData) { 3643 if (next_kind == kData) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
3701 3716
3702 // Check if target map is compatible. 3717 // Check if target map is compatible.
3703 #ifdef DEBUG 3718 #ifdef DEBUG
3704 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); 3719 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3705 DCHECK_EQ(next_kind, tmp_details.kind()); 3720 DCHECK_EQ(next_kind, tmp_details.kind());
3706 DCHECK_EQ(next_attributes, tmp_details.attributes()); 3721 DCHECK_EQ(next_attributes, tmp_details.attributes());
3707 #endif 3722 #endif
3708 if (next_kind == kAccessor && 3723 if (next_kind == kAccessor &&
3709 !EqualImmutableValues(old_descriptors->GetValue(i), 3724 !EqualImmutableValues(old_descriptors->GetValue(i),
3710 tmp_descriptors->GetValue(i))) { 3725 tmp_descriptors->GetValue(i))) {
3711 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3726 return CopyGeneralizeAllRepresentations(
3712 new_kind, new_attributes, 3727 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3713 "GenAll_Incompatible"); 3728 "GenAll_Incompatible");
3714 } 3729 }
3715 DCHECK(!tmp_map->is_deprecated()); 3730 DCHECK(!tmp_map->is_deprecated());
3716 target_map = tmp_map; 3731 target_map = tmp_map;
3717 } 3732 }
3718 target_nof = target_map->NumberOfOwnDescriptors(); 3733 target_nof = target_map->NumberOfOwnDescriptors();
3719 target_descriptors = handle(target_map->instance_descriptors(), isolate); 3734 target_descriptors = handle(target_map->instance_descriptors(), isolate);
3720 3735
3721 // Allocate a new descriptor array large enough to hold the required 3736 // Allocate a new descriptor array large enough to hold the required
3722 // descriptors, with minimally the exact same size as the old descriptor 3737 // descriptors, with minimally the exact same size as the old descriptor
3723 // array. 3738 // array.
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
3934 split_attributes); 3949 split_attributes);
3935 if (maybe_transition != NULL) { 3950 if (maybe_transition != NULL) {
3936 maybe_transition->DeprecateTransitionTree(); 3951 maybe_transition->DeprecateTransitionTree();
3937 } 3952 }
3938 3953
3939 // If |maybe_transition| is not NULL then the transition array already 3954 // If |maybe_transition| is not NULL then the transition array already
3940 // contains entry for given descriptor. This means that the transition 3955 // contains entry for given descriptor. This means that the transition
3941 // could be inserted regardless of whether transitions array is full or not. 3956 // could be inserted regardless of whether transitions array is full or not.
3942 if (maybe_transition == NULL && 3957 if (maybe_transition == NULL &&
3943 !TransitionArray::CanHaveMoreTransitions(split_map)) { 3958 !TransitionArray::CanHaveMoreTransitions(split_map)) {
3944 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3959 return CopyGeneralizeAllRepresentations(
3945 new_kind, new_attributes, 3960 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3946 "GenAll_CantHaveMoreTransitions"); 3961 "GenAll_CantHaveMoreTransitions");
3947 } 3962 }
3948 3963
3949 old_map->NotifyLeafMapLayoutChange(); 3964 old_map->NotifyLeafMapLayoutChange();
3950 3965
3951 if (FLAG_trace_generalization && modify_index >= 0) { 3966 if (FLAG_trace_generalization && modify_index >= 0) {
3952 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 3967 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3953 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); 3968 PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
3954 MaybeHandle<FieldType> old_field_type; 3969 MaybeHandle<FieldType> old_field_type;
3955 MaybeHandle<FieldType> new_field_type; 3970 MaybeHandle<FieldType> new_field_type;
3956 MaybeHandle<Object> old_value; 3971 MaybeHandle<Object> old_value;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
4017 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>(); 4032 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
4018 4033
4019 ElementsKind from_kind = root_map->elements_kind(); 4034 ElementsKind from_kind = root_map->elements_kind();
4020 ElementsKind to_kind = old_map->elements_kind(); 4035 ElementsKind to_kind = old_map->elements_kind();
4021 if (from_kind != to_kind) { 4036 if (from_kind != to_kind) {
4022 // Try to follow existing elements kind transitions. 4037 // Try to follow existing elements kind transitions.
4023 root_map = root_map->LookupElementsTransitionMap(to_kind); 4038 root_map = root_map->LookupElementsTransitionMap(to_kind);
4024 if (root_map == NULL) return MaybeHandle<Map>(); 4039 if (root_map == NULL) return MaybeHandle<Map>();
4025 // From here on, use the map with correct elements kind as root map. 4040 // From here on, use the map with correct elements kind as root map.
4026 } 4041 }
4027 int root_nof = root_map->NumberOfOwnDescriptors(); 4042 Map* new_map = root_map->TryReplayPropertyTransitions(*old_map);
4043 if (new_map == nullptr) return MaybeHandle<Map>();
4044 return handle(new_map);
4045 }
4046
4047 Map* Map::TryReplayPropertyTransitions(Map* old_map) {
4048 DisallowHeapAllocation no_allocation;
4049 DisallowDeoptimization no_deoptimization(GetIsolate());
4050
4051 int root_nof = NumberOfOwnDescriptors();
4028 4052
4029 int old_nof = old_map->NumberOfOwnDescriptors(); 4053 int old_nof = old_map->NumberOfOwnDescriptors();
4030 DescriptorArray* old_descriptors = old_map->instance_descriptors(); 4054 DescriptorArray* old_descriptors = old_map->instance_descriptors();
4031 4055
4032 Map* new_map = root_map; 4056 Map* new_map = this;
4033 for (int i = root_nof; i < old_nof; ++i) { 4057 for (int i = root_nof; i < old_nof; ++i) {
4034 PropertyDetails old_details = old_descriptors->GetDetails(i); 4058 PropertyDetails old_details = old_descriptors->GetDetails(i);
4035 Map* transition = TransitionArray::SearchTransition( 4059 Map* transition = TransitionArray::SearchTransition(
4036 new_map, old_details.kind(), old_descriptors->GetKey(i), 4060 new_map, old_details.kind(), old_descriptors->GetKey(i),
4037 old_details.attributes()); 4061 old_details.attributes());
4038 if (transition == NULL) return MaybeHandle<Map>(); 4062 if (transition == NULL) return nullptr;
4039 new_map = transition; 4063 new_map = transition;
4040 DescriptorArray* new_descriptors = new_map->instance_descriptors(); 4064 DescriptorArray* new_descriptors = new_map->instance_descriptors();
4041 4065
4042 PropertyDetails new_details = new_descriptors->GetDetails(i); 4066 PropertyDetails new_details = new_descriptors->GetDetails(i);
4043 DCHECK_EQ(old_details.kind(), new_details.kind()); 4067 DCHECK_EQ(old_details.kind(), new_details.kind());
4044 DCHECK_EQ(old_details.attributes(), new_details.attributes()); 4068 DCHECK_EQ(old_details.attributes(), new_details.attributes());
4045 if (!old_details.representation().fits_into(new_details.representation())) { 4069 if (!old_details.representation().fits_into(new_details.representation())) {
4046 return MaybeHandle<Map>(); 4070 return nullptr;
4047 } 4071 }
4048 switch (new_details.type()) { 4072 switch (new_details.type()) {
4049 case DATA: { 4073 case DATA: {
4050 FieldType* new_type = new_descriptors->GetFieldType(i); 4074 FieldType* new_type = new_descriptors->GetFieldType(i);
4051 // Cleared field types need special treatment. They represent lost 4075 // Cleared field types need special treatment. They represent lost
4052 // knowledge, so we must first generalize the new_type to "Any". 4076 // knowledge, so we must first generalize the new_type to "Any".
4053 if (FieldTypeIsCleared(new_details.representation(), new_type)) { 4077 if (FieldTypeIsCleared(new_details.representation(), new_type)) {
4054 return MaybeHandle<Map>(); 4078 return nullptr;
4055 } 4079 }
4056 PropertyType old_property_type = old_details.type(); 4080 PropertyType old_property_type = old_details.type();
4057 if (old_property_type == DATA) { 4081 if (old_property_type == DATA) {
4058 FieldType* old_type = old_descriptors->GetFieldType(i); 4082 FieldType* old_type = old_descriptors->GetFieldType(i);
4059 if (FieldTypeIsCleared(old_details.representation(), old_type) || 4083 if (FieldTypeIsCleared(old_details.representation(), old_type) ||
4060 !old_type->NowIs(new_type)) { 4084 !old_type->NowIs(new_type)) {
4061 return MaybeHandle<Map>(); 4085 return nullptr;
4062 } 4086 }
4063 } else { 4087 } else {
4064 DCHECK(old_property_type == DATA_CONSTANT); 4088 DCHECK(old_property_type == DATA_CONSTANT);
4065 Object* old_value = old_descriptors->GetValue(i); 4089 Object* old_value = old_descriptors->GetValue(i);
4066 if (!new_type->NowContains(old_value)) { 4090 if (!new_type->NowContains(old_value)) {
4067 return MaybeHandle<Map>(); 4091 return nullptr;
4068 } 4092 }
4069 } 4093 }
4070 break; 4094 break;
4071 } 4095 }
4072 case ACCESSOR: { 4096 case ACCESSOR: {
4073 #ifdef DEBUG 4097 #ifdef DEBUG
4074 FieldType* new_type = new_descriptors->GetFieldType(i); 4098 FieldType* new_type = new_descriptors->GetFieldType(i);
4075 DCHECK(new_type->IsAny()); 4099 DCHECK(new_type->IsAny());
4076 #endif 4100 #endif
4077 break; 4101 break;
4078 } 4102 }
4079 4103
4080 case DATA_CONSTANT: 4104 case DATA_CONSTANT:
4081 case ACCESSOR_CONSTANT: { 4105 case ACCESSOR_CONSTANT: {
4082 Object* old_value = old_descriptors->GetValue(i); 4106 Object* old_value = old_descriptors->GetValue(i);
4083 Object* new_value = new_descriptors->GetValue(i); 4107 Object* new_value = new_descriptors->GetValue(i);
4084 if (old_details.location() == kField || old_value != new_value) { 4108 if (old_details.location() == kField || old_value != new_value) {
4085 return MaybeHandle<Map>(); 4109 return nullptr;
4086 } 4110 }
4087 break; 4111 break;
4088 } 4112 }
4089 } 4113 }
4090 } 4114 }
4091 if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>(); 4115 if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr;
4092 return handle(new_map); 4116 return new_map;
4093 } 4117 }
4094 4118
4095 4119
4096 // static 4120 // static
4097 Handle<Map> Map::Update(Handle<Map> map) { 4121 Handle<Map> Map::Update(Handle<Map> map) {
4098 if (!map->is_deprecated()) return map; 4122 if (!map->is_deprecated()) return map;
4099 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), 4123 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
4100 FieldType::None(map->GetIsolate()), 4124 FieldType::None(map->GetIsolate()),
4101 ALLOW_IN_DESCRIPTOR); 4125 ALLOW_IN_DESCRIPTOR);
4102 } 4126 }
(...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after
4738 4762
4739 4763
4740 static bool ContainsMap(MapHandleList* maps, Map* map) { 4764 static bool ContainsMap(MapHandleList* maps, Map* map) {
4741 DCHECK_NOT_NULL(map); 4765 DCHECK_NOT_NULL(map);
4742 for (int i = 0; i < maps->length(); ++i) { 4766 for (int i = 0; i < maps->length(); ++i) {
4743 if (!maps->at(i).is_null() && *maps->at(i) == map) return true; 4767 if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
4744 } 4768 }
4745 return false; 4769 return false;
4746 } 4770 }
4747 4771
4772 Map* Map::FindElementsKindTransitionedMap(MapHandleList* candidates) {
4773 DisallowHeapAllocation no_allocation;
4774 DisallowDeoptimization no_deoptimization(GetIsolate());
4748 4775
4749 Handle<Map> Map::FindTransitionedMap(Handle<Map> map, 4776 ElementsKind kind = elements_kind();
4750 MapHandleList* candidates) {
4751 ElementsKind kind = map->elements_kind();
4752 bool packed = IsFastPackedElementsKind(kind); 4777 bool packed = IsFastPackedElementsKind(kind);
4753 4778
4754 Map* transition = nullptr; 4779 Map* transition = nullptr;
4755 if (IsTransitionableFastElementsKind(kind)) { 4780 if (IsTransitionableFastElementsKind(kind)) {
4756 for (Map* current = map->ElementsTransitionMap(); 4781 // Check the state of the root map.
4757 current != nullptr && current->has_fast_elements(); 4782 Map* root_map = FindRootMap();
4758 current = current->ElementsTransitionMap()) { 4783 if (!EquivalentToForTransition(root_map)) return nullptr;
4784 root_map = root_map->LookupElementsTransitionMap(kind);
4785 DCHECK_NOT_NULL(root_map);
4786 // Starting from the next existing elements kind transition try to
4787 // replay the property transitions that does not involve instance rewriting
4788 // (ElementsTransitionAndStoreStub does not support that).
4789 for (root_map = root_map->ElementsTransitionMap();
4790 root_map != nullptr && root_map->has_fast_elements();
4791 root_map = root_map->ElementsTransitionMap()) {
4792 Map* current = root_map->TryReplayPropertyTransitions(this);
4793 if (current == nullptr) continue;
4794 if (InstancesNeedRewriting(current)) continue;
4795
4759 if (ContainsMap(candidates, current) && 4796 if (ContainsMap(candidates, current) &&
4760 (packed || !IsFastPackedElementsKind(current->elements_kind()))) { 4797 (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
4761 transition = current; 4798 transition = current;
4762 packed = packed && IsFastPackedElementsKind(current->elements_kind()); 4799 packed = packed && IsFastPackedElementsKind(current->elements_kind());
4763 } 4800 }
4764 } 4801 }
4765 } 4802 }
4766 return transition == nullptr ? Handle<Map>() : handle(transition); 4803 return transition;
4767 } 4804 }
4768 4805
4769 4806
4770 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { 4807 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
4808 // Ensure we are requested to search elements kind transition "near the root".
4809 DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
4810 map->NumberOfOwnDescriptors());
4771 Map* current_map = map; 4811 Map* current_map = map;
4772 4812
4773 ElementsKind kind = map->elements_kind(); 4813 ElementsKind kind = map->elements_kind();
4774 while (kind != to_kind) { 4814 while (kind != to_kind) {
4775 Map* next_map = current_map->ElementsTransitionMap(); 4815 Map* next_map = current_map->ElementsTransitionMap();
4776 if (next_map == nullptr) return current_map; 4816 if (next_map == nullptr) return current_map;
4777 kind = next_map->elements_kind(); 4817 kind = next_map->elements_kind();
4778 current_map = next_map; 4818 current_map = next_map;
4779 } 4819 }
4780 4820
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
4889 if (IsFastElementsKind(to_kind)) { 4929 if (IsFastElementsKind(to_kind)) {
4890 allow_store_transition = 4930 allow_store_transition =
4891 allow_store_transition && IsTransitionableFastElementsKind(from_kind) && 4931 allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
4892 IsMoreGeneralElementsKindTransition(from_kind, to_kind); 4932 IsMoreGeneralElementsKindTransition(from_kind, to_kind);
4893 } 4933 }
4894 4934
4895 if (!allow_store_transition) { 4935 if (!allow_store_transition) {
4896 return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION); 4936 return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
4897 } 4937 }
4898 4938
4899 return Map::AsElementsKind(map, to_kind); 4939 return Map::ReconfigureElementsKind(map, to_kind);
4900 } 4940 }
4901 4941
4902 4942
4903 // static 4943 // static
4904 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) { 4944 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
4905 Handle<Map> closest_map(FindClosestElementsTransition(*map, kind)); 4945 Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
4906 4946
4907 if (closest_map->elements_kind() == kind) { 4947 if (closest_map->elements_kind() == kind) {
4908 return closest_map; 4948 return closest_map;
4909 } 4949 }
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
5213 if (map_kind != obj_kind) { 5253 if (map_kind != obj_kind) {
5214 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind); 5254 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
5215 if (IsDictionaryElementsKind(obj_kind)) { 5255 if (IsDictionaryElementsKind(obj_kind)) {
5216 to_kind = obj_kind; 5256 to_kind = obj_kind;
5217 } 5257 }
5218 if (IsDictionaryElementsKind(to_kind)) { 5258 if (IsDictionaryElementsKind(to_kind)) {
5219 NormalizeElements(object); 5259 NormalizeElements(object);
5220 } else { 5260 } else {
5221 TransitionElementsKind(object, to_kind); 5261 TransitionElementsKind(object, to_kind);
5222 } 5262 }
5223 map = Map::AsElementsKind(map, to_kind); 5263 map = Map::ReconfigureElementsKind(map, to_kind);
5224 } 5264 }
5225 JSObject::MigrateToMap(object, map); 5265 JSObject::MigrateToMap(object, map);
5226 } 5266 }
5227 5267
5228 5268
5229 void JSObject::MigrateInstance(Handle<JSObject> object) { 5269 void JSObject::MigrateInstance(Handle<JSObject> object) {
5230 Handle<Map> original_map(object->map()); 5270 Handle<Map> original_map(object->map());
5231 Handle<Map> map = Map::Update(original_map); 5271 Handle<Map> map = Map::Update(original_map);
5232 map->set_migration_target(true); 5272 map->set_migration_target(true);
5233 MigrateToMap(object, map); 5273 MigrateToMap(object, map);
(...skipping 4321 matching lines...) Expand 10 before | Expand all | Expand 10 after
9555 9595
9556 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); 9596 Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
9557 ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION); 9597 ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION);
9558 } 9598 }
9559 9599
9560 9600
9561 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, 9601 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
9562 TransitionFlag flag) { 9602 TransitionFlag flag) {
9563 Map* maybe_elements_transition_map = NULL; 9603 Map* maybe_elements_transition_map = NULL;
9564 if (flag == INSERT_TRANSITION) { 9604 if (flag == INSERT_TRANSITION) {
9605 // Ensure we are requested to add elements kind transition "near the root".
9606 DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
9607 map->NumberOfOwnDescriptors());
9608
9565 maybe_elements_transition_map = map->ElementsTransitionMap(); 9609 maybe_elements_transition_map = map->ElementsTransitionMap();
9566 DCHECK(maybe_elements_transition_map == NULL || 9610 DCHECK(maybe_elements_transition_map == NULL ||
9567 (maybe_elements_transition_map->elements_kind() == 9611 (maybe_elements_transition_map->elements_kind() ==
9568 DICTIONARY_ELEMENTS && 9612 DICTIONARY_ELEMENTS &&
9569 kind == DICTIONARY_ELEMENTS)); 9613 kind == DICTIONARY_ELEMENTS));
9570 DCHECK(!IsFastElementsKind(kind) || 9614 DCHECK(!IsFastElementsKind(kind) ||
9571 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); 9615 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
9572 DCHECK(kind != map->elements_kind()); 9616 DCHECK(kind != map->elements_kind());
9573 } 9617 }
9574 9618
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
9878 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor, 9922 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
9879 PropertyKind kind, 9923 PropertyKind kind,
9880 PropertyAttributes attributes) { 9924 PropertyAttributes attributes) {
9881 // Dictionaries have to be reconfigured in-place. 9925 // Dictionaries have to be reconfigured in-place.
9882 DCHECK(!map->is_dictionary_map()); 9926 DCHECK(!map->is_dictionary_map());
9883 9927
9884 if (!map->GetBackPointer()->IsMap()) { 9928 if (!map->GetBackPointer()->IsMap()) {
9885 // There is no benefit from reconstructing transition tree for maps without 9929 // There is no benefit from reconstructing transition tree for maps without
9886 // back pointers. 9930 // back pointers.
9887 return CopyGeneralizeAllRepresentations( 9931 return CopyGeneralizeAllRepresentations(
9888 map, descriptor, FORCE_FIELD, kind, attributes, 9932 map, map->elements_kind(), descriptor, FORCE_FIELD, kind, attributes,
9889 "GenAll_AttributesMismatchProtoMap"); 9933 "GenAll_AttributesMismatchProtoMap");
9890 } 9934 }
9891 9935
9892 if (FLAG_trace_generalization) { 9936 if (FLAG_trace_generalization) {
9893 map->PrintReconfiguration(stdout, descriptor, kind, attributes); 9937 map->PrintReconfiguration(stdout, descriptor, kind, attributes);
9894 } 9938 }
9895 9939
9896 Isolate* isolate = map->GetIsolate(); 9940 Isolate* isolate = map->GetIsolate();
9897 Handle<Map> new_map = ReconfigureProperty( 9941 Handle<Map> new_map = ReconfigureProperty(
9898 map, descriptor, kind, attributes, Representation::None(), 9942 map, descriptor, kind, attributes, Representation::None(),
(...skipping 9952 matching lines...) Expand 10 before | Expand all | Expand 10 after
19851 if (cell->value() != *new_value) { 19895 if (cell->value() != *new_value) {
19852 cell->set_value(*new_value); 19896 cell->set_value(*new_value);
19853 Isolate* isolate = cell->GetIsolate(); 19897 Isolate* isolate = cell->GetIsolate();
19854 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19898 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19855 isolate, DependentCode::kPropertyCellChangedGroup); 19899 isolate, DependentCode::kPropertyCellChangedGroup);
19856 } 19900 }
19857 } 19901 }
19858 19902
19859 } // namespace internal 19903 } // namespace internal
19860 } // namespace v8 19904 } // 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