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 static void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) { |
Benedikt Meurer
2016/02/16 04:55:16
Nit: static in anonymous is not needed.
| |
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 static void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map, | |
Benedikt Meurer
2016/02/16 04:55:16
Nit: static in anonymous is not needed.
| |
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 |