Index: src/compiler/property-access-info.cc |
diff --git a/src/compiler/property-access-info.cc b/src/compiler/property-access-info.cc |
index 45c0784f6e9dc3b7cef8911890063d9f6adfcedd..4b2afb602fce25929cc89ecffa132eb3f8583e34 100644 |
--- a/src/compiler/property-access-info.cc |
+++ b/src/compiler/property-access-info.cc |
@@ -87,39 +87,11 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
// Compute the receiver type. |
Handle<Map> receiver_map = map; |
- Type* receiver_type = Type::Class(receiver_map, zone()); |
// We support fast inline cases for certain JSObject getters. |
- if (access_mode == PropertyAccessMode::kLoad) { |
- // Check for special JSObject field accessors. |
- int offset; |
- if (Accessors::IsJSObjectFieldAccessor(map, name, &offset)) { |
- FieldIndex field_index = FieldIndex::ForInObjectOffset(offset); |
- Type* field_type = Type::Tagged(); |
- if (map->IsStringMap()) { |
- DCHECK(Name::Equals(factory()->length_string(), name)); |
- // The String::length property is always a smi in the range |
- // [0, String::kMaxLength]. |
- field_type = type_cache_.kStringLengthType; |
- } else if (map->IsJSArrayMap()) { |
- DCHECK(Name::Equals(factory()->length_string(), name)); |
- // The JSArray::length property is a smi in the range |
- // [0, FixedDoubleArray::kMaxLength] in case of fast double |
- // elements, a smi in the range [0, FixedArray::kMaxLength] |
- // in case of other fast elements, and [0, kMaxUInt32] in |
- // case of other arrays. |
- if (IsFastDoubleElementsKind(map->elements_kind())) { |
- field_type = type_cache_.kFixedDoubleArrayLengthType; |
- } else if (IsFastElementsKind(map->elements_kind())) { |
- field_type = type_cache_.kFixedArrayLengthType; |
- } else { |
- field_type = type_cache_.kJSArrayLengthType; |
- } |
- } |
- *access_info = |
- PropertyAccessInfo::DataField(receiver_type, field_index, field_type); |
- return true; |
- } |
+ if (access_mode == PropertyAccessMode::kLoad && |
+ LookupSpecialFieldAccessor(map, name, access_info)) { |
+ return true; |
} |
MaybeHandle<JSObject> holder; |
@@ -136,16 +108,16 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
} |
// Check for store to data property on a prototype. |
if (details.kind() == kData && !holder.is_null()) { |
- // We need to add the data field to the receiver. Leave the loop |
- // and check whether we already have a transition for this field. |
+ // Store to property not found on the receiver but on a prototype, we |
+ // need to transition to a new data property. |
// Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver) |
- break; |
+ return LookupTransition(receiver_map, name, holder, access_info); |
} |
} |
if (details.type() == DATA_CONSTANT) { |
*access_info = PropertyAccessInfo::DataConstant( |
- receiver_type, handle(descriptors->GetValue(number), isolate()), |
- holder); |
+ Type::Class(receiver_map, zone()), |
+ handle(descriptors->GetValue(number), isolate()), holder); |
return true; |
} else if (details.type() == DATA) { |
int index = descriptors->GetFieldIndex(number); |
@@ -180,8 +152,8 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
} |
DCHECK(field_type->Is(Type::TaggedPointer())); |
} |
- *access_info = PropertyAccessInfo::DataField(receiver_type, field_index, |
- field_type, holder); |
+ *access_info = PropertyAccessInfo::DataField( |
+ Type::Class(receiver_map, zone()), field_index, field_type, holder); |
return true; |
} else { |
// TODO(bmeurer): Add support for accessors. |
@@ -213,7 +185,7 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
// to transition to a new data property. |
// Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver) |
if (access_mode == PropertyAccessMode::kStore) { |
- break; |
+ return LookupTransition(receiver_map, name, holder, access_info); |
} |
// TODO(bmeurer): Handle the not found case if the prototype is null. |
return false; |
@@ -233,13 +205,53 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
// Check if it is safe to inline property access for the {map}. |
if (!CanInlinePropertyAccess(map)) return false; |
} |
- DCHECK_EQ(PropertyAccessMode::kStore, access_mode); |
+ return false; |
+} |
+ |
- // Check if the {receiver_map} has a data transition with the given {name}. |
- if (receiver_map->unused_property_fields() == 0) return false; |
- if (Map* transition = TransitionArray::SearchTransition(*receiver_map, kData, |
- *name, NONE)) { |
- Handle<Map> transition_map(transition, isolate()); |
+bool PropertyAccessInfoFactory::LookupSpecialFieldAccessor( |
+ Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { |
+ // Check for special JSObject field accessors. |
+ int offset; |
+ if (Accessors::IsJSObjectFieldAccessor(map, name, &offset)) { |
+ FieldIndex field_index = FieldIndex::ForInObjectOffset(offset); |
+ Type* field_type = Type::Tagged(); |
+ if (map->IsStringMap()) { |
+ DCHECK(Name::Equals(factory()->length_string(), name)); |
+ // The String::length property is always a smi in the range |
+ // [0, String::kMaxLength]. |
+ field_type = type_cache_.kStringLengthType; |
+ } else if (map->IsJSArrayMap()) { |
+ DCHECK(Name::Equals(factory()->length_string(), name)); |
+ // The JSArray::length property is a smi in the range |
+ // [0, FixedDoubleArray::kMaxLength] in case of fast double |
+ // elements, a smi in the range [0, FixedArray::kMaxLength] |
+ // in case of other fast elements, and [0, kMaxUInt32] in |
+ // case of other arrays. |
+ if (IsFastDoubleElementsKind(map->elements_kind())) { |
+ field_type = type_cache_.kFixedDoubleArrayLengthType; |
+ } else if (IsFastElementsKind(map->elements_kind())) { |
+ field_type = type_cache_.kFixedArrayLengthType; |
+ } else { |
+ field_type = type_cache_.kJSArrayLengthType; |
+ } |
+ } |
+ *access_info = PropertyAccessInfo::DataField(Type::Class(map, zone()), |
+ field_index, field_type); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+ |
+bool PropertyAccessInfoFactory::LookupTransition( |
+ Handle<Map> map, Handle<Name> name, MaybeHandle<JSObject> holder, |
+ PropertyAccessInfo* access_info) { |
+ // Check if the {map} has a data transition with the given {name}. |
+ if (map->unused_property_fields() == 0) return false; |
+ Handle<Map> transition_map; |
+ if (TransitionArray::SearchTransition(map, kData, name, NONE) |
+ .ToHandle(&transition_map)) { |
int const number = transition_map->LastAdded(); |
PropertyDetails const details = |
transition_map->instance_descriptors()->GetDetails(number); |
@@ -255,8 +267,7 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
if (field_representation.IsSmi()) { |
field_type = type_cache_.kSmi; |
} else if (field_representation.IsDouble()) { |
- // TODO(bmeurer): Add support for storing to double fields. |
- return false; |
+ field_type = type_cache_.kFloat64; |
} else if (field_representation.IsHeapObject()) { |
// Extract the field type from the property details (make sure its |
// representation is TaggedPointer to reflect the heap object case). |
@@ -279,8 +290,9 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
DCHECK(field_type->Is(Type::TaggedPointer())); |
} |
dependencies()->AssumeMapNotDeprecated(transition_map); |
- *access_info = PropertyAccessInfo::DataField( |
- receiver_type, field_index, field_type, holder, transition_map); |
+ *access_info = |
+ PropertyAccessInfo::DataField(Type::Class(map, zone()), field_index, |
+ field_type, holder, transition_map); |
return true; |
} |
return false; |