• 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_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
6 #define V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
7 
8 #include "src/base/flags.h"
9 #include "src/base/optional.h"
10 #include "src/compiler/graph-reducer.h"
11 #include "src/compiler/js-heap-broker.h"
12 #include "src/deoptimizer/deoptimize-reason.h"
13 #include "src/objects/map.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 // Forward declarations.
19 class Factory;
20 class JSGlobalObject;
21 class JSGlobalProxy;
22 class StringConstantBase;
23 
24 namespace compiler {
25 
26 // Forward declarations.
27 enum class AccessMode;
28 class CommonOperatorBuilder;
29 class CompilationDependencies;
30 class ElementAccessInfo;
31 class JSGraph;
32 class JSHeapBroker;
33 class JSOperatorBuilder;
34 class MachineOperatorBuilder;
35 class PropertyAccessInfo;
36 class SimplifiedOperatorBuilder;
37 class TypeCache;
38 
39 // Specializes a given JSGraph to a given native context, potentially constant
40 // folding some {LoadGlobal} nodes or strength reducing some {StoreGlobal}
41 // nodes.  And also specializes {LoadNamed} and {SetNamedProperty} nodes
42 // according to type feedback (if available).
43 class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
44     : public AdvancedReducer {
45  public:
46   // Flags that control the mode of operation.
47   enum Flag {
48     kNoFlags = 0u,
49     kBailoutOnUninitialized = 1u << 0,
50   };
51   using Flags = base::Flags<Flag>;
52 
53   JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph,
54                                 JSHeapBroker* broker, Flags flags,
55                                 CompilationDependencies* dependencies,
56                                 Zone* zone, Zone* shared_zone);
57   JSNativeContextSpecialization(const JSNativeContextSpecialization&) = delete;
58   JSNativeContextSpecialization& operator=(
59       const JSNativeContextSpecialization&) = delete;
60 
reducer_name()61   const char* reducer_name() const override {
62     return "JSNativeContextSpecialization";
63   }
64 
65   Reduction Reduce(Node* node) final;
66 
67   // Utility for folding string constant concatenation.
68   // Supports JSAdd nodes and nodes typed as string or number.
69   // Public for the sake of unit testing.
70   static base::Optional<size_t> GetMaxStringLength(JSHeapBroker* broker,
71                                                    Node* node);
72 
73  private:
74   Reduction ReduceJSAdd(Node* node);
75   Reduction ReduceJSAsyncFunctionEnter(Node* node);
76   Reduction ReduceJSAsyncFunctionReject(Node* node);
77   Reduction ReduceJSAsyncFunctionResolve(Node* node);
78   Reduction ReduceJSGetSuperConstructor(Node* node);
79   Reduction ReduceJSInstanceOf(Node* node);
80   Reduction ReduceJSHasInPrototypeChain(Node* node);
81   Reduction ReduceJSOrdinaryHasInstance(Node* node);
82   Reduction ReduceJSPromiseResolve(Node* node);
83   Reduction ReduceJSResolvePromise(Node* node);
84   Reduction ReduceJSLoadGlobal(Node* node);
85   Reduction ReduceJSStoreGlobal(Node* node);
86   Reduction ReduceJSLoadNamed(Node* node);
87   Reduction ReduceJSLoadNamedFromSuper(Node* node);
88   Reduction ReduceJSGetIterator(Node* node);
89   Reduction ReduceJSSetNamedProperty(Node* node);
90   Reduction ReduceJSHasProperty(Node* node);
91   Reduction ReduceJSLoadProperty(Node* node);
92   Reduction ReduceJSSetKeyedProperty(Node* node);
93   Reduction ReduceJSDefineKeyedOwnProperty(Node* node);
94   Reduction ReduceJSDefineNamedOwnProperty(Node* node);
95   Reduction ReduceJSDefineKeyedOwnPropertyInLiteral(Node* node);
96   Reduction ReduceJSStoreInArrayLiteral(Node* node);
97   Reduction ReduceJSToObject(Node* node);
98 
99   Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
100                                 ElementAccessFeedback const& feedback);
101   // In the case of non-keyed (named) accesses, pass the name as {static_name}
102   // and use {nullptr} for {key} (load/store modes are irrelevant).
103   Reduction ReducePropertyAccess(Node* node, Node* key,
104                                  base::Optional<NameRef> static_name,
105                                  Node* value, FeedbackSource const& source,
106                                  AccessMode access_mode);
107   Reduction ReduceNamedAccess(Node* node, Node* value,
108                               NamedAccessFeedback const& feedback,
109                               AccessMode access_mode, Node* key = nullptr);
110   Reduction ReduceGlobalAccess(Node* node, Node* lookup_start_object,
111                                Node* receiver, Node* value, NameRef const& name,
112                                AccessMode access_mode, Node* key,
113                                PropertyCellRef const& property_cell,
114                                Node* effect = nullptr);
115   Reduction ReduceElementLoadFromHeapConstant(Node* node, Node* key,
116                                               AccessMode access_mode,
117                                               KeyedAccessLoadMode load_mode);
118   Reduction ReduceElementAccessOnString(Node* node, Node* index, Node* value,
119                                         KeyedAccessMode const& keyed_mode);
120 
121   Reduction ReduceEagerDeoptimize(Node* node, DeoptimizeReason reason);
122   Reduction ReduceJSToString(Node* node);
123 
124   Reduction ReduceJSLoadPropertyWithEnumeratedKey(Node* node);
125 
126   base::Optional<const StringConstantBase*> CreateDelayedStringConstant(
127       Node* node);
128 
129   // A triple of nodes that represents a continuation.
130   class ValueEffectControl final {
131    public:
ValueEffectControl()132     ValueEffectControl()
133         : value_(nullptr), effect_(nullptr), control_(nullptr) {}
ValueEffectControl(Node * value,Node * effect,Node * control)134     ValueEffectControl(Node* value, Node* effect, Node* control)
135         : value_(value), effect_(effect), control_(control) {}
136 
value()137     Node* value() const { return value_; }
effect()138     Node* effect() const { return effect_; }
control()139     Node* control() const { return control_; }
140 
141    private:
142     Node* value_;
143     Node* effect_;
144     Node* control_;
145   };
146 
147   // Construct the appropriate subgraph for property access. Return {} if the
148   // property access couldn't be built.
149   base::Optional<ValueEffectControl> BuildPropertyAccess(
150       Node* lookup_start_object, Node* receiver, Node* value, Node* context,
151       Node* frame_state, Node* effect, Node* control, NameRef const& name,
152       ZoneVector<Node*>* if_exceptions, PropertyAccessInfo const& access_info,
153       AccessMode access_mode);
154   base::Optional<ValueEffectControl> BuildPropertyLoad(
155       Node* lookup_start_object, Node* receiver, Node* context,
156       Node* frame_state, Node* effect, Node* control, NameRef const& name,
157       ZoneVector<Node*>* if_exceptions, PropertyAccessInfo const& access_info);
158 
159   ValueEffectControl BuildPropertyStore(Node* receiver, Node* value,
160                                         Node* context, Node* frame_state,
161                                         Node* effect, Node* control,
162                                         NameRef const& name,
163                                         ZoneVector<Node*>* if_exceptions,
164                                         PropertyAccessInfo const& access_info,
165                                         AccessMode access_mode);
166 
167   ValueEffectControl BuildPropertyTest(Node* effect, Node* control,
168                                        PropertyAccessInfo const& access_info);
169 
170   // Helpers for accessor inlining.
171   Node* InlinePropertyGetterCall(Node* receiver,
172                                  ConvertReceiverMode receiver_mode,
173                                  Node* lookup_start_object, Node* context,
174                                  Node* frame_state, Node** effect,
175                                  Node** control,
176                                  ZoneVector<Node*>* if_exceptions,
177                                  PropertyAccessInfo const& access_info);
178   void InlinePropertySetterCall(Node* receiver, Node* value, Node* context,
179                                 Node* frame_state, Node** effect,
180                                 Node** control,
181                                 ZoneVector<Node*>* if_exceptions,
182                                 PropertyAccessInfo const& access_info);
183   Node* InlineApiCall(Node* receiver, Node* holder, Node* frame_state,
184                       Node* value, Node** effect, Node** control,
185                       FunctionTemplateInfoRef const& function_template_info);
186 
187   // Construct the appropriate subgraph for element access.
188   ValueEffectControl BuildElementAccess(Node* receiver, Node* index,
189                                         Node* value, Node* effect,
190                                         Node* control,
191                                         ElementAccessInfo const& access_info,
192                                         KeyedAccessMode const& keyed_mode);
193 
194   // Construct appropriate subgraph to load from a String.
195   Node* BuildIndexedStringLoad(Node* receiver, Node* index, Node* length,
196                                Node** effect, Node** control,
197                                KeyedAccessLoadMode load_mode);
198 
199   // Construct appropriate subgraph to extend properties backing store.
200   Node* BuildExtendPropertiesBackingStore(const MapRef& map, Node* properties,
201                                           Node* effect, Node* control);
202 
203   // Construct appropriate subgraph to check that the {value} matches
204   // the previously recorded {name} feedback.
205   Node* BuildCheckEqualsName(NameRef const& name, Node* value, Node* effect,
206                              Node* control);
207 
208   // Checks if we can turn the hole into undefined when loading an element
209   // from an object with one of the {receiver_maps}; sets up appropriate
210   // code dependencies and might use the array protector cell.
211   bool CanTreatHoleAsUndefined(ZoneVector<MapRef> const& receiver_maps);
212 
213   void RemoveImpossibleMaps(Node* object, ZoneVector<MapRef>* maps) const;
214 
215   ElementAccessFeedback const& TryRefineElementAccessFeedback(
216       ElementAccessFeedback const& feedback, Node* receiver,
217       Effect effect) const;
218 
219   // Try to infer maps for the given {object} at the current {effect}.
220   bool InferMaps(Node* object, Effect effect, ZoneVector<MapRef>* maps) const;
221 
222   // Try to infer a root map for the {object} independent of the current program
223   // location.
224   base::Optional<MapRef> InferRootMap(Node* object) const;
225 
226   // Checks if we know at compile time that the {receiver} either definitely
227   // has the {prototype} in it's prototype chain, or the {receiver} definitely
228   // doesn't have the {prototype} in it's prototype chain.
229   enum InferHasInPrototypeChainResult {
230     kIsInPrototypeChain,
231     kIsNotInPrototypeChain,
232     kMayBeInPrototypeChain
233   };
234   InferHasInPrototypeChainResult InferHasInPrototypeChain(
235       Node* receiver, Effect effect, HeapObjectRef const& prototype);
236 
237   Node* BuildLoadPrototypeFromObject(Node* object, Node* effect, Node* control);
238 
239   Graph* graph() const;
jsgraph()240   JSGraph* jsgraph() const { return jsgraph_; }
241 
broker()242   JSHeapBroker* broker() const { return broker_; }
243   Isolate* isolate() const;
244   Factory* factory() const;
245   CommonOperatorBuilder* common() const;
246   JSOperatorBuilder* javascript() const;
247   SimplifiedOperatorBuilder* simplified() const;
flags()248   Flags flags() const { return flags_; }
global_object()249   Handle<JSGlobalObject> global_object() const { return global_object_; }
global_proxy()250   Handle<JSGlobalProxy> global_proxy() const { return global_proxy_; }
native_context()251   NativeContextRef native_context() const {
252     return broker()->target_native_context();
253   }
dependencies()254   CompilationDependencies* dependencies() const { return dependencies_; }
zone()255   Zone* zone() const { return zone_; }
shared_zone()256   Zone* shared_zone() const { return shared_zone_; }
257 
258   JSGraph* const jsgraph_;
259   JSHeapBroker* const broker_;
260   Flags const flags_;
261   Handle<JSGlobalObject> global_object_;
262   Handle<JSGlobalProxy> global_proxy_;
263   CompilationDependencies* const dependencies_;
264   Zone* const zone_;
265   Zone* const shared_zone_;
266   TypeCache const* type_cache_;
267 };
268 
269 DEFINE_OPERATORS_FOR_FLAGS(JSNativeContextSpecialization::Flags)
270 
271 }  // namespace compiler
272 }  // namespace internal
273 }  // namespace v8
274 
275 #endif  // V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
276