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
13namespace v8 {
14namespace internal {
15
16// Forward declarations.
17class Factory;
18class FeedbackNexus;
19class JSGlobalObject;
20class JSGlobalProxy;
21class StringConstantBase;
22
23namespace compiler {
24
25// Forward declarations.
26enum class AccessMode;
27class CommonOperatorBuilder;
28class CompilationDependencies;
29class ElementAccessInfo;
30class JSGraph;
31class JSHeapBroker;
32class JSOperatorBuilder;
33class MachineOperatorBuilder;
34class PropertyAccessInfo;
35class SimplifiedOperatorBuilder;
36class 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).
42class 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 kAccessorInliningEnabled = 1u << 0,
49 kBailoutOnUninitialized = 1u << 1
50 };
51 using Flags = base::Flags<Flag>;
52
53 JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph,
54 JSHeapBroker* broker, Flags flags,
55 Handle<Context> native_context,
56 CompilationDependencies* dependencies,
57 Zone* zone, Zone* shared_zone);
58
59 const char* reducer_name() const override {
60 return "JSNativeContextSpecialization";
61 }
62
63 Reduction Reduce(Node* node) final;
64
65 // Utility for folding string constant concatenation.
66 // Supports JSAdd nodes and nodes typed as string or number.
67 // Public for the sake of unit testing.
68 static base::Optional<size_t> GetMaxStringLength(JSHeapBroker* broker,
69 Node* node);
70
71 private:
72 Reduction ReduceJSAdd(Node* node);
73 Reduction ReduceJSAsyncFunctionEnter(Node* node);
74 Reduction ReduceJSAsyncFunctionReject(Node* node);
75 Reduction ReduceJSAsyncFunctionResolve(Node* node);
76 Reduction ReduceJSGetSuperConstructor(Node* node);
77 Reduction ReduceJSInstanceOf(Node* node);
78 Reduction ReduceJSHasInPrototypeChain(Node* node);
79 Reduction ReduceJSOrdinaryHasInstance(Node* node);
80 Reduction ReduceJSPromiseResolve(Node* node);
81 Reduction ReduceJSResolvePromise(Node* node);
82 Reduction ReduceJSLoadContext(Node* node);
83 Reduction ReduceJSLoadGlobal(Node* node);
84 Reduction ReduceJSStoreGlobal(Node* node);
85 Reduction ReduceJSLoadNamed(Node* node);
86 Reduction ReduceJSStoreNamed(Node* node);
87 Reduction ReduceJSHasProperty(Node* node);
88 Reduction ReduceJSLoadProperty(Node* node);
89 Reduction ReduceJSStoreProperty(Node* node);
90 Reduction ReduceJSStoreNamedOwn(Node* node);
91 Reduction ReduceJSStoreDataPropertyInLiteral(Node* node);
92 Reduction ReduceJSStoreInArrayLiteral(Node* node);
93 Reduction ReduceJSToObject(Node* node);
94
95 Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
96 FeedbackNexus const& nexus,
97 MapHandles const& receiver_maps,
98 AccessMode access_mode,
99 KeyedAccessLoadMode load_mode,
100 KeyedAccessStoreMode store_mode);
101 Reduction ReduceKeyedAccess(Node* node, Node* key, Node* value,
102 FeedbackNexus const& nexus,
103 AccessMode access_mode,
104 KeyedAccessLoadMode load_mode,
105 KeyedAccessStoreMode store_mode);
106 Reduction ReduceNamedAccessFromNexus(Node* node, Node* value,
107 FeedbackNexus const& nexus,
108 NameRef const& name,
109 AccessMode access_mode);
110 Reduction ReduceNamedAccess(Node* node, Node* value,
111 MapHandles const& receiver_maps,
112 NameRef const& name, AccessMode access_mode,
113 Node* key = nullptr);
114 Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
115 NameRef const& name, AccessMode access_mode,
116 Node* key = nullptr);
117 Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
118 NameRef const& name, AccessMode access_mode,
119 Node* key, PropertyCellRef const& property_cell);
120 Reduction ReduceKeyedLoadFromHeapConstant(Node* node, Node* key,
121 FeedbackNexus const& nexus,
122 AccessMode access_mode,
123 KeyedAccessLoadMode load_mode);
124 Reduction ReduceElementAccessOnString(Node* node, Node* index, Node* value,
125 AccessMode access_mode,
126 KeyedAccessLoadMode load_mode);
127
128 Reduction ReduceSoftDeoptimize(Node* node, DeoptimizeReason reason);
129 Reduction ReduceJSToString(Node* node);
130
131 Reduction ReduceJSLoadPropertyWithEnumeratedKey(Node* node);
132
133 const StringConstantBase* CreateDelayedStringConstant(Node* node);
134
135 // A triple of nodes that represents a continuation.
136 class ValueEffectControl final {
137 public:
138 ValueEffectControl()
139 : value_(nullptr), effect_(nullptr), control_(nullptr) {}
140 ValueEffectControl(Node* value, Node* effect, Node* control)
141 : value_(value), effect_(effect), control_(control) {}
142
143 Node* value() const { return value_; }
144 Node* effect() const { return effect_; }
145 Node* control() const { return control_; }
146
147 private:
148 Node* value_;
149 Node* effect_;
150 Node* control_;
151 };
152
153 // Construct the appropriate subgraph for property access.
154 ValueEffectControl BuildPropertyAccess(Node* receiver, Node* value,
155 Node* context, Node* frame_state,
156 Node* effect, Node* control,
157 NameRef const& name,
158 ZoneVector<Node*>* if_exceptions,
159 PropertyAccessInfo const& access_info,
160 AccessMode access_mode);
161 ValueEffectControl BuildPropertyLoad(Node* receiver, Node* context,
162 Node* frame_state, Node* effect,
163 Node* control, NameRef const& name,
164 ZoneVector<Node*>* if_exceptions,
165 PropertyAccessInfo const& access_info);
166
167 ValueEffectControl BuildPropertyStore(Node* receiver, Node* value,
168 Node* context, Node* frame_state,
169 Node* effect, Node* control,
170 NameRef const& name,
171 ZoneVector<Node*>* if_exceptions,
172 PropertyAccessInfo const& access_info,
173 AccessMode access_mode);
174
175 ValueEffectControl BuildPropertyTest(Node* effect, Node* control,
176 PropertyAccessInfo const& access_info);
177
178 // Helpers for accessor inlining.
179 Node* InlinePropertyGetterCall(Node* receiver, Node* context,
180 Node* frame_state, Node** effect,
181 Node** control,
182 ZoneVector<Node*>* if_exceptions,
183 PropertyAccessInfo const& access_info);
184 void InlinePropertySetterCall(Node* receiver, Node* value, Node* context,
185 Node* frame_state, Node** effect,
186 Node** control,
187 ZoneVector<Node*>* if_exceptions,
188 PropertyAccessInfo const& access_info);
189 Node* InlineApiCall(Node* receiver, Node* holder, Node* frame_state,
190 Node* value, Node** effect, Node** control,
191 SharedFunctionInfoRef const& shared_info,
192 FunctionTemplateInfoRef const& function_template_info);
193
194 // Construct the appropriate subgraph for element access.
195 ValueEffectControl BuildElementAccess(
196 Node* receiver, Node* index, Node* value, Node* effect, Node* control,
197 ElementAccessInfo const& access_info, AccessMode access_mode,
198 KeyedAccessLoadMode load_mode, KeyedAccessStoreMode store_mode);
199
200 // Construct appropriate subgraph to load from a String.
201 Node* BuildIndexedStringLoad(Node* receiver, Node* index, Node* length,
202 Node** effect, Node** control,
203 KeyedAccessLoadMode load_mode);
204
205 // Construct appropriate subgraph to extend properties backing store.
206 Node* BuildExtendPropertiesBackingStore(const MapRef& map, Node* properties,
207 Node* effect, Node* control);
208
209 // Construct appropriate subgraph to check that the {value} matches
210 // the previously recorded {name} feedback.
211 Node* BuildCheckEqualsName(NameRef const& name, Node* value, Node* effect,
212 Node* control);
213
214 // Checks if we can turn the hole into undefined when loading an element
215 // from an object with one of the {receiver_maps}; sets up appropriate
216 // code dependencies and might use the array protector cell.
217 bool CanTreatHoleAsUndefined(MapHandles const& receiver_maps);
218
219 // Extract receiver maps from {nexus} and filter based on {receiver} if
220 // possible.
221 bool ExtractReceiverMaps(Node* receiver, Node* effect,
222 FeedbackNexus const& nexus,
223 MapHandles* receiver_maps);
224
225 // Try to infer maps for the given {receiver} at the current {effect}.
226 bool InferReceiverMaps(Node* receiver, Node* effect,
227 MapHandles* receiver_maps);
228 // Try to infer a root map for the {receiver} independent of the current
229 // program location.
230 MaybeHandle<Map> InferReceiverRootMap(Node* receiver);
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, Handle<HeapObject> prototype);
242
243 Graph* graph() const;
244 JSGraph* jsgraph() const { return jsgraph_; }
245
246 JSHeapBroker* broker() const { return broker_; }
247 Isolate* isolate() const;
248 Factory* factory() const;
249 CommonOperatorBuilder* common() const;
250 JSOperatorBuilder* javascript() const;
251 SimplifiedOperatorBuilder* simplified() const;
252 Flags flags() const { return flags_; }
253 Handle<JSGlobalObject> global_object() const { return global_object_; }
254 Handle<JSGlobalProxy> global_proxy() const { return global_proxy_; }
255 NativeContextRef native_context() const { return broker()->native_context(); }
256 CompilationDependencies* dependencies() const { return dependencies_; }
257 Zone* zone() const { return zone_; }
258 Zone* shared_zone() const { return shared_zone_; }
259
260 JSGraph* const jsgraph_;
261 JSHeapBroker* const broker_;
262 Flags const flags_;
263 Handle<JSGlobalObject> global_object_;
264 Handle<JSGlobalProxy> global_proxy_;
265 CompilationDependencies* const dependencies_;
266 Zone* const zone_;
267 Zone* const shared_zone_;
268 TypeCache const* type_cache_;
269
270 DISALLOW_COPY_AND_ASSIGN(JSNativeContextSpecialization);
271};
272
273DEFINE_OPERATORS_FOR_FLAGS(JSNativeContextSpecialization::Flags)
274
275} // namespace compiler
276} // namespace internal
277} // namespace v8
278
279#endif // V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
280