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 2663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |