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 2794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2805 if (new_map->prototype_info()->IsPrototypeInfo()) { | 2805 if (new_map->prototype_info()->IsPrototypeInfo()) { |
2806 // The new map isn't registered with its prototype yet; reflect this fact | 2806 // The new map isn't registered with its prototype yet; reflect this fact |
2807 // in the PrototypeInfo it just inherited from the old map. | 2807 // in the PrototypeInfo it just inherited from the old map. |
2808 PrototypeInfo::cast(new_map->prototype_info()) | 2808 PrototypeInfo::cast(new_map->prototype_info()) |
2809 ->set_registry_slot(PrototypeInfo::UNREGISTERED); | 2809 ->set_registry_slot(PrototypeInfo::UNREGISTERED); |
2810 } | 2810 } |
2811 JSObject::LazyRegisterPrototypeUser(new_map, isolate); | 2811 JSObject::LazyRegisterPrototypeUser(new_map, isolate); |
2812 } | 2812 } |
2813 } | 2813 } |
2814 | 2814 |
2815 | 2815 namespace { |
2816 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, | |
2817 int expected_additional_properties) { | |
2818 if (object->map() == *new_map) return; | |
2819 // If this object is a prototype (the callee will check), invalidate any | |
2820 // prototype chains involving it. | |
2821 InvalidatePrototypeChains(object->map()); | |
2822 Handle<Map> old_map(object->map()); | |
2823 | |
2824 // If the map was registered with its prototype before, ensure that it | |
2825 // registers with its new prototype now. This preserves the invariant that | |
2826 // when a map on a prototype chain is registered with its prototype, then | |
2827 // all prototypes further up the chain are also registered with their | |
2828 // respective prototypes. | |
2829 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate()); | |
2830 | |
2831 if (object->HasFastProperties()) { | |
2832 if (!new_map->is_dictionary_map()) { | |
2833 MigrateFastToFast(object, new_map); | |
2834 if (old_map->is_prototype_map()) { | |
2835 DCHECK(!old_map->is_stable()); | |
2836 DCHECK(new_map->is_stable()); | |
2837 // Clear out the old descriptor array to avoid problems to sharing | |
2838 // the descriptor array without using an explicit. | |
2839 old_map->InitializeDescriptors( | |
2840 old_map->GetHeap()->empty_descriptor_array(), | |
2841 LayoutDescriptor::FastPointerLayout()); | |
2842 // Ensure that no transition was inserted for prototype migrations. | |
2843 DCHECK_EQ(0, TransitionArray::NumberOfTransitions( | |
2844 old_map->raw_transitions())); | |
2845 DCHECK(new_map->GetBackPointer()->IsUndefined()); | |
2846 } | |
2847 } else { | |
2848 MigrateFastToSlow(object, new_map, expected_additional_properties); | |
2849 } | |
2850 } else { | |
2851 // For slow-to-fast migrations JSObject::MigrateSlowToFast() | |
2852 // must be used instead. | |
2853 CHECK(new_map->is_dictionary_map()); | |
2854 | |
2855 // Slow-to-slow migration is trivial. | |
2856 object->set_map(*new_map); | |
2857 } | |
2858 | |
2859 // Careful: Don't allocate here! | |
2860 // For some callers of this method, |object| might be in an inconsistent | |
2861 // state now: the new map might have a new elements_kind, but the object's | |
2862 // elements pointer hasn't been updated yet. Callers will fix this, but in | |
2863 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. | |
2864 // When adding code here, add a DisallowHeapAllocation too. | |
2865 } | |
2866 | |
2867 | |
2868 // To migrate a fast instance to a fast map: | 2816 // To migrate a fast instance to a fast map: |
2869 // - First check whether the instance needs to be rewritten. If not, simply | 2817 // - First check whether the instance needs to be rewritten. If not, simply |
2870 // change the map. | 2818 // change the map. |
2871 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 2819 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
2872 // addition to unused space. | 2820 // addition to unused space. |
2873 // - Copy all existing properties in, in the following order: backing store | 2821 // - Copy all existing properties in, in the following order: backing store |
2874 // properties, unused fields, inobject properties. | 2822 // properties, unused fields, inobject properties. |
2875 // - If all allocation succeeded, commit the state atomically: | 2823 // - If all allocation succeeded, commit the state atomically: |
2876 // * Copy inobject properties from the backing store back into the object. | 2824 // * Copy inobject properties from the backing store back into the object. |
2877 // * Trim the difference in instance size of the object. This also cleanly | 2825 // * Trim the difference in instance size of the object. This also cleanly |
2878 // frees inobject properties that moved to the backing store. | 2826 // frees inobject properties that moved to the backing store. |
2879 // * If there are properties left in the backing store, trim of the space used | 2827 // * If there are properties left in the backing store, trim of the space used |
2880 // to temporarily store the inobject properties. | 2828 // to temporarily store the inobject properties. |
2881 // * If there are properties left in the backing store, install the backing | 2829 // * If there are properties left in the backing store, install the backing |
2882 // store. | 2830 // store. |
2883 void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) { | 2831 void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) { |
2884 Isolate* isolate = object->GetIsolate(); | 2832 Isolate* isolate = object->GetIsolate(); |
2885 Handle<Map> old_map(object->map()); | 2833 Handle<Map> old_map(object->map()); |
2886 // In case of a regular transition. | 2834 // In case of a regular transition. |
2887 if (new_map->GetBackPointer() == *old_map) { | 2835 if (new_map->GetBackPointer() == *old_map) { |
2888 // If the map does not add named properties, simply set the map. | 2836 // If the map does not add named properties, simply set the map. |
2889 if (old_map->NumberOfOwnDescriptors() == | 2837 if (old_map->NumberOfOwnDescriptors() == |
2890 new_map->NumberOfOwnDescriptors()) { | 2838 new_map->NumberOfOwnDescriptors()) { |
2891 object->synchronized_set_map(*new_map); | 2839 object->synchronized_set_map(*new_map); |
2892 return; | 2840 return; |
2893 } | 2841 } |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3077 address + new_instance_size, instance_size_delta); | 3025 address + new_instance_size, instance_size_delta); |
3078 heap->AdjustLiveBytes(*object, -instance_size_delta, | 3026 heap->AdjustLiveBytes(*object, -instance_size_delta, |
3079 Heap::CONCURRENT_TO_SWEEPER); | 3027 Heap::CONCURRENT_TO_SWEEPER); |
3080 } | 3028 } |
3081 | 3029 |
3082 // We are storing the new map using release store after creating a filler for | 3030 // We are storing the new map using release store after creating a filler for |
3083 // the left-over space to avoid races with the sweeper thread. | 3031 // the left-over space to avoid races with the sweeper thread. |
3084 object->synchronized_set_map(*new_map); | 3032 object->synchronized_set_map(*new_map); |
3085 } | 3033 } |
3086 | 3034 |
| 3035 void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map, |
| 3036 int expected_additional_properties) { |
| 3037 // The global object is always normalized. |
| 3038 DCHECK(!object->IsJSGlobalObject()); |
| 3039 // JSGlobalProxy must never be normalized |
| 3040 DCHECK(!object->IsJSGlobalProxy()); |
| 3041 |
| 3042 Isolate* isolate = object->GetIsolate(); |
| 3043 HandleScope scope(isolate); |
| 3044 Handle<Map> map(object->map()); |
| 3045 |
| 3046 // Allocate new content. |
| 3047 int real_size = map->NumberOfOwnDescriptors(); |
| 3048 int property_count = real_size; |
| 3049 if (expected_additional_properties > 0) { |
| 3050 property_count += expected_additional_properties; |
| 3051 } else { |
| 3052 property_count += 2; // Make space for two more properties. |
| 3053 } |
| 3054 Handle<NameDictionary> dictionary = |
| 3055 NameDictionary::New(isolate, property_count); |
| 3056 |
| 3057 Handle<DescriptorArray> descs(map->instance_descriptors()); |
| 3058 for (int i = 0; i < real_size; i++) { |
| 3059 PropertyDetails details = descs->GetDetails(i); |
| 3060 Handle<Name> key(descs->GetKey(i)); |
| 3061 switch (details.type()) { |
| 3062 case DATA_CONSTANT: { |
| 3063 Handle<Object> value(descs->GetConstant(i), isolate); |
| 3064 PropertyDetails d(details.attributes(), DATA, i + 1, |
| 3065 PropertyCellType::kNoCell); |
| 3066 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 3067 break; |
| 3068 } |
| 3069 case DATA: { |
| 3070 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
| 3071 Handle<Object> value; |
| 3072 if (object->IsUnboxedDoubleField(index)) { |
| 3073 double old_value = object->RawFastDoublePropertyAt(index); |
| 3074 value = isolate->factory()->NewHeapNumber(old_value); |
| 3075 } else { |
| 3076 value = handle(object->RawFastPropertyAt(index), isolate); |
| 3077 if (details.representation().IsDouble()) { |
| 3078 DCHECK(value->IsMutableHeapNumber()); |
| 3079 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); |
| 3080 value = isolate->factory()->NewHeapNumber(old->value()); |
| 3081 } |
| 3082 } |
| 3083 PropertyDetails d(details.attributes(), DATA, i + 1, |
| 3084 PropertyCellType::kNoCell); |
| 3085 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 3086 break; |
| 3087 } |
| 3088 case ACCESSOR: { |
| 3089 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
| 3090 Handle<Object> value(object->RawFastPropertyAt(index), isolate); |
| 3091 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
| 3092 PropertyCellType::kNoCell); |
| 3093 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 3094 break; |
| 3095 } |
| 3096 case ACCESSOR_CONSTANT: { |
| 3097 Handle<Object> value(descs->GetCallbacksObject(i), isolate); |
| 3098 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
| 3099 PropertyCellType::kNoCell); |
| 3100 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 3101 break; |
| 3102 } |
| 3103 } |
| 3104 } |
| 3105 |
| 3106 // Copy the next enumeration index from instance descriptor. |
| 3107 dictionary->SetNextEnumerationIndex(real_size + 1); |
| 3108 |
| 3109 // From here on we cannot fail and we shouldn't GC anymore. |
| 3110 DisallowHeapAllocation no_allocation; |
| 3111 |
| 3112 // Resize the object in the heap if necessary. |
| 3113 int new_instance_size = new_map->instance_size(); |
| 3114 int instance_size_delta = map->instance_size() - new_instance_size; |
| 3115 DCHECK(instance_size_delta >= 0); |
| 3116 |
| 3117 if (instance_size_delta > 0) { |
| 3118 Heap* heap = isolate->heap(); |
| 3119 heap->CreateFillerObjectAt(object->address() + new_instance_size, |
| 3120 instance_size_delta); |
| 3121 heap->AdjustLiveBytes(*object, -instance_size_delta, |
| 3122 Heap::CONCURRENT_TO_SWEEPER); |
| 3123 } |
| 3124 |
| 3125 // We are storing the new map using release store after creating a filler for |
| 3126 // the left-over space to avoid races with the sweeper thread. |
| 3127 object->synchronized_set_map(*new_map); |
| 3128 |
| 3129 object->set_properties(*dictionary); |
| 3130 |
| 3131 // Ensure that in-object space of slow-mode object does not contain random |
| 3132 // garbage. |
| 3133 int inobject_properties = new_map->GetInObjectProperties(); |
| 3134 for (int i = 0; i < inobject_properties; i++) { |
| 3135 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); |
| 3136 object->RawFastPropertyAtPut(index, Smi::FromInt(0)); |
| 3137 } |
| 3138 |
| 3139 isolate->counters()->props_to_dictionary()->Increment(); |
| 3140 |
| 3141 #ifdef DEBUG |
| 3142 if (FLAG_trace_normalization) { |
| 3143 OFStream os(stdout); |
| 3144 os << "Object properties have been normalized:\n"; |
| 3145 object->Print(os); |
| 3146 } |
| 3147 #endif |
| 3148 } |
| 3149 |
| 3150 } // namespace |
| 3151 |
| 3152 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, |
| 3153 int expected_additional_properties) { |
| 3154 if (object->map() == *new_map) return; |
| 3155 // If this object is a prototype (the callee will check), invalidate any |
| 3156 // prototype chains involving it. |
| 3157 InvalidatePrototypeChains(object->map()); |
| 3158 Handle<Map> old_map(object->map()); |
| 3159 |
| 3160 // If the map was registered with its prototype before, ensure that it |
| 3161 // registers with its new prototype now. This preserves the invariant that |
| 3162 // when a map on a prototype chain is registered with its prototype, then |
| 3163 // all prototypes further up the chain are also registered with their |
| 3164 // respective prototypes. |
| 3165 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate()); |
| 3166 |
| 3167 if (object->HasFastProperties()) { |
| 3168 if (!new_map->is_dictionary_map()) { |
| 3169 MigrateFastToFast(object, new_map); |
| 3170 if (old_map->is_prototype_map()) { |
| 3171 DCHECK(!old_map->is_stable()); |
| 3172 DCHECK(new_map->is_stable()); |
| 3173 // Clear out the old descriptor array to avoid problems to sharing |
| 3174 // the descriptor array without using an explicit. |
| 3175 old_map->InitializeDescriptors( |
| 3176 old_map->GetHeap()->empty_descriptor_array(), |
| 3177 LayoutDescriptor::FastPointerLayout()); |
| 3178 // Ensure that no transition was inserted for prototype migrations. |
| 3179 DCHECK_EQ(0, TransitionArray::NumberOfTransitions( |
| 3180 old_map->raw_transitions())); |
| 3181 DCHECK(new_map->GetBackPointer()->IsUndefined()); |
| 3182 } |
| 3183 } else { |
| 3184 MigrateFastToSlow(object, new_map, expected_additional_properties); |
| 3185 } |
| 3186 } else { |
| 3187 // For slow-to-fast migrations JSObject::MigrateSlowToFast() |
| 3188 // must be used instead. |
| 3189 CHECK(new_map->is_dictionary_map()); |
| 3190 |
| 3191 // Slow-to-slow migration is trivial. |
| 3192 object->set_map(*new_map); |
| 3193 } |
| 3194 |
| 3195 // Careful: Don't allocate here! |
| 3196 // For some callers of this method, |object| might be in an inconsistent |
| 3197 // state now: the new map might have a new elements_kind, but the object's |
| 3198 // elements pointer hasn't been updated yet. Callers will fix this, but in |
| 3199 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. |
| 3200 // When adding code here, add a DisallowHeapAllocation too. |
| 3201 } |
3087 | 3202 |
3088 int Map::NumberOfFields() { | 3203 int Map::NumberOfFields() { |
3089 DescriptorArray* descriptors = instance_descriptors(); | 3204 DescriptorArray* descriptors = instance_descriptors(); |
3090 int result = 0; | 3205 int result = 0; |
3091 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 3206 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
3092 if (descriptors->GetDetails(i).location() == kField) result++; | 3207 if (descriptors->GetDetails(i).location() == kField) result++; |
3093 } | 3208 } |
3094 return result; | 3209 return result; |
3095 } | 3210 } |
3096 | 3211 |
(...skipping 2462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5559 const char* reason) { | 5674 const char* reason) { |
5560 if (!object->HasFastProperties()) return; | 5675 if (!object->HasFastProperties()) return; |
5561 | 5676 |
5562 Handle<Map> map(object->map()); | 5677 Handle<Map> map(object->map()); |
5563 Handle<Map> new_map = Map::Normalize(map, mode, reason); | 5678 Handle<Map> new_map = Map::Normalize(map, mode, reason); |
5564 | 5679 |
5565 MigrateToMap(object, new_map, expected_additional_properties); | 5680 MigrateToMap(object, new_map, expected_additional_properties); |
5566 } | 5681 } |
5567 | 5682 |
5568 | 5683 |
5569 void JSObject::MigrateFastToSlow(Handle<JSObject> object, | |
5570 Handle<Map> new_map, | |
5571 int expected_additional_properties) { | |
5572 // The global object is always normalized. | |
5573 DCHECK(!object->IsJSGlobalObject()); | |
5574 // JSGlobalProxy must never be normalized | |
5575 DCHECK(!object->IsJSGlobalProxy()); | |
5576 | |
5577 Isolate* isolate = object->GetIsolate(); | |
5578 HandleScope scope(isolate); | |
5579 Handle<Map> map(object->map()); | |
5580 | |
5581 // Allocate new content. | |
5582 int real_size = map->NumberOfOwnDescriptors(); | |
5583 int property_count = real_size; | |
5584 if (expected_additional_properties > 0) { | |
5585 property_count += expected_additional_properties; | |
5586 } else { | |
5587 property_count += 2; // Make space for two more properties. | |
5588 } | |
5589 Handle<NameDictionary> dictionary = | |
5590 NameDictionary::New(isolate, property_count); | |
5591 | |
5592 Handle<DescriptorArray> descs(map->instance_descriptors()); | |
5593 for (int i = 0; i < real_size; i++) { | |
5594 PropertyDetails details = descs->GetDetails(i); | |
5595 Handle<Name> key(descs->GetKey(i)); | |
5596 switch (details.type()) { | |
5597 case DATA_CONSTANT: { | |
5598 Handle<Object> value(descs->GetConstant(i), isolate); | |
5599 PropertyDetails d(details.attributes(), DATA, i + 1, | |
5600 PropertyCellType::kNoCell); | |
5601 dictionary = NameDictionary::Add(dictionary, key, value, d); | |
5602 break; | |
5603 } | |
5604 case DATA: { | |
5605 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | |
5606 Handle<Object> value; | |
5607 if (object->IsUnboxedDoubleField(index)) { | |
5608 double old_value = object->RawFastDoublePropertyAt(index); | |
5609 value = isolate->factory()->NewHeapNumber(old_value); | |
5610 } else { | |
5611 value = handle(object->RawFastPropertyAt(index), isolate); | |
5612 if (details.representation().IsDouble()) { | |
5613 DCHECK(value->IsMutableHeapNumber()); | |
5614 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); | |
5615 value = isolate->factory()->NewHeapNumber(old->value()); | |
5616 } | |
5617 } | |
5618 PropertyDetails d(details.attributes(), DATA, i + 1, | |
5619 PropertyCellType::kNoCell); | |
5620 dictionary = NameDictionary::Add(dictionary, key, value, d); | |
5621 break; | |
5622 } | |
5623 case ACCESSOR: { | |
5624 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | |
5625 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | |
5626 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, | |
5627 PropertyCellType::kNoCell); | |
5628 dictionary = NameDictionary::Add(dictionary, key, value, d); | |
5629 break; | |
5630 } | |
5631 case ACCESSOR_CONSTANT: { | |
5632 Handle<Object> value(descs->GetCallbacksObject(i), isolate); | |
5633 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, | |
5634 PropertyCellType::kNoCell); | |
5635 dictionary = NameDictionary::Add(dictionary, key, value, d); | |
5636 break; | |
5637 } | |
5638 } | |
5639 } | |
5640 | |
5641 // Copy the next enumeration index from instance descriptor. | |
5642 dictionary->SetNextEnumerationIndex(real_size + 1); | |
5643 | |
5644 // From here on we cannot fail and we shouldn't GC anymore. | |
5645 DisallowHeapAllocation no_allocation; | |
5646 | |
5647 // Resize the object in the heap if necessary. | |
5648 int new_instance_size = new_map->instance_size(); | |
5649 int instance_size_delta = map->instance_size() - new_instance_size; | |
5650 DCHECK(instance_size_delta >= 0); | |
5651 | |
5652 if (instance_size_delta > 0) { | |
5653 Heap* heap = isolate->heap(); | |
5654 heap->CreateFillerObjectAt(object->address() + new_instance_size, | |
5655 instance_size_delta); | |
5656 heap->AdjustLiveBytes(*object, -instance_size_delta, | |
5657 Heap::CONCURRENT_TO_SWEEPER); | |
5658 } | |
5659 | |
5660 // We are storing the new map using release store after creating a filler for | |
5661 // the left-over space to avoid races with the sweeper thread. | |
5662 object->synchronized_set_map(*new_map); | |
5663 | |
5664 object->set_properties(*dictionary); | |
5665 | |
5666 // Ensure that in-object space of slow-mode object does not contain random | |
5667 // garbage. | |
5668 int inobject_properties = new_map->GetInObjectProperties(); | |
5669 for (int i = 0; i < inobject_properties; i++) { | |
5670 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); | |
5671 object->RawFastPropertyAtPut(index, Smi::FromInt(0)); | |
5672 } | |
5673 | |
5674 isolate->counters()->props_to_dictionary()->Increment(); | |
5675 | |
5676 #ifdef DEBUG | |
5677 if (FLAG_trace_normalization) { | |
5678 OFStream os(stdout); | |
5679 os << "Object properties have been normalized:\n"; | |
5680 object->Print(os); | |
5681 } | |
5682 #endif | |
5683 } | |
5684 | |
5685 | |
5686 void JSObject::MigrateSlowToFast(Handle<JSObject> object, | 5684 void JSObject::MigrateSlowToFast(Handle<JSObject> object, |
5687 int unused_property_fields, | 5685 int unused_property_fields, |
5688 const char* reason) { | 5686 const char* reason) { |
5689 if (object->HasFastProperties()) return; | 5687 if (object->HasFastProperties()) return; |
5690 DCHECK(!object->IsJSGlobalObject()); | 5688 DCHECK(!object->IsJSGlobalObject()); |
5691 Isolate* isolate = object->GetIsolate(); | 5689 Isolate* isolate = object->GetIsolate(); |
5692 Factory* factory = isolate->factory(); | 5690 Factory* factory = isolate->factory(); |
5693 Handle<NameDictionary> dictionary(object->property_dictionary()); | 5691 Handle<NameDictionary> dictionary(object->property_dictionary()); |
5694 | 5692 |
5695 // Make sure we preserve dictionary representation if there are too many | 5693 // Make sure we preserve dictionary representation if there are too many |
(...skipping 14289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19985 if (cell->value() != *new_value) { | 19983 if (cell->value() != *new_value) { |
19986 cell->set_value(*new_value); | 19984 cell->set_value(*new_value); |
19987 Isolate* isolate = cell->GetIsolate(); | 19985 Isolate* isolate = cell->GetIsolate(); |
19988 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19986 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19989 isolate, DependentCode::kPropertyCellChangedGroup); | 19987 isolate, DependentCode::kPropertyCellChangedGroup); |
19990 } | 19988 } |
19991 } | 19989 } |
19992 | 19990 |
19993 } // namespace internal | 19991 } // namespace internal |
19994 } // namespace v8 | 19992 } // namespace v8 |
OLD | NEW |