| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index a7a5c480f32cb374fcf43d6b4f9c02422684e382..680abc36ab24be64b8829aeba96155b647f98541 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -3164,32 +3164,30 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
|
| // respective prototypes.
|
| UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate());
|
|
|
| - if (object->HasFastProperties()) {
|
| - if (!new_map->is_dictionary_map()) {
|
| - MigrateFastToFast(object, new_map);
|
| - if (old_map->is_prototype_map()) {
|
| - DCHECK(!old_map->is_stable());
|
| - DCHECK(new_map->is_stable());
|
| - // Clear out the old descriptor array to avoid problems to sharing
|
| - // the descriptor array without using an explicit.
|
| - old_map->InitializeDescriptors(
|
| - old_map->GetHeap()->empty_descriptor_array(),
|
| - LayoutDescriptor::FastPointerLayout());
|
| - // Ensure that no transition was inserted for prototype migrations.
|
| - DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
|
| - old_map->raw_transitions()));
|
| - DCHECK(new_map->GetBackPointer()->IsUndefined());
|
| - }
|
| - } else {
|
| - MigrateFastToSlow(object, new_map, expected_additional_properties);
|
| - }
|
| - } else {
|
| + if (old_map->is_dictionary_map()) {
|
| // For slow-to-fast migrations JSObject::MigrateSlowToFast()
|
| // must be used instead.
|
| CHECK(new_map->is_dictionary_map());
|
|
|
| // Slow-to-slow migration is trivial.
|
| object->set_map(*new_map);
|
| + } else if (!new_map->is_dictionary_map()) {
|
| + MigrateFastToFast(object, new_map);
|
| + if (old_map->is_prototype_map()) {
|
| + DCHECK(!old_map->is_stable());
|
| + DCHECK(new_map->is_stable());
|
| + // Clear out the old descriptor array to avoid problems to sharing
|
| + // the descriptor array without using an explicit.
|
| + old_map->InitializeDescriptors(
|
| + old_map->GetHeap()->empty_descriptor_array(),
|
| + LayoutDescriptor::FastPointerLayout());
|
| + // Ensure that no transition was inserted for prototype migrations.
|
| + DCHECK_EQ(
|
| + 0, TransitionArray::NumberOfTransitions(old_map->raw_transitions()));
|
| + DCHECK(new_map->GetBackPointer()->IsUndefined());
|
| + }
|
| + } else {
|
| + MigrateFastToSlow(object, new_map, expected_additional_properties);
|
| }
|
|
|
| // Careful: Don't allocate here!
|
| @@ -4608,8 +4606,7 @@ Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
|
|
|
| Isolate* isolate = it->isolate();
|
|
|
| - if (!receiver->map()->is_extensible() &&
|
| - (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) {
|
| + if (it->ExtendingNonExtensible(receiver)) {
|
| RETURN_FAILURE(
|
| isolate, should_throw,
|
| NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
|
| @@ -4642,9 +4639,10 @@ Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
|
| } else {
|
| // Migrate to the most up-to-date map that will be able to store |value|
|
| // under it->name() with |attributes|.
|
| - it->PrepareTransitionToDataProperty(value, attributes, store_mode);
|
| + it->PrepareTransitionToDataProperty(receiver, value, attributes,
|
| + store_mode);
|
| DCHECK_EQ(LookupIterator::TRANSITION, it->state());
|
| - it->ApplyTransitionToDataProperty();
|
| + it->ApplyTransitionToDataProperty(receiver);
|
|
|
| // TODO(verwaest): Encapsulate dictionary handling better.
|
| if (receiver->map()->is_dictionary_map()) {
|
| @@ -9930,28 +9928,32 @@ bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
|
| return false;
|
| }
|
|
|
| +namespace {
|
|
|
| -// static
|
| -Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
|
| - Handle<Object> value) {
|
| - // Dictionaries can store any property value.
|
| - if (map->is_dictionary_map()) return map;
|
| -
|
| - // Migrate to the newest map before storing the property.
|
| - map = Update(map);
|
| -
|
| - Handle<DescriptorArray> descriptors(map->instance_descriptors());
|
| -
|
| - if (descriptors->CanHoldValue(descriptor, *value)) return map;
|
| +Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor,
|
| + Handle<Object> value) {
|
| + if (map->instance_descriptors()->CanHoldValue(descriptor, *value)) return map;
|
|
|
| Isolate* isolate = map->GetIsolate();
|
| PropertyAttributes attributes =
|
| - descriptors->GetDetails(descriptor).attributes();
|
| + map->instance_descriptors()->GetDetails(descriptor).attributes();
|
| Representation representation = value->OptimalRepresentation();
|
| Handle<FieldType> type = value->OptimalType(isolate, representation);
|
|
|
| - return ReconfigureProperty(map, descriptor, kData, attributes, representation,
|
| - type, FORCE_FIELD);
|
| + return Map::ReconfigureProperty(map, descriptor, kData, attributes,
|
| + representation, type, FORCE_FIELD);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
|
| + Handle<Object> value) {
|
| + // Dictionaries can store any property value.
|
| + if (map->is_dictionary_map()) return map;
|
| +
|
| + // Update to the newest map before storing the property.
|
| + return UpdateDescriptorForValue(Update(map), descriptor, value);
|
| }
|
|
|
|
|
| @@ -9975,7 +9977,7 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
|
| ->GetDetails(descriptor)
|
| .attributes());
|
|
|
| - return Map::PrepareForDataProperty(transition, descriptor, value);
|
| + return UpdateDescriptorForValue(transition, descriptor, value);
|
| }
|
|
|
| TransitionFlag flag = INSERT_TRANSITION;
|
|
|