1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_ACCESS_INFO_H_
6#define V8_COMPILER_ACCESS_INFO_H_
7
8#include <iosfwd>
9
10#include "src/field-index.h"
11#include "src/machine-type.h"
12#include "src/objects.h"
13#include "src/zone/zone-containers.h"
14
15namespace v8 {
16namespace internal {
17
18// Forward declarations.
19class CompilationDependencies;
20class Factory;
21
22namespace compiler {
23
24// Forward declarations.
25class Type;
26class TypeCache;
27
28// Whether we are loading a property or storing to a property.
29// For a store during literal creation, do not walk up the prototype chain.
30enum class AccessMode { kLoad, kStore, kStoreInLiteral };
31
32std::ostream& operator<<(std::ostream&, AccessMode);
33
34typedef std::vector<Handle<Map>> MapList;
35
36// Mapping of transition source to transition target.
37typedef std::vector<std::pair<Handle<Map>, Handle<Map>>> MapTransitionList;
38
39// This class encapsulates all information required to access a certain element.
40class ElementAccessInfo final {
41 public:
42  ElementAccessInfo();
43  ElementAccessInfo(MapList const& receiver_maps, ElementsKind elements_kind);
44
45  ElementsKind elements_kind() const { return elements_kind_; }
46  MapList const& receiver_maps() const { return receiver_maps_; }
47  MapTransitionList& transitions() { return transitions_; }
48  MapTransitionList const& transitions() const { return transitions_; }
49
50 private:
51  ElementsKind elements_kind_;
52  MapList receiver_maps_;
53  MapTransitionList transitions_;
54};
55
56// This class encapsulates all information required to access a certain
57// object property, either on the object itself or on the prototype chain.
58class PropertyAccessInfo final {
59 public:
60  enum Kind {
61    kInvalid,
62    kNotFound,
63    kDataConstant,
64    kDataField,
65    kDataConstantField,
66    kAccessorConstant,
67    kGeneric
68  };
69
70  static PropertyAccessInfo NotFound(MapList const& receiver_maps,
71                                     MaybeHandle<JSObject> holder);
72  static PropertyAccessInfo DataConstant(MapList const& receiver_maps,
73                                         Handle<Object> constant,
74                                         MaybeHandle<JSObject> holder);
75  static PropertyAccessInfo DataField(
76      PropertyConstness constness, MapList const& receiver_maps,
77      FieldIndex field_index, MachineRepresentation field_representation,
78      Type* field_type, MaybeHandle<Map> field_map = MaybeHandle<Map>(),
79      MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(),
80      MaybeHandle<Map> transition_map = MaybeHandle<Map>());
81  static PropertyAccessInfo AccessorConstant(MapList const& receiver_maps,
82                                             Handle<Object> constant,
83                                             MaybeHandle<JSObject> holder);
84  static PropertyAccessInfo Generic(MapList const& receiver_maps);
85
86  PropertyAccessInfo();
87
88  bool Merge(PropertyAccessInfo const* that) WARN_UNUSED_RESULT;
89
90  bool IsNotFound() const { return kind() == kNotFound; }
91  bool IsDataConstant() const { return kind() == kDataConstant; }
92  bool IsDataField() const { return kind() == kDataField; }
93  // TODO(ishell): rename to IsDataConstant() once constant field tracking
94  // is done.
95  bool IsDataConstantField() const { return kind() == kDataConstantField; }
96  bool IsAccessorConstant() const { return kind() == kAccessorConstant; }
97  bool IsGeneric() const { return kind() == kGeneric; }
98
99  bool HasTransitionMap() const { return !transition_map().is_null(); }
100
101  Kind kind() const { return kind_; }
102  MaybeHandle<JSObject> holder() const { return holder_; }
103  MaybeHandle<Map> transition_map() const { return transition_map_; }
104  Handle<Object> constant() const { return constant_; }
105  FieldIndex field_index() const { return field_index_; }
106  Type* field_type() const { return field_type_; }
107  MachineRepresentation field_representation() const {
108    return field_representation_;
109  }
110  MaybeHandle<Map> field_map() const { return field_map_; }
111  MapList const& receiver_maps() const { return receiver_maps_; }
112
113 private:
114  PropertyAccessInfo(MaybeHandle<JSObject> holder,
115                     MapList const& receiver_maps);
116  PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder,
117                     Handle<Object> constant, MapList const& receiver_maps);
118  PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder,
119                     MaybeHandle<Map> transition_map, FieldIndex field_index,
120                     MachineRepresentation field_representation,
121                     Type* field_type, MaybeHandle<Map> field_map,
122                     MapList const& receiver_maps);
123
124  Kind kind_;
125  MapList receiver_maps_;
126  Handle<Object> constant_;
127  MaybeHandle<Map> transition_map_;
128  MaybeHandle<JSObject> holder_;
129  FieldIndex field_index_;
130  MachineRepresentation field_representation_;
131  Type* field_type_;
132  MaybeHandle<Map> field_map_;
133};
134
135
136// Factory class for {ElementAccessInfo}s and {PropertyAccessInfo}s.
137class AccessInfoFactory final {
138 public:
139  AccessInfoFactory(CompilationDependencies* dependencies,
140                    Handle<Context> native_context, Zone* zone);
141
142  bool ComputeElementAccessInfo(Handle<Map> map, AccessMode access_mode,
143                                ElementAccessInfo* access_info);
144  bool ComputeElementAccessInfos(MapHandleList const& maps,
145                                 AccessMode access_mode,
146                                 ZoneVector<ElementAccessInfo>* access_infos);
147  bool ComputePropertyAccessInfo(Handle<Map> map, Handle<Name> name,
148                                 AccessMode access_mode,
149                                 PropertyAccessInfo* access_info);
150  bool ComputePropertyAccessInfos(MapHandleList const& maps, Handle<Name> name,
151                                  AccessMode access_mode,
152                                  ZoneVector<PropertyAccessInfo>* access_infos);
153
154 private:
155  bool LookupSpecialFieldAccessor(Handle<Map> map, Handle<Name> name,
156                                  PropertyAccessInfo* access_info);
157  bool LookupTransition(Handle<Map> map, Handle<Name> name,
158                        MaybeHandle<JSObject> holder,
159                        PropertyAccessInfo* access_info);
160
161  CompilationDependencies* dependencies() const { return dependencies_; }
162  Factory* factory() const;
163  Isolate* isolate() const { return isolate_; }
164  Handle<Context> native_context() const { return native_context_; }
165  Zone* zone() const { return zone_; }
166
167  CompilationDependencies* const dependencies_;
168  Handle<Context> const native_context_;
169  Isolate* const isolate_;
170  TypeCache const& type_cache_;
171  Zone* const zone_;
172
173  DISALLOW_COPY_AND_ASSIGN(AccessInfoFactory);
174};
175
176}  // namespace compiler
177}  // namespace internal
178}  // namespace v8
179
180#endif  // V8_COMPILER_ACCESS_INFO_H_
181