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/objects.h"
12 #include "src/zone-containers.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 // Forward declarations.
18 class CompilationDependencies;
19 class Factory;
20 class TypeCache;
21 
22 
23 namespace compiler {
24 
25 // Whether we are loading a property or storing to a property.
26 enum class AccessMode { kLoad, kStore };
27 
28 std::ostream& operator<<(std::ostream&, AccessMode);
29 
30 
31 // Mapping of transition source to transition target.
32 typedef std::vector<std::pair<Handle<Map>, Handle<Map>>> MapTransitionList;
33 
34 
35 // This class encapsulates all information required to access a certain element.
36 class ElementAccessInfo final {
37  public:
38   ElementAccessInfo();
39   ElementAccessInfo(Type* receiver_type, ElementsKind elements_kind,
40                     MaybeHandle<JSObject> holder);
41 
holder()42   MaybeHandle<JSObject> holder() const { return holder_; }
elements_kind()43   ElementsKind elements_kind() const { return elements_kind_; }
receiver_type()44   Type* receiver_type() const { return receiver_type_; }
transitions()45   MapTransitionList& transitions() { return transitions_; }
transitions()46   MapTransitionList const& transitions() const { return transitions_; }
47 
48  private:
49   ElementsKind elements_kind_;
50   MaybeHandle<JSObject> holder_;
51   Type* receiver_type_;
52   MapTransitionList transitions_;
53 };
54 
55 
56 // Additional checks that need to be perform for data field accesses.
57 enum class FieldCheck : uint8_t {
58   // No additional checking needed.
59   kNone,
60   // Check that the [[ViewedArrayBuffer]] of {JSArrayBufferView}s
61   // was not neutered.
62   kJSArrayBufferViewBufferNotNeutered,
63 };
64 
65 
66 // This class encapsulates all information required to access a certain
67 // object property, either on the object itself or on the prototype chain.
68 class PropertyAccessInfo final {
69  public:
70   enum Kind { kInvalid, kNotFound, kDataConstant, kDataField };
71 
72   static PropertyAccessInfo NotFound(Type* receiver_type,
73                                      MaybeHandle<JSObject> holder);
74   static PropertyAccessInfo DataConstant(Type* receiver_type,
75                                          Handle<Object> constant,
76                                          MaybeHandle<JSObject> holder);
77   static PropertyAccessInfo DataField(
78       Type* receiver_type, FieldIndex field_index, Type* field_type,
79       FieldCheck field_check = FieldCheck::kNone,
80       MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(),
81       MaybeHandle<Map> transition_map = MaybeHandle<Map>());
82 
83   PropertyAccessInfo();
84 
IsNotFound()85   bool IsNotFound() const { return kind() == kNotFound; }
IsDataConstant()86   bool IsDataConstant() const { return kind() == kDataConstant; }
IsDataField()87   bool IsDataField() const { return kind() == kDataField; }
88 
HasTransitionMap()89   bool HasTransitionMap() const { return !transition_map().is_null(); }
90 
kind()91   Kind kind() const { return kind_; }
holder()92   MaybeHandle<JSObject> holder() const { return holder_; }
transition_map()93   MaybeHandle<Map> transition_map() const { return transition_map_; }
constant()94   Handle<Object> constant() const { return constant_; }
field_check()95   FieldCheck field_check() const { return field_check_; }
field_index()96   FieldIndex field_index() const { return field_index_; }
field_type()97   Type* field_type() const { return field_type_; }
receiver_type()98   Type* receiver_type() const { return receiver_type_; }
99 
100  private:
101   PropertyAccessInfo(MaybeHandle<JSObject> holder, Type* receiver_type);
102   PropertyAccessInfo(MaybeHandle<JSObject> holder, Handle<Object> constant,
103                      Type* receiver_type);
104   PropertyAccessInfo(MaybeHandle<JSObject> holder,
105                      MaybeHandle<Map> transition_map, FieldIndex field_index,
106                      FieldCheck field_check, Type* field_type,
107                      Type* receiver_type);
108 
109   Kind kind_;
110   Type* receiver_type_;
111   Handle<Object> constant_;
112   MaybeHandle<Map> transition_map_;
113   MaybeHandle<JSObject> holder_;
114   FieldIndex field_index_;
115   FieldCheck field_check_;
116   Type* field_type_;
117 };
118 
119 
120 // Factory class for {ElementAccessInfo}s and {PropertyAccessInfo}s.
121 class AccessInfoFactory final {
122  public:
123   AccessInfoFactory(CompilationDependencies* dependencies,
124                     Handle<Context> native_context, Zone* zone);
125 
126   bool ComputeElementAccessInfo(Handle<Map> map, AccessMode access_mode,
127                                 ElementAccessInfo* access_info);
128   bool ComputeElementAccessInfos(MapHandleList const& maps,
129                                  AccessMode access_mode,
130                                  ZoneVector<ElementAccessInfo>* access_infos);
131   bool ComputePropertyAccessInfo(Handle<Map> map, Handle<Name> name,
132                                  AccessMode access_mode,
133                                  PropertyAccessInfo* access_info);
134   bool ComputePropertyAccessInfos(MapHandleList const& maps, Handle<Name> name,
135                                   AccessMode access_mode,
136                                   ZoneVector<PropertyAccessInfo>* access_infos);
137 
138  private:
139   bool LookupSpecialFieldAccessor(Handle<Map> map, Handle<Name> name,
140                                   PropertyAccessInfo* access_info);
141   bool LookupTransition(Handle<Map> map, Handle<Name> name,
142                         MaybeHandle<JSObject> holder,
143                         PropertyAccessInfo* access_info);
144 
dependencies()145   CompilationDependencies* dependencies() const { return dependencies_; }
146   Factory* factory() const;
isolate()147   Isolate* isolate() const { return isolate_; }
native_context()148   Handle<Context> native_context() const { return native_context_; }
zone()149   Zone* zone() const { return zone_; }
150 
151   CompilationDependencies* const dependencies_;
152   Handle<Context> const native_context_;
153   Isolate* const isolate_;
154   TypeCache const& type_cache_;
155   Zone* const zone_;
156 
157   DISALLOW_COPY_AND_ASSIGN(AccessInfoFactory);
158 };
159 
160 }  // namespace compiler
161 }  // namespace internal
162 }  // namespace v8
163 
164 #endif  // V8_COMPILER_ACCESS_INFO_H_
165