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/compiler/graph-reducer.h"
10 #include "src/deoptimize-reason.h"
11 #include "src/objects/map.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 // Forward declarations.
17 class Factory;
18 class FeedbackNexus;
19 
20 namespace compiler {
21 
22 // Forward declarations.
23 enum class AccessMode;
24 class CommonOperatorBuilder;
25 class CompilationDependencies;
26 class ElementAccessInfo;
27 class JSGraph;
28 class JSHeapBroker;
29 class JSOperatorBuilder;
30 class MachineOperatorBuilder;
31 class PropertyAccessInfo;
32 class SimplifiedOperatorBuilder;
33 class TypeCache;
34 
35 // Specializes a given JSGraph to a given native context, potentially constant
36 // folding some {LoadGlobal} nodes or strength reducing some {StoreGlobal}
37 // nodes.  And also specializes {LoadNamed} and {StoreNamed} nodes according
38 // to type feedback (if available).
39 class JSNativeContextSpecialization final : public AdvancedReducer {
40  public:
41   // Flags that control the mode of operation.
42   enum Flag {
43     kNoFlags = 0u,
44     kAccessorInliningEnabled = 1u << 0,
45     kBailoutOnUninitialized = 1u << 1
46   };
47   typedef base::Flags<Flag> Flags;
48 
49   JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph,
50                                 JSHeapBroker* js_heap_broker, Flags flags,
51                                 Handle<Context> native_context,
52                                 CompilationDependencies* dependencies,
53                                 Zone* zone);
54 
reducer_name()55   const char* reducer_name() const override {
56     return "JSNativeContextSpecialization";
57   }
58 
59   Reduction Reduce(Node* node) final;
60 
61  private:
62   Reduction ReduceJSAdd(Node* node);
63   Reduction ReduceJSGetSuperConstructor(Node* node);
64   Reduction ReduceJSInstanceOf(Node* node);
65   Reduction ReduceJSHasInPrototypeChain(Node* node);
66   Reduction ReduceJSOrdinaryHasInstance(Node* node);
67   Reduction ReduceJSPromiseResolve(Node* node);
68   Reduction ReduceJSResolvePromise(Node* node);
69   Reduction ReduceJSLoadContext(Node* node);
70   Reduction ReduceJSLoadGlobal(Node* node);
71   Reduction ReduceJSStoreGlobal(Node* node);
72   Reduction ReduceJSLoadNamed(Node* node);
73   Reduction ReduceJSStoreNamed(Node* node);
74   Reduction ReduceJSLoadProperty(Node* node);
75   Reduction ReduceJSStoreProperty(Node* node);
76   Reduction ReduceJSStoreNamedOwn(Node* node);
77   Reduction ReduceJSStoreDataPropertyInLiteral(Node* node);
78   Reduction ReduceJSStoreInArrayLiteral(Node* node);
79   Reduction ReduceJSToObject(Node* node);
80 
81   Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
82                                 MapHandles const& receiver_maps,
83                                 AccessMode access_mode,
84                                 KeyedAccessLoadMode load_mode,
85                                 KeyedAccessStoreMode store_mode);
86   Reduction ReduceKeyedAccess(Node* node, Node* index, Node* value,
87                               FeedbackNexus const& nexus,
88                               AccessMode access_mode,
89                               KeyedAccessLoadMode load_mode,
90                               KeyedAccessStoreMode store_mode);
91   Reduction ReduceNamedAccessFromNexus(Node* node, Node* value,
92                                        FeedbackNexus const& nexus,
93                                        Handle<Name> name,
94                                        AccessMode access_mode);
95   Reduction ReduceNamedAccess(Node* node, Node* value,
96                               MapHandles const& receiver_maps,
97                               Handle<Name> name, AccessMode access_mode,
98                               Node* index = nullptr);
99   Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
100                                Handle<Name> name, AccessMode access_mode,
101                                Node* index = nullptr);
102 
103   Reduction ReduceSoftDeoptimize(Node* node, DeoptimizeReason reason);
104 
105   // A triple of nodes that represents a continuation.
106   class ValueEffectControl final {
107    public:
ValueEffectControl()108     ValueEffectControl()
109         : value_(nullptr), effect_(nullptr), control_(nullptr) {}
ValueEffectControl(Node * value,Node * effect,Node * control)110     ValueEffectControl(Node* value, Node* effect, Node* control)
111         : value_(value), effect_(effect), control_(control) {}
112 
value()113     Node* value() const { return value_; }
effect()114     Node* effect() const { return effect_; }
control()115     Node* control() const { return control_; }
116 
117    private:
118     Node* value_;
119     Node* effect_;
120     Node* control_;
121   };
122 
123   // Construct the appropriate subgraph for property access.
124   ValueEffectControl BuildPropertyAccess(Node* receiver, Node* value,
125                                          Node* context, Node* frame_state,
126                                          Node* effect, Node* control,
127                                          Handle<Name> name,
128                                          ZoneVector<Node*>* if_exceptions,
129                                          PropertyAccessInfo const& access_info,
130                                          AccessMode access_mode);
131   ValueEffectControl BuildPropertyLoad(Node* receiver, Node* context,
132                                        Node* frame_state, Node* effect,
133                                        Node* control, Handle<Name> name,
134                                        ZoneVector<Node*>* if_exceptions,
135                                        PropertyAccessInfo const& access_info);
136 
137   ValueEffectControl BuildPropertyStore(Node* receiver, Node* value,
138                                         Node* context, Node* frame_state,
139                                         Node* effect, Node* control,
140                                         Handle<Name> name,
141                                         ZoneVector<Node*>* if_exceptions,
142                                         PropertyAccessInfo const& access_info,
143                                         AccessMode access_mode);
144 
145   // Helpers for accessor inlining.
146   Node* InlinePropertyGetterCall(Node* receiver, Node* context,
147                                  Node* frame_state, Node** effect,
148                                  Node** control,
149                                  ZoneVector<Node*>* if_exceptions,
150                                  PropertyAccessInfo const& access_info);
151   void InlinePropertySetterCall(Node* receiver, Node* value, Node* context,
152                                 Node* frame_state, Node** effect,
153                                 Node** control,
154                                 ZoneVector<Node*>* if_exceptions,
155                                 PropertyAccessInfo const& access_info);
156   Node* InlineApiCall(Node* receiver, Node* holder, Node* frame_state,
157                       Node* value, Node** effect, Node** control,
158                       Handle<SharedFunctionInfo> shared_info,
159                       Handle<FunctionTemplateInfo> function_template_info);
160 
161   // Construct the appropriate subgraph for element access.
162   ValueEffectControl BuildElementAccess(
163       Node* receiver, Node* index, Node* value, Node* effect, Node* control,
164       ElementAccessInfo const& access_info, AccessMode access_mode,
165       KeyedAccessLoadMode load_mode, KeyedAccessStoreMode store_mode);
166 
167   // Construct appropriate subgraph to load from a String.
168   Node* BuildIndexedStringLoad(Node* receiver, Node* index, Node* length,
169                                Node** effect, Node** control,
170                                KeyedAccessLoadMode load_mode);
171 
172   // Construct appropriate subgraph to extend properties backing store.
173   Node* BuildExtendPropertiesBackingStore(Handle<Map> map, Node* properties,
174                                           Node* effect, Node* control);
175 
176   // Construct appropriate subgraph to check that the {value} matches
177   // the previously recorded {name} feedback.
178   Node* BuildCheckEqualsName(Handle<Name> name, Node* value, Node* effect,
179                              Node* control);
180 
181   // Checks if we can turn the hole into undefined when loading an element
182   // from an object with one of the {receiver_maps}; sets up appropriate
183   // code dependencies and might use the array protector cell.
184   bool CanTreatHoleAsUndefined(MapHandles const& receiver_maps);
185 
186   // Extract receiver maps from {nexus} and filter based on {receiver} if
187   // possible.
188   bool ExtractReceiverMaps(Node* receiver, Node* effect,
189                            FeedbackNexus const& nexus,
190                            MapHandles* receiver_maps);
191 
192   // Try to infer maps for the given {receiver} at the current {effect}.
193   // If maps are returned then you can be sure that the {receiver} definitely
194   // has one of the returned maps at this point in the program (identified
195   // by {effect}).
196   bool InferReceiverMaps(Node* receiver, Node* effect,
197                          MapHandles* receiver_maps);
198   // Try to infer a root map for the {receiver} independent of the current
199   // program location.
200   MaybeHandle<Map> InferReceiverRootMap(Node* receiver);
201 
202   // Checks if we know at compile time that the {receiver} either definitely
203   // has the {prototype} in it's prototype chain, or the {receiver} definitely
204   // doesn't have the {prototype} in it's prototype chain.
205   enum InferHasInPrototypeChainResult {
206     kIsInPrototypeChain,
207     kIsNotInPrototypeChain,
208     kMayBeInPrototypeChain
209   };
210   InferHasInPrototypeChainResult InferHasInPrototypeChain(
211       Node* receiver, Node* effect, Handle<HeapObject> prototype);
212 
213   // Script context lookup logic.
214   struct ScriptContextTableLookupResult;
215   bool LookupInScriptContextTable(Handle<Name> name,
216                                   ScriptContextTableLookupResult* result);
217 
218   Graph* graph() const;
jsgraph()219   JSGraph* jsgraph() const { return jsgraph_; }
220 
js_heap_broker()221   JSHeapBroker* js_heap_broker() const { return js_heap_broker_; }
222   Isolate* isolate() const;
223   Factory* factory() const;
224   CommonOperatorBuilder* common() const;
225   JSOperatorBuilder* javascript() const;
226   SimplifiedOperatorBuilder* simplified() const;
flags()227   Flags flags() const { return flags_; }
global_object()228   Handle<JSGlobalObject> global_object() const { return global_object_; }
global_proxy()229   Handle<JSGlobalProxy> global_proxy() const { return global_proxy_; }
native_context()230   const NativeContextRef& native_context() const { return native_context_; }
dependencies()231   CompilationDependencies* dependencies() const { return dependencies_; }
zone()232   Zone* zone() const { return zone_; }
233 
234   JSGraph* const jsgraph_;
235   JSHeapBroker* const js_heap_broker_;
236   Flags const flags_;
237   Handle<JSGlobalObject> global_object_;
238   Handle<JSGlobalProxy> global_proxy_;
239   NativeContextRef native_context_;
240   CompilationDependencies* const dependencies_;
241   Zone* const zone_;
242   TypeCache const& type_cache_;
243 
244   DISALLOW_COPY_AND_ASSIGN(JSNativeContextSpecialization);
245 };
246 
247 DEFINE_OPERATORS_FOR_FLAGS(JSNativeContextSpecialization::Flags)
248 
249 }  // namespace compiler
250 }  // namespace internal
251 }  // namespace v8
252 
253 #endif  // V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
254