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 3146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3157 InvalidatePrototypeChains(object->map()); | 3157 InvalidatePrototypeChains(object->map()); |
3158 Handle<Map> old_map(object->map()); | 3158 Handle<Map> old_map(object->map()); |
3159 | 3159 |
3160 // If the map was registered with its prototype before, ensure that it | 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 | 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 | 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 | 3163 // all prototypes further up the chain are also registered with their |
3164 // respective prototypes. | 3164 // respective prototypes. |
3165 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate()); | 3165 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate()); |
3166 | 3166 |
3167 if (object->HasFastProperties()) { | 3167 if (old_map->is_dictionary_map()) { |
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() | 3168 // For slow-to-fast migrations JSObject::MigrateSlowToFast() |
3188 // must be used instead. | 3169 // must be used instead. |
3189 CHECK(new_map->is_dictionary_map()); | 3170 CHECK(new_map->is_dictionary_map()); |
3190 | 3171 |
3191 // Slow-to-slow migration is trivial. | 3172 // Slow-to-slow migration is trivial. |
3192 object->set_map(*new_map); | 3173 object->set_map(*new_map); |
| 3174 } else if (!new_map->is_dictionary_map()) { |
| 3175 MigrateFastToFast(object, new_map); |
| 3176 if (old_map->is_prototype_map()) { |
| 3177 DCHECK(!old_map->is_stable()); |
| 3178 DCHECK(new_map->is_stable()); |
| 3179 // Clear out the old descriptor array to avoid problems to sharing |
| 3180 // the descriptor array without using an explicit. |
| 3181 old_map->InitializeDescriptors( |
| 3182 old_map->GetHeap()->empty_descriptor_array(), |
| 3183 LayoutDescriptor::FastPointerLayout()); |
| 3184 // Ensure that no transition was inserted for prototype migrations. |
| 3185 DCHECK_EQ( |
| 3186 0, TransitionArray::NumberOfTransitions(old_map->raw_transitions())); |
| 3187 DCHECK(new_map->GetBackPointer()->IsUndefined()); |
| 3188 } |
| 3189 } else { |
| 3190 MigrateFastToSlow(object, new_map, expected_additional_properties); |
3193 } | 3191 } |
3194 | 3192 |
3195 // Careful: Don't allocate here! | 3193 // Careful: Don't allocate here! |
3196 // For some callers of this method, |object| might be in an inconsistent | 3194 // 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 | 3195 // 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 | 3196 // elements pointer hasn't been updated yet. Callers will fix this, but in |
3199 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. | 3197 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. |
3200 // When adding code here, add a DisallowHeapAllocation too. | 3198 // When adding code here, add a DisallowHeapAllocation too. |
3201 } | 3199 } |
3202 | 3200 |
(...skipping 6720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9923 | 9921 |
9924 case ACCESSOR: | 9922 case ACCESSOR: |
9925 case ACCESSOR_CONSTANT: | 9923 case ACCESSOR_CONSTANT: |
9926 return false; | 9924 return false; |
9927 } | 9925 } |
9928 | 9926 |
9929 UNREACHABLE(); | 9927 UNREACHABLE(); |
9930 return false; | 9928 return false; |
9931 } | 9929 } |
9932 | 9930 |
| 9931 namespace { |
| 9932 |
| 9933 Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor, |
| 9934 Handle<Object> value) { |
| 9935 if (map->instance_descriptors()->CanHoldValue(descriptor, *value)) return map; |
| 9936 |
| 9937 Isolate* isolate = map->GetIsolate(); |
| 9938 PropertyAttributes attributes = |
| 9939 map->instance_descriptors()->GetDetails(descriptor).attributes(); |
| 9940 Representation representation = value->OptimalRepresentation(); |
| 9941 Handle<FieldType> type = value->OptimalType(isolate, representation); |
| 9942 |
| 9943 return Map::ReconfigureProperty(map, descriptor, kData, attributes, |
| 9944 representation, type, FORCE_FIELD); |
| 9945 } |
| 9946 |
| 9947 } // namespace |
9933 | 9948 |
9934 // static | 9949 // static |
9935 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, | 9950 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, |
9936 Handle<Object> value) { | 9951 Handle<Object> value) { |
9937 // Dictionaries can store any property value. | 9952 // Dictionaries can store any property value. |
9938 if (map->is_dictionary_map()) return map; | 9953 if (map->is_dictionary_map()) return map; |
9939 | 9954 |
9940 // Migrate to the newest map before storing the property. | 9955 // Update to the newest map before storing the property. |
9941 map = Update(map); | 9956 return UpdateDescriptorForValue(Update(map), descriptor, value); |
9942 | |
9943 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | |
9944 | |
9945 if (descriptors->CanHoldValue(descriptor, *value)) return map; | |
9946 | |
9947 Isolate* isolate = map->GetIsolate(); | |
9948 PropertyAttributes attributes = | |
9949 descriptors->GetDetails(descriptor).attributes(); | |
9950 Representation representation = value->OptimalRepresentation(); | |
9951 Handle<FieldType> type = value->OptimalType(isolate, representation); | |
9952 | |
9953 return ReconfigureProperty(map, descriptor, kData, attributes, representation, | |
9954 type, FORCE_FIELD); | |
9955 } | 9957 } |
9956 | 9958 |
9957 | 9959 |
9958 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, | 9960 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
9959 Handle<Object> value, | 9961 Handle<Object> value, |
9960 PropertyAttributes attributes, | 9962 PropertyAttributes attributes, |
9961 StoreFromKeyed store_mode) { | 9963 StoreFromKeyed store_mode) { |
9962 // Dictionary maps can always have additional data properties. | 9964 // Dictionary maps can always have additional data properties. |
9963 if (map->is_dictionary_map()) return map; | 9965 if (map->is_dictionary_map()) return map; |
9964 | 9966 |
9965 // Migrate to the newest map before storing the property. | 9967 // Migrate to the newest map before storing the property. |
9966 map = Update(map); | 9968 map = Update(map); |
9967 | 9969 |
9968 Map* maybe_transition = | 9970 Map* maybe_transition = |
9969 TransitionArray::SearchTransition(*map, kData, *name, attributes); | 9971 TransitionArray::SearchTransition(*map, kData, *name, attributes); |
9970 if (maybe_transition != NULL) { | 9972 if (maybe_transition != NULL) { |
9971 Handle<Map> transition(maybe_transition); | 9973 Handle<Map> transition(maybe_transition); |
9972 int descriptor = transition->LastAdded(); | 9974 int descriptor = transition->LastAdded(); |
9973 | 9975 |
9974 DCHECK_EQ(attributes, transition->instance_descriptors() | 9976 DCHECK_EQ(attributes, transition->instance_descriptors() |
9975 ->GetDetails(descriptor) | 9977 ->GetDetails(descriptor) |
9976 .attributes()); | 9978 .attributes()); |
9977 | 9979 |
9978 return Map::PrepareForDataProperty(transition, descriptor, value); | 9980 return UpdateDescriptorForValue(transition, descriptor, value); |
9979 } | 9981 } |
9980 | 9982 |
9981 TransitionFlag flag = INSERT_TRANSITION; | 9983 TransitionFlag flag = INSERT_TRANSITION; |
9982 MaybeHandle<Map> maybe_map; | 9984 MaybeHandle<Map> maybe_map; |
9983 if (value->IsJSFunction()) { | 9985 if (value->IsJSFunction()) { |
9984 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); | 9986 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); |
9985 } else if (!map->TooManyFastProperties(store_mode)) { | 9987 } else if (!map->TooManyFastProperties(store_mode)) { |
9986 Isolate* isolate = name->GetIsolate(); | 9988 Isolate* isolate = name->GetIsolate(); |
9987 Representation representation = value->OptimalRepresentation(); | 9989 Representation representation = value->OptimalRepresentation(); |
9988 Handle<FieldType> type = value->OptimalType(isolate, representation); | 9990 Handle<FieldType> type = value->OptimalType(isolate, representation); |
(...skipping 9994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19983 if (cell->value() != *new_value) { | 19985 if (cell->value() != *new_value) { |
19984 cell->set_value(*new_value); | 19986 cell->set_value(*new_value); |
19985 Isolate* isolate = cell->GetIsolate(); | 19987 Isolate* isolate = cell->GetIsolate(); |
19986 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19988 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19987 isolate, DependentCode::kPropertyCellChangedGroup); | 19989 isolate, DependentCode::kPropertyCellChangedGroup); |
19988 } | 19990 } |
19989 } | 19991 } |
19990 | 19992 |
19991 } // namespace internal | 19993 } // namespace internal |
19992 } // namespace v8 | 19994 } // namespace v8 |
OLD | NEW |