Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 403b470edf638435f638f19e805e04276638bad5..bcceb841af0738578ff770cc0fdf61d5561dce9a 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; |
@@ -4608,7 +4629,7 @@ Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) { |
it->PrepareForDataProperty(to_assign); |
// Write the property value. |
- it->WriteDataValue(to_assign); |
+ it->WriteDataValue(to_assign, false); |
#if VERIFY_HEAP |
if (FLAG_verify_heap) { |
@@ -4682,7 +4703,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 +5737,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 +5814,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 +7032,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 +9185,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 +9202,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 +9216,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 +9230,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 +9240,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 +9274,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 +9331,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; |
} |