OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 2734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |