Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 403b470edf638435f638f19e805e04276638bad5..02d518f1b33ca7e80d73325f93515f972ef6dffa 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -3368,6 +3368,7 @@ FieldType* Map::UnwrapFieldType(Object* wrapped_type) { |
| MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name, |
| Handle<FieldType> type, |
| PropertyAttributes attributes, |
| + PropertyConstness constness, |
| Representation representation, |
| TransitionFlag flag) { |
| DCHECK(DescriptorArray::kNotFound == |
| @@ -3391,7 +3392,8 @@ MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name, |
| Handle<Object> wrapped_type(WrapFieldType(type)); |
| - Descriptor d = Descriptor::DataField(name, index, attributes, kMutable, |
| + DCHECK_IMPLIES(!FLAG_track_constant_fields, constness == kMutable); |
| + Descriptor d = Descriptor::DataField(name, index, attributes, constness, |
| representation, wrapped_type); |
| Handle<Map> new_map = Map::CopyAddDescriptor(map, &d, flag); |
| int unused_property_fields = new_map->unused_property_fields() - 1; |
| @@ -3413,9 +3415,18 @@ MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map, |
| return MaybeHandle<Map>(); |
| } |
| - // Allocate new instance descriptors with (name, constant) added. |
| - Descriptor d = Descriptor::DataConstant(name, constant, attributes); |
| - return Map::CopyAddDescriptor(map, &d, flag); |
| + if (FLAG_track_constant_fields) { |
| + Isolate* isolate = map->GetIsolate(); |
| + Representation representation = constant->OptimalRepresentation(); |
| + Handle<FieldType> type = constant->OptimalType(isolate, representation); |
| + return CopyWithField(map, name, type, attributes, kConst, representation, |
| + flag); |
| + } else { |
| + // Allocate new instance descriptors with (name, constant) added. |
| + Descriptor d = Descriptor::DataConstant(name, 0, constant, attributes); |
| + Handle<Map> new_map = Map::CopyAddDescriptor(map, &d, flag); |
| + return new_map; |
| + } |
| } |
| const char* Representation::Mnemonic() const { |
| @@ -3923,6 +3934,7 @@ void DescriptorArray::GeneralizeAllFields() { |
| details = details.CopyWithRepresentation(Representation::Tagged()); |
| if (details.location() == kField) { |
| DCHECK_EQ(kData, details.kind()); |
| + details = details.CopyWithConstness(kMutable); |
| SetValue(i, FieldType::Any()); |
| } |
| set(ToDetailsIndex(i), details.AsSmi()); |
| @@ -3950,7 +3962,8 @@ Handle<Map> Map::CopyGeneralizeAllFields(Handle<Map> map, |
| // Unless the instance is being migrated, ensure that modify_index is a field. |
| if (modify_index >= 0) { |
| PropertyDetails details = descriptors->GetDetails(modify_index); |
| - if (details.location() != kField || details.attributes() != attributes) { |
| + if (details.constness() != kMutable || details.location() != kField || |
| + details.attributes() != attributes) { |
| int field_index = details.location() == kField |
| ? details.field_index() |
| : new_map->NumberOfFields(); |
| @@ -4059,8 +4072,8 @@ Map* Map::FindFieldOwner(int descriptor) { |
| return result; |
| } |
| - |
| void Map::UpdateFieldType(int descriptor, Handle<Name> name, |
| + PropertyConstness new_constness, |
| Representation new_representation, |
| Handle<Object> new_wrapped_type) { |
| DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell()); |
| @@ -4087,15 +4100,19 @@ void Map::UpdateFieldType(int descriptor, Handle<Name> name, |
| DescriptorArray* descriptors = current->instance_descriptors(); |
| PropertyDetails details = descriptors->GetDetails(descriptor); |
| + // Currently constness change implies map change. |
| + DCHECK_EQ(new_constness, details.constness()); |
| + |
| // It is allowed to change representation here only from None to something. |
| DCHECK(details.representation().Equals(new_representation) || |
| details.representation().IsNone()); |
| // Skip if already updated the shared descriptor. |
| if (descriptors->GetValue(descriptor) != *new_wrapped_type) { |
| + DCHECK_IMPLIES(!FLAG_track_constant_fields, new_constness == kMutable); |
| Descriptor d = Descriptor::DataField( |
| name, descriptors->GetFieldIndex(descriptor), details.attributes(), |
| - kMutable, new_representation, new_wrapped_type); |
| + new_constness, new_representation, new_wrapped_type); |
| descriptors->Replace(descriptor, &d); |
| } |
| } |
| @@ -4126,18 +4143,21 @@ Handle<FieldType> Map::GeneralizeFieldType(Representation rep1, |
| // static |
| void Map::GeneralizeField(Handle<Map> map, int modify_index, |
| + PropertyConstness new_constness, |
| Representation new_representation, |
| Handle<FieldType> new_field_type) { |
| Isolate* isolate = map->GetIsolate(); |
| // Check if we actually need to generalize the field type at all. |
| Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); |
| - Representation old_representation = |
| - old_descriptors->GetDetails(modify_index).representation(); |
| + PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| + PropertyConstness old_constness = old_details.constness(); |
| + Representation old_representation = old_details.representation(); |
| Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index), |
| isolate); |
| - if (old_representation.Equals(new_representation) && |
| + if (old_constness == new_constness && |
| + old_representation.Equals(new_representation) && |
| !FieldTypeIsCleared(new_representation, *new_field_type) && |
| // Checking old_field_type for being cleared is not necessary because |
| // the NowIs check below would fail anyway in that case. |
| @@ -4162,8 +4182,8 @@ void Map::GeneralizeField(Handle<Map> map, int modify_index, |
| Handle<Name> name(descriptors->GetKey(modify_index)); |
| Handle<Object> wrapped_type(WrapFieldType(new_field_type)); |
| - field_owner->UpdateFieldType(modify_index, name, new_representation, |
| - wrapped_type); |
| + field_owner->UpdateFieldType(modify_index, name, new_constness, |
| + new_representation, wrapped_type); |
| field_owner->dependent_code()->DeoptimizeDependentCodeGroup( |
| isolate, DependentCode::kFieldOwnerGroup); |
| @@ -4185,7 +4205,7 @@ Handle<Map> Map::ReconfigureProperty(Handle<Map> map, int modify_index, |
| Handle<FieldType> new_field_type) { |
| DCHECK_EQ(kData, new_kind); // Only kData case is supported. |
| MapUpdater mu(map->GetIsolate(), map); |
| - return mu.ReconfigureToDataField(modify_index, new_attributes, |
| + return mu.ReconfigureToDataField(modify_index, new_attributes, kConst, |
| new_representation, new_field_type); |
| } |
| @@ -4208,7 +4228,7 @@ Handle<Map> Map::GeneralizeAllFields(Handle<Map> map) { |
| if (details.location() == kField) { |
| DCHECK_EQ(kData, details.kind()); |
| MapUpdater mu(isolate, map); |
| - map = mu.ReconfigureToDataField(i, details.attributes(), |
| + map = mu.ReconfigureToDataField(i, details.attributes(), kMutable, |
| Representation::Tagged(), any_type); |
| } |
| } |
| @@ -4286,6 +4306,7 @@ Map* Map::TryReplayPropertyTransitions(Map* old_map) { |
| } |
| } else { |
| DCHECK_EQ(kDescriptor, old_details.location()); |
| + DCHECK(!FLAG_track_constant_fields); |
| Object* old_value = old_descriptors->GetValue(i); |
| if (!new_type->NowContains(old_value)) { |
| return nullptr; |
| @@ -4603,12 +4624,17 @@ Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) { |
| } |
| } |
| + // If we are initializing a computed property of an object literal then the |
| + // property is guaranteed to be present but the value is not initialized yet. |
| + // Therefore the full initializing store is required. |
| + bool is_initializing_store = it->IsInitializingStoreRequired(); |
|
Toon Verwaest
2017/02/09 16:06:09
I'm not sure this is necessary (anymore?)
Igor Sheludko
2017/02/09 17:08:13
Indeed.
|
| + |
| // Possibly migrate to the most up-to-date map that will be able to store |
| // |value| under it->name(). |
| it->PrepareForDataProperty(to_assign); |
| // Write the property value. |
| - it->WriteDataValue(to_assign); |
| + it->WriteDataValue(to_assign, is_initializing_store); |
|
Igor Sheludko
2017/02/09 17:08:14
But the "initializing_store" parameter is still ne
|
| #if VERIFY_HEAP |
| if (FLAG_verify_heap) { |
| @@ -4682,7 +4708,7 @@ Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value, |
| it->ApplyTransitionToDataProperty(receiver); |
| // Write the property value. |
| - it->WriteDataValue(value); |
| + it->WriteDataValue(value, true); |
| #if VERIFY_HEAP |
| if (FLAG_verify_heap) { |
| @@ -5716,9 +5742,13 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object, |
| PropertyKind kind = dictionary->DetailsAt(index).kind(); |
| if (kind == kData) { |
| - Object* value = dictionary->ValueAt(index); |
| - if (!value->IsJSFunction()) { |
| + if (FLAG_track_constant_fields) { |
| number_of_fields += 1; |
| + } else { |
| + Object* value = dictionary->ValueAt(index); |
| + if (!value->IsJSFunction()) { |
| + number_of_fields += 1; |
| + } |
| } |
| } |
| } |
| @@ -5789,14 +5819,14 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object, |
| Descriptor d; |
| if (details.kind() == kData) { |
| - if (value->IsJSFunction()) { |
| + if (!FLAG_track_constant_fields && value->IsJSFunction()) { |
| d = Descriptor::DataConstant(key, handle(value, isolate), |
| details.attributes()); |
| } else { |
| d = Descriptor::DataField( |
| - key, current_offset, details.attributes(), |
| + key, current_offset, details.attributes(), kDefaultFieldConstness, |
| // TODO(verwaest): value->OptimalRepresentation(); |
| - Representation::Tagged()); |
| + Representation::Tagged(), FieldType::Any(isolate)); |
| } |
| } else { |
| DCHECK_EQ(kAccessor, details.kind()); |
| @@ -7007,7 +7037,7 @@ Maybe<bool> JSProxy::SetPrivateProperty(Isolate* isolate, Handle<JSProxy> proxy, |
| if (it.IsFound()) { |
| DCHECK_EQ(LookupIterator::DATA, it.state()); |
| DCHECK_EQ(DONT_ENUM, it.property_attributes()); |
| - it.WriteDataValue(value); |
| + it.WriteDataValue(value, false); |
| return Just(true); |
| } |
| @@ -9160,16 +9190,16 @@ Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map, |
| namespace { |
| -bool CanHoldValue(DescriptorArray* descriptors, int descriptor, Object* value) { |
| +bool CanHoldValue(DescriptorArray* descriptors, int descriptor, |
| + PropertyConstness constness, Object* value) { |
| PropertyDetails details = descriptors->GetDetails(descriptor); |
| if (details.location() == kField) { |
| - DCHECK_EQ(kMutable, details.constness()); |
| if (details.kind() == kData) { |
| - return value->FitsRepresentation(details.representation()) && |
| + return IsGeneralizableTo(constness, details.constness()) && |
| + value->FitsRepresentation(details.representation()) && |
| descriptors->GetFieldType(descriptor)->NowContains(value); |
| } else { |
| DCHECK_EQ(kAccessor, details.kind()); |
| - UNREACHABLE(); |
| return false; |
| } |
| @@ -9177,6 +9207,7 @@ bool CanHoldValue(DescriptorArray* descriptors, int descriptor, Object* value) { |
| DCHECK_EQ(kDescriptor, details.location()); |
| DCHECK_EQ(kConst, details.constness()); |
| if (details.kind() == kData) { |
| + DCHECK(!FLAG_track_constant_fields); |
| DCHECK(descriptors->GetValue(descriptor) != value || |
| value->FitsRepresentation(details.representation())); |
| return descriptors->GetValue(descriptor) == value; |
| @@ -9190,8 +9221,12 @@ bool CanHoldValue(DescriptorArray* descriptors, int descriptor, Object* value) { |
| } |
| Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor, |
| + PropertyConstness constness, |
| Handle<Object> value) { |
| - if (CanHoldValue(map->instance_descriptors(), descriptor, *value)) return map; |
| + if (CanHoldValue(map->instance_descriptors(), descriptor, constness, |
| + *value)) { |
| + return map; |
| + } |
| Isolate* isolate = map->GetIsolate(); |
| PropertyAttributes attributes = |
| @@ -9200,8 +9235,8 @@ Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor, |
| Handle<FieldType> type = value->OptimalType(isolate, representation); |
| MapUpdater mu(isolate, map); |
| - Handle<Map> new_map = |
| - mu.ReconfigureToDataField(descriptor, attributes, representation, type); |
| + Handle<Map> new_map = mu.ReconfigureToDataField( |
| + descriptor, attributes, constness, representation, type); |
| new_map->set_migration_target(true); |
| return new_map; |
| } |
| @@ -9210,17 +9245,18 @@ Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor, |
| // static |
| Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, |
| + PropertyConstness constness, |
| Handle<Object> value) { |
| // Dictionaries can store any property value. |
| DCHECK(!map->is_dictionary_map()); |
| // Update to the newest map before storing the property. |
| - return UpdateDescriptorForValue(Update(map), descriptor, value); |
| + return UpdateDescriptorForValue(Update(map), descriptor, constness, value); |
| } |
| - |
| Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
| Handle<Object> value, |
| PropertyAttributes attributes, |
| + PropertyConstness constness, |
| StoreFromKeyed store_mode) { |
| RuntimeCallTimerScope stats_scope( |
| *map, map->is_prototype_map() |
| @@ -9243,19 +9279,19 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
| ->GetDetails(descriptor) |
| .attributes()); |
| - return UpdateDescriptorForValue(transition, descriptor, value); |
| + return UpdateDescriptorForValue(transition, descriptor, constness, value); |
| } |
| TransitionFlag flag = INSERT_TRANSITION; |
| MaybeHandle<Map> maybe_map; |
| - if (value->IsJSFunction()) { |
| + if (!FLAG_track_constant_fields && value->IsJSFunction()) { |
| maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); |
| } else if (!map->TooManyFastProperties(store_mode)) { |
| Isolate* isolate = name->GetIsolate(); |
| Representation representation = value->OptimalRepresentation(); |
| Handle<FieldType> type = value->OptimalType(isolate, representation); |
| - maybe_map = |
| - Map::CopyWithField(map, name, type, attributes, representation, flag); |
| + maybe_map = Map::CopyWithField(map, name, type, attributes, constness, |
| + representation, flag); |
| } |
| Handle<Map> result; |
| @@ -9300,7 +9336,8 @@ Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor, |
| MapUpdater mu(isolate, map); |
| DCHECK_EQ(kData, kind); // Only kData case is supported so far. |
| Handle<Map> new_map = mu.ReconfigureToDataField( |
| - descriptor, attributes, Representation::None(), FieldType::None(isolate)); |
| + descriptor, attributes, kDefaultFieldConstness, Representation::None(), |
| + FieldType::None(isolate)); |
| return new_map; |
| } |