Line data Source code
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 : 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 456727 : 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 : kAccessorInliningEnabled = 1u << 0,
49 : kBailoutOnUninitialized = 1u << 1
50 : };
51 : typedef base::Flags<Flag> Flags;
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 19 : const char* reducer_name() const override {
60 19 : 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 ReduceJSLoadProperty(Node* node);
88 : Reduction ReduceJSStoreProperty(Node* node);
89 : Reduction ReduceJSStoreNamedOwn(Node* node);
90 : Reduction ReduceJSStoreDataPropertyInLiteral(Node* node);
91 : Reduction ReduceJSStoreInArrayLiteral(Node* node);
92 : Reduction ReduceJSToObject(Node* node);
93 :
94 : Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
95 : MapHandles const& receiver_maps,
96 : AccessMode access_mode,
97 : KeyedAccessLoadMode load_mode,
98 : KeyedAccessStoreMode store_mode);
99 : Reduction ReduceKeyedAccess(Node* node, Node* index, Node* value,
100 : FeedbackNexus const& nexus,
101 : AccessMode access_mode,
102 : KeyedAccessLoadMode load_mode,
103 : KeyedAccessStoreMode store_mode);
104 : Reduction ReduceNamedAccessFromNexus(Node* node, Node* value,
105 : FeedbackNexus const& nexus,
106 : Handle<Name> name,
107 : AccessMode access_mode);
108 : Reduction ReduceNamedAccess(Node* node, Node* value,
109 : MapHandles const& receiver_maps,
110 : Handle<Name> name, AccessMode access_mode,
111 : Node* index = nullptr);
112 : Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
113 : Handle<Name> name, AccessMode access_mode,
114 : Node* index = nullptr);
115 : Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
116 : Handle<Name> name, AccessMode access_mode,
117 : Node* index, Handle<PropertyCell> property_cell);
118 : Reduction ReduceKeyedLoadFromHeapConstant(Node* node, Node* index,
119 : FeedbackNexus const& nexus,
120 : KeyedAccessLoadMode load_mode);
121 :
122 : Reduction ReduceSoftDeoptimize(Node* node, DeoptimizeReason reason);
123 : Reduction ReduceJSToString(Node* node);
124 :
125 : Reduction ReduceJSLoadPropertyWithEnumeratedKey(Node* node);
126 :
127 : const StringConstantBase* CreateDelayedStringConstant(Node* node);
128 :
129 : // A triple of nodes that represents a continuation.
130 : class ValueEffectControl final {
131 : public:
132 : ValueEffectControl()
133 : : value_(nullptr), effect_(nullptr), control_(nullptr) {}
134 : ValueEffectControl(Node* value, Node* effect, Node* control)
135 156203 : : value_(value), effect_(effect), control_(control) {}
136 :
137 : Node* value() const { return value_; }
138 : Node* effect() const { return effect_; }
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.
148 : ValueEffectControl BuildPropertyAccess(Node* receiver, Node* value,
149 : Node* context, Node* frame_state,
150 : Node* effect, Node* control,
151 : Handle<Name> name,
152 : ZoneVector<Node*>* if_exceptions,
153 : PropertyAccessInfo const& access_info,
154 : AccessMode access_mode);
155 : ValueEffectControl BuildPropertyLoad(Node* receiver, Node* context,
156 : Node* frame_state, Node* effect,
157 : Node* control, Handle<Name> name,
158 : ZoneVector<Node*>* if_exceptions,
159 : PropertyAccessInfo const& access_info);
160 :
161 : ValueEffectControl BuildPropertyStore(Node* receiver, Node* value,
162 : Node* context, Node* frame_state,
163 : Node* effect, Node* control,
164 : Handle<Name> name,
165 : ZoneVector<Node*>* if_exceptions,
166 : PropertyAccessInfo const& access_info,
167 : AccessMode access_mode);
168 :
169 : // Helpers for accessor inlining.
170 : Node* InlinePropertyGetterCall(Node* receiver, Node* context,
171 : Node* frame_state, Node** effect,
172 : Node** control,
173 : ZoneVector<Node*>* if_exceptions,
174 : PropertyAccessInfo const& access_info);
175 : void InlinePropertySetterCall(Node* receiver, Node* value, Node* context,
176 : Node* frame_state, Node** effect,
177 : Node** control,
178 : ZoneVector<Node*>* if_exceptions,
179 : PropertyAccessInfo const& access_info);
180 : Node* InlineApiCall(Node* receiver, Node* holder, Node* frame_state,
181 : Node* value, Node** effect, Node** control,
182 : Handle<SharedFunctionInfo> shared_info,
183 : Handle<FunctionTemplateInfo> function_template_info);
184 :
185 : // Construct the appropriate subgraph for element access.
186 : ValueEffectControl BuildElementAccess(
187 : Node* receiver, Node* index, Node* value, Node* effect, Node* control,
188 : ElementAccessInfo const& access_info, AccessMode access_mode,
189 : KeyedAccessLoadMode load_mode, KeyedAccessStoreMode store_mode);
190 :
191 : // Construct appropriate subgraph to load from a String.
192 : Node* BuildIndexedStringLoad(Node* receiver, Node* index, Node* length,
193 : Node** effect, Node** control,
194 : KeyedAccessLoadMode load_mode);
195 :
196 : // Construct appropriate subgraph to extend properties backing store.
197 : Node* BuildExtendPropertiesBackingStore(const MapRef& map, Node* properties,
198 : Node* effect, Node* control);
199 :
200 : // Construct appropriate subgraph to check that the {value} matches
201 : // the previously recorded {name} feedback.
202 : Node* BuildCheckEqualsName(Handle<Name> name, Node* value, Node* effect,
203 : Node* control);
204 :
205 : // Checks if we can turn the hole into undefined when loading an element
206 : // from an object with one of the {receiver_maps}; sets up appropriate
207 : // code dependencies and might use the array protector cell.
208 : bool CanTreatHoleAsUndefined(MapHandles const& receiver_maps);
209 :
210 : // Extract receiver maps from {nexus} and filter based on {receiver} if
211 : // possible.
212 : bool ExtractReceiverMaps(Node* receiver, Node* effect,
213 : FeedbackNexus const& nexus,
214 : MapHandles* receiver_maps);
215 :
216 : // Try to infer maps for the given {receiver} at the current {effect}.
217 : bool InferReceiverMaps(Node* receiver, Node* effect,
218 : MapHandles* receiver_maps);
219 : // Try to infer a root map for the {receiver} independent of the current
220 : // program location.
221 : MaybeHandle<Map> InferReceiverRootMap(Node* receiver);
222 :
223 : // Checks if we know at compile time that the {receiver} either definitely
224 : // has the {prototype} in it's prototype chain, or the {receiver} definitely
225 : // doesn't have the {prototype} in it's prototype chain.
226 : enum InferHasInPrototypeChainResult {
227 : kIsInPrototypeChain,
228 : kIsNotInPrototypeChain,
229 : kMayBeInPrototypeChain
230 : };
231 : InferHasInPrototypeChainResult InferHasInPrototypeChain(
232 : Node* receiver, Node* effect, Handle<HeapObject> prototype);
233 :
234 : Graph* graph() const;
235 : JSGraph* jsgraph() const { return jsgraph_; }
236 :
237 : JSHeapBroker* broker() const { return broker_; }
238 : Isolate* isolate() const;
239 : Factory* factory() const;
240 : CommonOperatorBuilder* common() const;
241 : JSOperatorBuilder* javascript() const;
242 : SimplifiedOperatorBuilder* simplified() const;
243 : Flags flags() const { return flags_; }
244 : Handle<JSGlobalObject> global_object() const { return global_object_; }
245 : Handle<JSGlobalProxy> global_proxy() const { return global_proxy_; }
246 167262 : NativeContextRef native_context() const { return broker()->native_context(); }
247 : CompilationDependencies* dependencies() const { return dependencies_; }
248 : Zone* zone() const { return zone_; }
249 : Zone* shared_zone() const { return shared_zone_; }
250 :
251 : JSGraph* const jsgraph_;
252 : JSHeapBroker* const broker_;
253 : Flags const flags_;
254 : Handle<JSGlobalObject> global_object_;
255 : Handle<JSGlobalProxy> global_proxy_;
256 : CompilationDependencies* const dependencies_;
257 : Zone* const zone_;
258 : Zone* const shared_zone_;
259 : TypeCache const* type_cache_;
260 :
261 : DISALLOW_COPY_AND_ASSIGN(JSNativeContextSpecialization);
262 : };
263 :
264 : DEFINE_OPERATORS_FOR_FLAGS(JSNativeContextSpecialization::Flags)
265 :
266 : } // namespace compiler
267 : } // namespace internal
268 : } // namespace v8
269 :
270 : #endif // V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
|