| 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 |