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

Side by Side Diff: src/objects.cc

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