| 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;
|
|
|