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