blob: 3d0c3472618c0c97efff5a74f8e43567f1763bfd [file] [log] [blame]
Ben Murdoch014dc512016-03-22 12:00:34 +00001// 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"
Rubin Xu6e1e26a2021-02-10 00:04:48 +000010#include "src/compiler/js-heap-broker.h"
11#include "src/deoptimizer/deoptimize-reason.h"
Rubin Xu2894c6a2019-02-07 16:01:35 +000012#include "src/objects/map.h"
Ben Murdoch014dc512016-03-22 12:00:34 +000013
14namespace v8 {
15namespace internal {
16
17// Forward declarations.
Ben Murdoch014dc512016-03-22 12:00:34 +000018class Factory;
Rubin Xu6e1e26a2021-02-10 00:04:48 +000019class JSGlobalObject;
20class JSGlobalProxy;
21class StringConstantBase;
Ben Murdoch014dc512016-03-22 12:00:34 +000022
23namespace compiler {
24
25// Forward declarations.
26enum class AccessMode;
27class CommonOperatorBuilder;
Rubin Xu2894c6a2019-02-07 16:01:35 +000028class CompilationDependencies;
Ben Murdochf91f0612016-11-29 16:50:11 +000029class ElementAccessInfo;
Ben Murdoch014dc512016-03-22 12:00:34 +000030class JSGraph;
Rubin Xu2894c6a2019-02-07 16:01:35 +000031class JSHeapBroker;
Ben Murdoch014dc512016-03-22 12:00:34 +000032class JSOperatorBuilder;
33class MachineOperatorBuilder;
Ben Murdochf91f0612016-11-29 16:50:11 +000034class PropertyAccessInfo;
Ben Murdoch014dc512016-03-22 12:00:34 +000035class SimplifiedOperatorBuilder;
Ben Murdochf3b273f2017-01-17 12:11:28 +000036class TypeCache;
Ben Murdoch014dc512016-03-22 12:00:34 +000037
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).
Rubin Xu6e1e26a2021-02-10 00:04:48 +000042class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
43 : public AdvancedReducer {
Ben Murdoch014dc512016-03-22 12:00:34 +000044 public:
45 // Flags that control the mode of operation.
46 enum Flag {
47 kNoFlags = 0u,
Rubin Xu6e1e26a2021-02-10 00:04:48 +000048 kBailoutOnUninitialized = 1u << 0,
Ben Murdoch014dc512016-03-22 12:00:34 +000049 };
Rubin Xu6e1e26a2021-02-10 00:04:48 +000050 using Flags = base::Flags<Flag>;
Ben Murdoch014dc512016-03-22 12:00:34 +000051
Rubin Xu2894c6a2019-02-07 16:01:35 +000052 JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph,
Rubin Xu6e1e26a2021-02-10 00:04:48 +000053 JSHeapBroker* broker, Flags flags,
Ben Murdoch014dc512016-03-22 12:00:34 +000054 CompilationDependencies* dependencies,
Rubin Xu6e1e26a2021-02-10 00:04:48 +000055 Zone* zone, Zone* shared_zone);
56 JSNativeContextSpecialization(const JSNativeContextSpecialization&) = delete;
57 JSNativeContextSpecialization& operator=(
58 const JSNativeContextSpecialization&) = delete;
Ben Murdoch014dc512016-03-22 12:00:34 +000059
Rubin Xu2894c6a2019-02-07 16:01:35 +000060 const char* reducer_name() const override {
61 return "JSNativeContextSpecialization";
62 }
63
Ben Murdoch014dc512016-03-22 12:00:34 +000064 Reduction Reduce(Node* node) final;
65
Rubin Xu6e1e26a2021-02-10 00:04:48 +000066 // 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
Ben Murdoch014dc512016-03-22 12:00:34 +000072 private:
Ben Murdoch62ed6312017-06-06 11:06:27 +010073 Reduction ReduceJSAdd(Node* node);
Rubin Xu6e1e26a2021-02-10 00:04:48 +000074 Reduction ReduceJSAsyncFunctionEnter(Node* node);
75 Reduction ReduceJSAsyncFunctionReject(Node* node);
76 Reduction ReduceJSAsyncFunctionResolve(Node* node);
Ben Murdoch62ed6312017-06-06 11:06:27 +010077 Reduction ReduceJSGetSuperConstructor(Node* node);
Ben Murdochf3b273f2017-01-17 12:11:28 +000078 Reduction ReduceJSInstanceOf(Node* node);
Rubin Xu2894c6a2019-02-07 16:01:35 +000079 Reduction ReduceJSHasInPrototypeChain(Node* node);
Ben Murdoch62ed6312017-06-06 11:06:27 +010080 Reduction ReduceJSOrdinaryHasInstance(Node* node);
Rubin Xu2894c6a2019-02-07 16:01:35 +000081 Reduction ReduceJSPromiseResolve(Node* node);
82 Reduction ReduceJSResolvePromise(Node* node);
Ben Murdoch62ed6312017-06-06 11:06:27 +010083 Reduction ReduceJSLoadGlobal(Node* node);
84 Reduction ReduceJSStoreGlobal(Node* node);
Ben Murdoch014dc512016-03-22 12:00:34 +000085 Reduction ReduceJSLoadNamed(Node* node);
Rubin Xu6e1e26a2021-02-10 00:04:48 +000086 Reduction ReduceJSLoadNamedFromSuper(Node* node);
87 Reduction ReduceJSGetIterator(Node* node);
Ben Murdoch014dc512016-03-22 12:00:34 +000088 Reduction ReduceJSStoreNamed(Node* node);
Rubin Xu6e1e26a2021-02-10 00:04:48 +000089 Reduction ReduceJSHasProperty(Node* node);
Ben Murdoch014dc512016-03-22 12:00:34 +000090 Reduction ReduceJSLoadProperty(Node* node);
91 Reduction ReduceJSStoreProperty(Node* node);
Ben Murdoch62ed6312017-06-06 11:06:27 +010092 Reduction ReduceJSStoreNamedOwn(Node* node);
93 Reduction ReduceJSStoreDataPropertyInLiteral(Node* node);
Rubin Xu2894c6a2019-02-07 16:01:35 +000094 Reduction ReduceJSStoreInArrayLiteral(Node* node);
95 Reduction ReduceJSToObject(Node* node);
Ben Murdoch014dc512016-03-22 12:00:34 +000096
97 Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
Rubin Xu6e1e26a2021-02-10 00:04:48 +000098 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);
Ben Murdoch109988c2016-05-18 11:27:45 +0100105 Reduction ReduceNamedAccess(Node* node, Node* value,
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000106 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);
Ben Murdoch014dc512016-03-22 12:00:34 +0000126
Ben Murdochf91f0612016-11-29 16:50:11 +0000127 Reduction ReduceSoftDeoptimize(Node* node, DeoptimizeReason reason);
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000128 Reduction ReduceJSToString(Node* node);
129
130 Reduction ReduceJSLoadPropertyWithEnumeratedKey(Node* node);
131
132 const StringConstantBase* CreateDelayedStringConstant(Node* node);
Ben Murdochf91f0612016-11-29 16:50:11 +0000133
134 // A triple of nodes that represents a continuation.
135 class ValueEffectControl final {
136 public:
Rubin Xu2894c6a2019-02-07 16:01:35 +0000137 ValueEffectControl()
138 : value_(nullptr), effect_(nullptr), control_(nullptr) {}
Ben Murdochf91f0612016-11-29 16:50:11 +0000139 ValueEffectControl(Node* value, Node* effect, Node* control)
140 : value_(value), effect_(effect), control_(control) {}
141
142 Node* value() const { return value_; }
143 Node* effect() const { return effect_; }
144 Node* control() const { return control_; }
145
146 private:
Rubin Xu2894c6a2019-02-07 16:01:35 +0000147 Node* value_;
148 Node* effect_;
149 Node* control_;
Ben Murdochf91f0612016-11-29 16:50:11 +0000150 };
151
152 // Construct the appropriate subgraph for property access.
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000153 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,
Rubin Xu2894c6a2019-02-07 16:01:35 +0000160 Node* frame_state, Node* effect,
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000161 Node* control, NameRef const& name,
Rubin Xu2894c6a2019-02-07 16:01:35 +0000162 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,
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000168 NameRef const& name,
Rubin Xu2894c6a2019-02-07 16:01:35 +0000169 ZoneVector<Node*>* if_exceptions,
170 PropertyAccessInfo const& access_info,
171 AccessMode access_mode);
172
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000173 ValueEffectControl BuildPropertyTest(Node* effect, Node* control,
174 PropertyAccessInfo const& access_info);
175
Rubin Xu2894c6a2019-02-07 16:01:35 +0000176 // 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,
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000189 SharedFunctionInfoRef const& shared_info,
190 FunctionTemplateInfoRef const& function_template_info);
Ben Murdochf91f0612016-11-29 16:50:11 +0000191
192 // Construct the appropriate subgraph for element access.
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000193 ValueEffectControl BuildElementAccess(Node* receiver, Node* index,
194 Node* value, Node* effect,
195 Node* control,
196 ElementAccessInfo const& access_info,
197 KeyedAccessMode const& keyed_mode);
Ben Murdochf91f0612016-11-29 16:50:11 +0000198
Rubin Xu2894c6a2019-02-07 16:01:35 +0000199 // 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);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100203
Rubin Xu2894c6a2019-02-07 16:01:35 +0000204 // Construct appropriate subgraph to extend properties backing store.
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000205 Node* BuildExtendPropertiesBackingStore(const MapRef& map, Node* properties,
Rubin Xu2894c6a2019-02-07 16:01:35 +0000206 Node* effect, Node* control);
Ben Murdochf91f0612016-11-29 16:50:11 +0000207
Rubin Xu2894c6a2019-02-07 16:01:35 +0000208 // Construct appropriate subgraph to check that the {value} matches
209 // the previously recorded {name} feedback.
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000210 Node* BuildCheckEqualsName(NameRef const& name, Node* value, Node* effect,
Rubin Xu2894c6a2019-02-07 16:01:35 +0000211 Node* control);
Ben Murdoch014dc512016-03-22 12:00:34 +0000212
Ben Murdochf91f0612016-11-29 16:50:11 +0000213 // 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.
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000216 bool CanTreatHoleAsUndefined(ZoneVector<Handle<Map>> const& receiver_maps);
Ben Murdochf91f0612016-11-29 16:50:11 +0000217
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000218 void RemoveImpossibleMaps(Node* object, ZoneVector<Handle<Map>>* maps) const;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100219
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000220 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;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100231
Rubin Xu2894c6a2019-02-07 16:01:35 +0000232 // 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(
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000241 Node* receiver, Node* effect, HeapObjectRef const& prototype);
Ben Murdoch014dc512016-03-22 12:00:34 +0000242
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000243 Node* BuildLoadPrototypeFromObject(Node* object, Node* effect, Node* control);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100244
Ben Murdoch014dc512016-03-22 12:00:34 +0000245 Graph* graph() const;
246 JSGraph* jsgraph() const { return jsgraph_; }
Rubin Xu2894c6a2019-02-07 16:01:35 +0000247
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000248 JSHeapBroker* broker() const { return broker_; }
Ben Murdoch014dc512016-03-22 12:00:34 +0000249 Isolate* isolate() const;
250 Factory* factory() const;
251 CommonOperatorBuilder* common() const;
252 JSOperatorBuilder* javascript() const;
253 SimplifiedOperatorBuilder* simplified() const;
Ben Murdoch014dc512016-03-22 12:00:34 +0000254 Flags flags() const { return flags_; }
Ben Murdoch62ed6312017-06-06 11:06:27 +0100255 Handle<JSGlobalObject> global_object() const { return global_object_; }
256 Handle<JSGlobalProxy> global_proxy() const { return global_proxy_; }
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000257 NativeContextRef native_context() const {
258 return broker()->target_native_context();
259 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000260 CompilationDependencies* dependencies() const { return dependencies_; }
261 Zone* zone() const { return zone_; }
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000262 Zone* shared_zone() const { return shared_zone_; }
263 bool should_disallow_heap_access() const;
Ben Murdoch014dc512016-03-22 12:00:34 +0000264
265 JSGraph* const jsgraph_;
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000266 JSHeapBroker* const broker_;
Ben Murdoch014dc512016-03-22 12:00:34 +0000267 Flags const flags_;
Ben Murdoch62ed6312017-06-06 11:06:27 +0100268 Handle<JSGlobalObject> global_object_;
269 Handle<JSGlobalProxy> global_proxy_;
Ben Murdoch014dc512016-03-22 12:00:34 +0000270 CompilationDependencies* const dependencies_;
271 Zone* const zone_;
Rubin Xu6e1e26a2021-02-10 00:04:48 +0000272 Zone* const shared_zone_;
273 TypeCache const* type_cache_;
Ben Murdoch014dc512016-03-22 12:00:34 +0000274};
275
276DEFINE_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_