| Index: src/compiler/js-native-context-specialization.cc
|
| diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
|
| index 45b9061579c805175e69f79b0600f4072ced1264..0bd131960ef34e77c2f8da96d945725b331d6b9a 100644
|
| --- a/src/compiler/js-native-context-specialization.cc
|
| +++ b/src/compiler/js-native-context-specialization.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "src/compiler/js-native-context-specialization.h"
|
|
|
| +#include "src/accessors.h"
|
| #include "src/compilation-dependencies.h"
|
| #include "src/compiler/access-builder.h"
|
| #include "src/compiler/js-graph.h"
|
| @@ -249,9 +250,10 @@ class JSNativeContextSpecialization::PropertyAccessInfo final {
|
| }
|
| static PropertyAccessInfo Data(Type* receiver_type, FieldIndex field_index,
|
| Representation field_representation,
|
| + Type* field_type,
|
| MaybeHandle<JSObject> holder) {
|
| return PropertyAccessInfo(holder, field_index, field_representation,
|
| - receiver_type);
|
| + field_type, receiver_type);
|
| }
|
|
|
| PropertyAccessInfo() : kind_(kInvalid) {}
|
| @@ -262,12 +264,14 @@ class JSNativeContextSpecialization::PropertyAccessInfo final {
|
| constant_(constant),
|
| holder_(holder) {}
|
| PropertyAccessInfo(MaybeHandle<JSObject> holder, FieldIndex field_index,
|
| - Representation field_representation, Type* receiver_type)
|
| + Representation field_representation, Type* field_type,
|
| + Type* receiver_type)
|
| : kind_(kData),
|
| receiver_type_(receiver_type),
|
| holder_(holder),
|
| field_index_(field_index),
|
| - field_representation_(field_representation) {}
|
| + field_representation_(field_representation),
|
| + field_type_(field_type) {}
|
|
|
| bool IsDataConstant() const { return kind() == kDataConstant; }
|
| bool IsData() const { return kind() == kData; }
|
| @@ -277,6 +281,7 @@ class JSNativeContextSpecialization::PropertyAccessInfo final {
|
| Handle<Object> constant() const { return constant_; }
|
| FieldIndex field_index() const { return field_index_; }
|
| Representation field_representation() const { return field_representation_; }
|
| + Type* field_type() const { return field_type_; }
|
| Type* receiver_type() const { return receiver_type_; }
|
|
|
| private:
|
| @@ -286,6 +291,7 @@ class JSNativeContextSpecialization::PropertyAccessInfo final {
|
| MaybeHandle<JSObject> holder_;
|
| FieldIndex field_index_;
|
| Representation field_representation_;
|
| + Type* field_type_ = Type::Any();
|
| };
|
|
|
|
|
| @@ -307,8 +313,47 @@ bool CanInlinePropertyAccess(Handle<Map> map) {
|
| bool JSNativeContextSpecialization::ComputePropertyAccessInfo(
|
| Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) {
|
| MaybeHandle<JSObject> holder;
|
| - Type* receiver_type = Type::Class(map, graph()->zone());
|
| + Handle<Map> receiver_map = map;
|
| + Type* receiver_type = Type::Class(receiver_map, graph()->zone());
|
| while (CanInlinePropertyAccess(map)) {
|
| + // Check for special JSObject field accessors.
|
| + int offset;
|
| + if (Accessors::IsJSObjectFieldAccessor(map, name, &offset)) {
|
| + FieldIndex field_index = FieldIndex::ForInObjectOffset(offset);
|
| + Representation field_representation = Representation::Tagged();
|
| + Type* field_type = Type::Tagged();
|
| + if (receiver_type->Is(Type::String())) {
|
| + DCHECK(Name::Equals(factory()->length_string(), name));
|
| + // The String::length property is always a smi in the range
|
| + // [0, String::kMaxLength].
|
| + field_representation = Representation::Smi();
|
| + field_type = Type::Intersect(
|
| + Type::Range(0.0, String::kMaxLength, graph()->zone()),
|
| + Type::TaggedSigned(), graph()->zone());
|
| + } else if (receiver_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-1] in
|
| + // case of other arrays.
|
| + double field_type_upper = kMaxUInt32 - 1;
|
| + if (IsFastElementsKind(receiver_map->elements_kind())) {
|
| + field_representation = Representation::Smi();
|
| + field_type_upper =
|
| + IsFastDoubleElementsKind(receiver_map->elements_kind())
|
| + ? FixedDoubleArray::kMaxLength
|
| + : FixedArray::kMaxLength;
|
| + }
|
| + field_type =
|
| + Type::Intersect(Type::Range(0.0, field_type_upper, graph()->zone()),
|
| + Type::TaggedSigned(), graph()->zone());
|
| + }
|
| + *access_info = PropertyAccessInfo::Data(
|
| + receiver_type, field_index, field_representation, field_type, holder);
|
| + return true;
|
| + }
|
| +
|
| // Lookup the named property on the {map}.
|
| Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
|
| int const number = descriptors->SearchWithCache(*name, *map);
|
| @@ -324,8 +369,19 @@ bool JSNativeContextSpecialization::ComputePropertyAccessInfo(
|
| Representation field_representation = details.representation();
|
| FieldIndex field_index = FieldIndex::ForPropertyIndex(
|
| *map, index, field_representation.IsDouble());
|
| - *access_info = PropertyAccessInfo::Data(receiver_type, field_index,
|
| - field_representation, holder);
|
| + Type* field_type = Type::Any();
|
| + if (field_representation.IsSmi()) {
|
| + field_type = Type::Intersect(Type::SignedSmall(),
|
| + Type::TaggedSigned(), graph()->zone());
|
| + } else if (field_representation.IsDouble()) {
|
| + field_type = Type::Intersect(Type::Number(), Type::UntaggedFloat64(),
|
| + graph()->zone());
|
| + } else if (field_representation.IsHeapObject()) {
|
| + field_type = Type::TaggedPointer();
|
| + }
|
| + *access_info =
|
| + PropertyAccessInfo::Data(receiver_type, field_index,
|
| + field_representation, field_type, holder);
|
| return true;
|
| } else {
|
| // TODO(bmeurer): Add support for accessors.
|
| @@ -510,6 +566,7 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
|
| FieldIndex const field_index = access_info.field_index();
|
| Representation const field_representation =
|
| access_info.field_representation();
|
| + Type* const field_type = access_info.field_type();
|
| if (!field_index.is_inobject()) {
|
| this_value = this_effect = graph()->NewNode(
|
| simplified()->LoadField(AccessBuilder::ForJSObjectProperties()),
|
| @@ -519,12 +576,9 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
|
| field_access.base_is_tagged = kTaggedBase;
|
| field_access.offset = field_index.offset();
|
| field_access.name = name;
|
| - field_access.type = Type::Any();
|
| + field_access.type = field_type;
|
| field_access.machine_type = kMachAnyTagged;
|
| - if (field_representation.IsSmi()) {
|
| - field_access.type = Type::Intersect(
|
| - Type::SignedSmall(), Type::TaggedSigned(), graph()->zone());
|
| - } else if (field_representation.IsDouble()) {
|
| + if (field_representation.IsDouble()) {
|
| if (!field_index.is_inobject() || field_index.is_hidden_field() ||
|
| !FLAG_unbox_double_fields) {
|
| this_value = this_effect =
|
| @@ -533,11 +587,7 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
|
| field_access.offset = HeapNumber::kValueOffset;
|
| field_access.name = MaybeHandle<Name>();
|
| }
|
| - field_access.type = Type::Intersect(
|
| - Type::Number(), Type::UntaggedFloat64(), graph()->zone());
|
| field_access.machine_type = kMachFloat64;
|
| - } else if (field_representation.IsHeapObject()) {
|
| - field_access.type = Type::TaggedPointer();
|
| }
|
| this_value = this_effect =
|
| graph()->NewNode(simplified()->LoadField(field_access), this_value,
|
| @@ -640,6 +690,11 @@ Isolate* JSNativeContextSpecialization::isolate() const {
|
| }
|
|
|
|
|
| +Factory* JSNativeContextSpecialization::factory() const {
|
| + return isolate()->factory();
|
| +}
|
| +
|
| +
|
| MachineOperatorBuilder* JSNativeContextSpecialization::machine() const {
|
| return jsgraph()->machine();
|
| }
|
|
|