| 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 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4601   DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); | 4599   DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); | 
| 4602 | 4600 | 
| 4603   Handle<JSObject> receiver = it->GetStoreTarget(); | 4601   Handle<JSObject> receiver = it->GetStoreTarget(); | 
| 4604 | 4602 | 
| 4605   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) | 4603   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) | 
| 4606   // instead. If the prototype is Null, the proxy is detached. | 4604   // instead. If the prototype is Null, the proxy is detached. | 
| 4607   if (receiver->IsJSGlobalProxy()) return Just(true); | 4605   if (receiver->IsJSGlobalProxy()) return Just(true); | 
| 4608 | 4606 | 
| 4609   Isolate* isolate = it->isolate(); | 4607   Isolate* isolate = it->isolate(); | 
| 4610 | 4608 | 
| 4611   if (!receiver->map()->is_extensible() && | 4609   if (it->ExtendingNonExtensible(receiver)) { | 
| 4612       (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) { |  | 
| 4613     RETURN_FAILURE( | 4610     RETURN_FAILURE( | 
| 4614         isolate, should_throw, | 4611         isolate, should_throw, | 
| 4615         NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName())); | 4612         NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName())); | 
| 4616   } | 4613   } | 
| 4617 | 4614 | 
| 4618   if (it->IsElement()) { | 4615   if (it->IsElement()) { | 
| 4619     if (receiver->IsJSArray()) { | 4616     if (receiver->IsJSArray()) { | 
| 4620       Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 4617       Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 
| 4621       if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { | 4618       if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { | 
| 4622         RETURN_FAILURE(array->GetIsolate(), should_throw, | 4619         RETURN_FAILURE(array->GetIsolate(), should_throw, | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 4635       } | 4632       } | 
| 4636     } | 4633     } | 
| 4637 | 4634 | 
| 4638     Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value, | 4635     Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value, | 
| 4639                                                   attributes, should_throw); | 4636                                                   attributes, should_throw); | 
| 4640     JSObject::ValidateElements(receiver); | 4637     JSObject::ValidateElements(receiver); | 
| 4641     return result; | 4638     return result; | 
| 4642   } else { | 4639   } else { | 
| 4643     // Migrate to the most up-to-date map that will be able to store |value| | 4640     // Migrate to the most up-to-date map that will be able to store |value| | 
| 4644     // under it->name() with |attributes|. | 4641     // under it->name() with |attributes|. | 
| 4645     it->PrepareTransitionToDataProperty(value, attributes, store_mode); | 4642     it->PrepareTransitionToDataProperty(receiver, value, attributes, | 
|  | 4643                                         store_mode); | 
| 4646     DCHECK_EQ(LookupIterator::TRANSITION, it->state()); | 4644     DCHECK_EQ(LookupIterator::TRANSITION, it->state()); | 
| 4647     it->ApplyTransitionToDataProperty(); | 4645     it->ApplyTransitionToDataProperty(receiver); | 
| 4648 | 4646 | 
| 4649     // TODO(verwaest): Encapsulate dictionary handling better. | 4647     // TODO(verwaest): Encapsulate dictionary handling better. | 
| 4650     if (receiver->map()->is_dictionary_map()) { | 4648     if (receiver->map()->is_dictionary_map()) { | 
| 4651       // TODO(verwaest): Probably should ensure this is done beforehand. | 4649       // TODO(verwaest): Probably should ensure this is done beforehand. | 
| 4652       it->InternalizeName(); | 4650       it->InternalizeName(); | 
| 4653       // TODO(dcarney): just populate TransitionPropertyCell here? | 4651       // TODO(dcarney): just populate TransitionPropertyCell here? | 
| 4654       JSObject::AddSlowProperty(receiver, it->name(), value, attributes); | 4652       JSObject::AddSlowProperty(receiver, it->name(), value, attributes); | 
| 4655     } else { | 4653     } else { | 
| 4656       // Write the property value. | 4654       // Write the property value. | 
| 4657       it->WriteDataValue(value); | 4655       it->WriteDataValue(value); | 
| (...skipping 5265 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 | 
|---|