• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/codegen/machine-type.h"
11 #include "src/compiler/types.h"
12 #include "src/objects/feedback-vector.h"
13 #include "src/objects/field-index.h"
14 #include "src/objects/map.h"
15 #include "src/objects/objects.h"
16 #include "src/zone/zone-containers.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 // Forward declarations.
22 class Factory;
23 
24 namespace compiler {
25 
26 // Forward declarations.
27 class CompilationDependencies;
28 class CompilationDependency;
29 class ElementAccessFeedback;
30 class JSHeapBroker;
31 class MinimorphicLoadPropertyAccessFeedback;
32 class TypeCache;
33 struct ConstFieldInfo;
34 
35 std::ostream& operator<<(std::ostream&, AccessMode);
36 
37 // This class encapsulates all information required to access a certain element.
38 class ElementAccessInfo final {
39  public:
40   ElementAccessInfo(ZoneVector<Handle<Map>>&& lookup_start_object_maps,
41                     ElementsKind elements_kind, Zone* zone);
42 
elements_kind()43   ElementsKind elements_kind() const { return elements_kind_; }
lookup_start_object_maps()44   ZoneVector<Handle<Map>> const& lookup_start_object_maps() const {
45     return lookup_start_object_maps_;
46   }
transition_sources()47   ZoneVector<Handle<Map>> const& transition_sources() const {
48     return transition_sources_;
49   }
50 
AddTransitionSource(Handle<Map> map)51   void AddTransitionSource(Handle<Map> map) {
52     CHECK_EQ(lookup_start_object_maps_.size(), 1);
53     transition_sources_.push_back(map);
54   }
55 
56  private:
57   ElementsKind elements_kind_;
58   ZoneVector<Handle<Map>> lookup_start_object_maps_;
59   ZoneVector<Handle<Map>> transition_sources_;
60 };
61 
62 // This class encapsulates all information required to access a certain
63 // object property, either on the object itself or on the prototype chain.
64 class PropertyAccessInfo final {
65  public:
66   enum Kind {
67     kInvalid,
68     kNotFound,
69     kDataField,
70     kDataConstant,
71     kAccessorConstant,
72     kModuleExport,
73     kStringLength
74   };
75 
76   static PropertyAccessInfo NotFound(Zone* zone, Handle<Map> receiver_map,
77                                      MaybeHandle<JSObject> holder);
78   static PropertyAccessInfo DataField(
79       Zone* zone, Handle<Map> receiver_map,
80       ZoneVector<CompilationDependency const*>&& unrecorded_dependencies,
81       FieldIndex field_index, Representation field_representation,
82       Type field_type, Handle<Map> field_owner_map,
83       MaybeHandle<Map> field_map = MaybeHandle<Map>(),
84       MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(),
85       MaybeHandle<Map> transition_map = MaybeHandle<Map>());
86   static PropertyAccessInfo DataConstant(
87       Zone* zone, Handle<Map> receiver_map,
88       ZoneVector<CompilationDependency const*>&& unrecorded_dependencies,
89       FieldIndex field_index, Representation field_representation,
90       Type field_type, Handle<Map> field_owner_map, MaybeHandle<Map> field_map,
91       MaybeHandle<JSObject> holder,
92       MaybeHandle<Map> transition_map = MaybeHandle<Map>());
93   static PropertyAccessInfo AccessorConstant(Zone* zone,
94                                              Handle<Map> receiver_map,
95                                              Handle<Object> constant,
96                                              MaybeHandle<JSObject> holder);
97   static PropertyAccessInfo ModuleExport(Zone* zone, Handle<Map> receiver_map,
98                                          Handle<Cell> cell);
99   static PropertyAccessInfo StringLength(Zone* zone, Handle<Map> receiver_map);
100   static PropertyAccessInfo Invalid(Zone* zone);
101 
102   bool Merge(PropertyAccessInfo const* that, AccessMode access_mode,
103              Zone* zone) V8_WARN_UNUSED_RESULT;
104 
105   void RecordDependencies(CompilationDependencies* dependencies);
106 
IsInvalid()107   bool IsInvalid() const { return kind() == kInvalid; }
IsNotFound()108   bool IsNotFound() const { return kind() == kNotFound; }
IsDataField()109   bool IsDataField() const { return kind() == kDataField; }
IsDataConstant()110   bool IsDataConstant() const { return kind() == kDataConstant; }
IsAccessorConstant()111   bool IsAccessorConstant() const { return kind() == kAccessorConstant; }
IsModuleExport()112   bool IsModuleExport() const { return kind() == kModuleExport; }
IsStringLength()113   bool IsStringLength() const { return kind() == kStringLength; }
114 
HasTransitionMap()115   bool HasTransitionMap() const { return !transition_map().is_null(); }
116   ConstFieldInfo GetConstFieldInfo() const;
117 
kind()118   Kind kind() const { return kind_; }
holder()119   MaybeHandle<JSObject> holder() const {
120     // TODO(neis): There was a CHECK here that tries to protect against
121     // using the access info without recording its dependencies first.
122     // Find a more suitable place for it.
123     return holder_;
124   }
transition_map()125   MaybeHandle<Map> transition_map() const { return transition_map_; }
constant()126   Handle<Object> constant() const { return constant_; }
field_index()127   FieldIndex field_index() const { return field_index_; }
field_type()128   Type field_type() const { return field_type_; }
field_representation()129   Representation field_representation() const { return field_representation_; }
field_map()130   MaybeHandle<Map> field_map() const { return field_map_; }
lookup_start_object_maps()131   ZoneVector<Handle<Map>> const& lookup_start_object_maps() const {
132     return lookup_start_object_maps_;
133   }
134 
135  private:
136   explicit PropertyAccessInfo(Zone* zone);
137   PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder,
138                      ZoneVector<Handle<Map>>&& lookup_start_object_maps);
139   PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder,
140                      Handle<Object> constant,
141                      ZoneVector<Handle<Map>>&& lookup_start_object_maps);
142   PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder,
143                      MaybeHandle<Map> transition_map, FieldIndex field_index,
144                      Representation field_representation, Type field_type,
145                      Handle<Map> field_owner_map, MaybeHandle<Map> field_map,
146                      ZoneVector<Handle<Map>>&& lookup_start_object_maps,
147                      ZoneVector<CompilationDependency const*>&& dependencies);
148 
149   Kind kind_;
150   ZoneVector<Handle<Map>> lookup_start_object_maps_;
151   ZoneVector<CompilationDependency const*> unrecorded_dependencies_;
152   Handle<Object> constant_;
153   MaybeHandle<Map> transition_map_;
154   MaybeHandle<JSObject> holder_;
155   FieldIndex field_index_;
156   Representation field_representation_;
157   Type field_type_;
158   MaybeHandle<Map> field_owner_map_;
159   MaybeHandle<Map> field_map_;
160 };
161 
162 // This class encapsulates information required to generate load properties
163 // by only using the information from handlers. This information is used with
164 // dynamic map checks.
165 class MinimorphicLoadPropertyAccessInfo final {
166  public:
167   enum Kind { kInvalid, kDataField };
168   static MinimorphicLoadPropertyAccessInfo DataField(
169       int offset, bool is_inobject, Representation field_representation,
170       Type field_type);
171   static MinimorphicLoadPropertyAccessInfo Invalid();
172 
IsInvalid()173   bool IsInvalid() const { return kind_ == kInvalid; }
IsDataField()174   bool IsDataField() const { return kind_ == kDataField; }
offset()175   int offset() const { return offset_; }
is_inobject()176   int is_inobject() const { return is_inobject_; }
field_type()177   Type field_type() const { return field_type_; }
field_representation()178   Representation field_representation() const { return field_representation_; }
179 
180  private:
181   MinimorphicLoadPropertyAccessInfo(Kind kind, int offset, bool is_inobject,
182                                     Representation field_representation,
183                                     Type field_type);
184 
185   Kind kind_;
186   bool is_inobject_;
187   int offset_;
188   Representation field_representation_;
189   Type field_type_;
190 };
191 
192 // Factory class for {ElementAccessInfo}s and {PropertyAccessInfo}s.
193 class AccessInfoFactory final {
194  public:
195   AccessInfoFactory(JSHeapBroker* broker, CompilationDependencies* dependencies,
196                     Zone* zone);
197 
198   base::Optional<ElementAccessInfo> ComputeElementAccessInfo(
199       Handle<Map> map, AccessMode access_mode) const;
200   bool ComputeElementAccessInfos(
201       ElementAccessFeedback const& feedback,
202       ZoneVector<ElementAccessInfo>* access_infos) const;
203 
204   PropertyAccessInfo ComputePropertyAccessInfo(Handle<Map> map,
205                                                Handle<Name> name,
206                                                AccessMode access_mode) const;
207 
208   MinimorphicLoadPropertyAccessInfo ComputePropertyAccessInfo(
209       MinimorphicLoadPropertyAccessFeedback const& feedback) const;
210 
211   // Convenience wrapper around {ComputePropertyAccessInfo} for multiple maps.
212   void ComputePropertyAccessInfos(
213       MapHandles const& maps, Handle<Name> name, AccessMode access_mode,
214       ZoneVector<PropertyAccessInfo>* access_infos) const;
215 
216   // Merge as many of the given {infos} as possible and record any dependencies.
217   // Return false iff any of them was invalid, in which case no dependencies are
218   // recorded.
219   // TODO(neis): Make access_mode part of access info?
220   bool FinalizePropertyAccessInfos(
221       ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode,
222       ZoneVector<PropertyAccessInfo>* result) const;
223 
224   // Merge the given {infos} to a single one and record any dependencies. If the
225   // merge is not possible, the result has kind {kInvalid} and no dependencies
226   // are recorded.
227   PropertyAccessInfo FinalizePropertyAccessInfosAsOne(
228       ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode) const;
229 
230  private:
231   base::Optional<ElementAccessInfo> ConsolidateElementLoad(
232       ElementAccessFeedback const& feedback) const;
233   PropertyAccessInfo LookupSpecialFieldAccessor(Handle<Map> map,
234                                                 Handle<Name> name) const;
235   PropertyAccessInfo LookupTransition(Handle<Map> map, Handle<Name> name,
236                                       MaybeHandle<JSObject> holder) const;
237   PropertyAccessInfo ComputeDataFieldAccessInfo(Handle<Map> receiver_map,
238                                                 Handle<Map> map,
239                                                 MaybeHandle<JSObject> holder,
240                                                 InternalIndex descriptor,
241                                                 AccessMode access_mode) const;
242   PropertyAccessInfo ComputeAccessorDescriptorAccessInfo(
243       Handle<Map> receiver_map, Handle<Name> name, Handle<Map> map,
244       MaybeHandle<JSObject> holder, InternalIndex descriptor,
245       AccessMode access_mode) const;
246 
247   void MergePropertyAccessInfos(ZoneVector<PropertyAccessInfo> infos,
248                                 AccessMode access_mode,
249                                 ZoneVector<PropertyAccessInfo>* result) const;
250 
dependencies()251   CompilationDependencies* dependencies() const { return dependencies_; }
broker()252   JSHeapBroker* broker() const { return broker_; }
253   Isolate* isolate() const;
zone()254   Zone* zone() const { return zone_; }
255 
256   JSHeapBroker* const broker_;
257   CompilationDependencies* const dependencies_;
258   TypeCache const* const type_cache_;
259   Zone* const zone_;
260 
261   // TODO(nicohartmann@): Move to public
262   AccessInfoFactory(const AccessInfoFactory&) = delete;
263   AccessInfoFactory& operator=(const AccessInfoFactory&) = delete;
264 };
265 
266 }  // namespace compiler
267 }  // namespace internal
268 }  // namespace v8
269 
270 #endif  // V8_COMPILER_ACCESS_INFO_H_
271