• 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_CALL_REDUCER_H_
6 #define V8_COMPILER_JS_CALL_REDUCER_H_
7 
8 #include "src/base/flags.h"
9 #include "src/compiler/frame-states.h"
10 #include "src/compiler/globals.h"
11 #include "src/compiler/graph-reducer.h"
12 #include "src/compiler/node-properties.h"
13 #include "src/deoptimizer/deoptimize-reason.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 // Forward declarations.
19 class Factory;
20 class JSGlobalProxy;
21 
22 namespace compiler {
23 
24 // Forward declarations.
25 class CallFrequency;
26 class CommonOperatorBuilder;
27 class CompilationDependencies;
28 struct FeedbackSource;
29 struct FieldAccess;
30 class JSCallReducerAssembler;
31 class JSGraph;
32 class JSHeapBroker;
33 class JSOperatorBuilder;
34 class MapInference;
35 class NodeProperties;
36 class SimplifiedOperatorBuilder;
37 
38 // Performs strength reduction on {JSConstruct} and {JSCall} nodes,
39 // which might allow inlining or other optimizations to be performed afterwards.
40 class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
41  public:
42   // Flags that control the mode of operation.
43   enum Flag {
44     kNoFlags = 0u,
45     kBailoutOnUninitialized = 1u << 0,
46     kInlineJSToWasmCalls = 1u << 1,
47   };
48   using Flags = base::Flags<Flag>;
49 
JSCallReducer(Editor * editor,JSGraph * jsgraph,JSHeapBroker * broker,Zone * temp_zone,Flags flags)50   JSCallReducer(Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker,
51                 Zone* temp_zone, Flags flags)
52       : AdvancedReducer(editor),
53         jsgraph_(jsgraph),
54         broker_(broker),
55         temp_zone_(temp_zone),
56         flags_(flags) {}
57 
58   // Max string length for inlining entire match sequence for
59   // String.prototype.startsWith in JSCallReducer.
60   static constexpr int kMaxInlineMatchSequence = 3;
61 
reducer_name()62   const char* reducer_name() const override { return "JSCallReducer"; }
63 
64   Reduction Reduce(Node* node) final;
65 
66   // Processes the waitlist gathered while the reducer was running,
67   // and does a final attempt to reduce the nodes in the waitlist.
68   void Finalize() final;
69 
70   // JSCallReducer outsources much work to a graph assembler.
RevisitForGraphAssembler(Node * node)71   void RevisitForGraphAssembler(Node* node) { Revisit(node); }
ZoneForGraphAssembler()72   Zone* ZoneForGraphAssembler() const { return temp_zone(); }
JSGraphForGraphAssembler()73   JSGraph* JSGraphForGraphAssembler() const { return jsgraph(); }
74 
has_wasm_calls()75   bool has_wasm_calls() const { return has_wasm_calls_; }
76 
77   CompilationDependencies* dependencies() const;
78 
79  private:
80   Reduction ReduceBooleanConstructor(Node* node);
81   Reduction ReduceCallApiFunction(Node* node,
82                                   const SharedFunctionInfoRef& shared);
83   Reduction ReduceCallWasmFunction(Node* node,
84                                    const SharedFunctionInfoRef& shared);
85   Reduction ReduceFunctionPrototypeApply(Node* node);
86   Reduction ReduceFunctionPrototypeBind(Node* node);
87   Reduction ReduceFunctionPrototypeCall(Node* node);
88   Reduction ReduceFunctionPrototypeHasInstance(Node* node);
89   Reduction ReduceObjectConstructor(Node* node);
90   Reduction ReduceObjectGetPrototype(Node* node, Node* object);
91   Reduction ReduceObjectGetPrototypeOf(Node* node);
92   Reduction ReduceObjectIs(Node* node);
93   Reduction ReduceObjectPrototypeGetProto(Node* node);
94   Reduction ReduceObjectPrototypeHasOwnProperty(Node* node);
95   Reduction ReduceObjectPrototypeIsPrototypeOf(Node* node);
96   Reduction ReduceObjectCreate(Node* node);
97   Reduction ReduceReflectApply(Node* node);
98   Reduction ReduceReflectConstruct(Node* node);
99   Reduction ReduceReflectGet(Node* node);
100   Reduction ReduceReflectGetPrototypeOf(Node* node);
101   Reduction ReduceReflectHas(Node* node);
102 
103   Reduction ReduceArrayConstructor(Node* node);
104   Reduction ReduceArrayEvery(Node* node, const SharedFunctionInfoRef& shared);
105   Reduction ReduceArrayFilter(Node* node, const SharedFunctionInfoRef& shared);
106   Reduction ReduceArrayFindIndex(Node* node,
107                                  const SharedFunctionInfoRef& shared);
108   Reduction ReduceArrayFind(Node* node, const SharedFunctionInfoRef& shared);
109   Reduction ReduceArrayForEach(Node* node, const SharedFunctionInfoRef& shared);
110   Reduction ReduceArrayIncludes(Node* node);
111   Reduction ReduceArrayIndexOf(Node* node);
112   Reduction ReduceArrayIsArray(Node* node);
113   Reduction ReduceArrayMap(Node* node, const SharedFunctionInfoRef& shared);
114   Reduction ReduceArrayPrototypePop(Node* node);
115   Reduction ReduceArrayPrototypePush(Node* node);
116   Reduction ReduceArrayPrototypeShift(Node* node);
117   Reduction ReduceArrayPrototypeSlice(Node* node);
118   Reduction ReduceArrayReduce(Node* node, const SharedFunctionInfoRef& shared);
119   Reduction ReduceArrayReduceRight(Node* node,
120                                    const SharedFunctionInfoRef& shared);
121   Reduction ReduceArraySome(Node* node, const SharedFunctionInfoRef& shared);
122 
123   enum class ArrayIteratorKind { kArrayLike, kTypedArray };
124   Reduction ReduceArrayIterator(Node* node, ArrayIteratorKind array_kind,
125                                 IterationKind iteration_kind);
126   Reduction ReduceArrayIteratorPrototypeNext(Node* node);
127   Reduction ReduceFastArrayIteratorNext(InstanceType type, Node* node,
128                                         IterationKind kind);
129 
130   Reduction ReduceCallOrConstructWithArrayLikeOrSpreadOfCreateArguments(
131       Node* node, Node* arguments_list, int arraylike_or_spread_index,
132       CallFrequency const& frequency, FeedbackSource const& feedback,
133       SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation);
134   Reduction ReduceCallOrConstructWithArrayLikeOrSpread(
135       Node* node, int argument_count, int arraylike_or_spread_index,
136       CallFrequency const& frequency, FeedbackSource const& feedback_source,
137       SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation,
138       Node* target, Effect effect, Control control);
139   Reduction ReduceJSConstruct(Node* node);
140   Reduction ReduceJSConstructWithArrayLike(Node* node);
141   Reduction ReduceJSConstructWithSpread(Node* node);
142   Reduction ReduceJSCall(Node* node);
143   Reduction ReduceJSCall(Node* node, const SharedFunctionInfoRef& shared);
144   Reduction ReduceJSCallWithArrayLike(Node* node);
145   Reduction ReduceJSCallWithSpread(Node* node);
146   Reduction ReduceRegExpPrototypeTest(Node* node);
147   Reduction ReduceReturnReceiver(Node* node);
148 
149   enum class StringIndexOfIncludesVariant { kIncludes, kIndexOf };
150   Reduction ReduceStringPrototypeIndexOfIncludes(
151       Node* node, StringIndexOfIncludesVariant variant);
152   Reduction ReduceStringPrototypeSubstring(Node* node);
153   Reduction ReduceStringPrototypeSlice(Node* node);
154   Reduction ReduceStringPrototypeSubstr(Node* node);
155   Reduction ReduceStringPrototypeStringAt(
156       const Operator* string_access_operator, Node* node);
157   Reduction ReduceStringPrototypeCharAt(Node* node);
158   Reduction ReduceStringPrototypeStartsWith(Node* node);
159 
160 #ifdef V8_INTL_SUPPORT
161   Reduction ReduceStringPrototypeToLowerCaseIntl(Node* node);
162   Reduction ReduceStringPrototypeToUpperCaseIntl(Node* node);
163 #endif  // V8_INTL_SUPPORT
164 
165   Reduction ReduceStringFromCharCode(Node* node);
166   Reduction ReduceStringFromCodePoint(Node* node);
167   Reduction ReduceStringPrototypeIterator(Node* node);
168   Reduction ReduceStringPrototypeLocaleCompare(Node* node);
169   Reduction ReduceStringIteratorPrototypeNext(Node* node);
170   Reduction ReduceStringPrototypeConcat(Node* node);
171 
172   Reduction ReducePromiseConstructor(Node* node);
173   Reduction ReducePromiseInternalConstructor(Node* node);
174   Reduction ReducePromiseInternalReject(Node* node);
175   Reduction ReducePromiseInternalResolve(Node* node);
176   Reduction ReducePromisePrototypeCatch(Node* node);
177   Reduction ReducePromisePrototypeFinally(Node* node);
178   Reduction ReducePromisePrototypeThen(Node* node);
179   Reduction ReducePromiseResolveTrampoline(Node* node);
180 
181   Reduction ReduceTypedArrayConstructor(Node* node,
182                                         const SharedFunctionInfoRef& shared);
183   Reduction ReduceTypedArrayPrototypeToStringTag(Node* node);
184 
185   Reduction ReduceForInsufficientFeedback(Node* node, DeoptimizeReason reason);
186 
187   Reduction ReduceMathUnary(Node* node, const Operator* op);
188   Reduction ReduceMathBinary(Node* node, const Operator* op);
189   Reduction ReduceMathImul(Node* node);
190   Reduction ReduceMathClz32(Node* node);
191   Reduction ReduceMathMinMax(Node* node, const Operator* op, Node* empty_value);
192 
193   Reduction ReduceNumberIsFinite(Node* node);
194   Reduction ReduceNumberIsInteger(Node* node);
195   Reduction ReduceNumberIsSafeInteger(Node* node);
196   Reduction ReduceNumberIsNaN(Node* node);
197 
198   Reduction ReduceGlobalIsFinite(Node* node);
199   Reduction ReduceGlobalIsNaN(Node* node);
200 
201   Reduction ReduceMapPrototypeHas(Node* node);
202   Reduction ReduceMapPrototypeGet(Node* node);
203   Reduction ReduceCollectionIteration(Node* node,
204                                       CollectionKind collection_kind,
205                                       IterationKind iteration_kind);
206   Reduction ReduceCollectionPrototypeSize(Node* node,
207                                           CollectionKind collection_kind);
208   Reduction ReduceCollectionIteratorPrototypeNext(
209       Node* node, int entry_size, Handle<HeapObject> empty_collection,
210       InstanceType collection_iterator_instance_type_first,
211       InstanceType collection_iterator_instance_type_last);
212 
213   Reduction ReduceArrayBufferIsView(Node* node);
214   Reduction ReduceArrayBufferViewAccessor(Node* node,
215                                           InstanceType instance_type,
216                                           FieldAccess const& access);
217 
218   enum class DataViewAccess { kGet, kSet };
219   Reduction ReduceDataViewAccess(Node* node, DataViewAccess access,
220                                  ExternalArrayType element_type);
221 
222   Reduction ReduceDatePrototypeGetTime(Node* node);
223   Reduction ReduceDateNow(Node* node);
224   Reduction ReduceNumberParseInt(Node* node);
225 
226   Reduction ReduceNumberConstructor(Node* node);
227   Reduction ReduceBigIntAsN(Node* node, Builtin builtin);
228 
229   // The pendant to ReplaceWithValue when using GraphAssembler-based reductions.
230   Reduction ReplaceWithSubgraph(JSCallReducerAssembler* gasm, Node* subgraph);
231 
232   // Helper to verify promise receiver maps are as expected.
233   // On bailout from a reduction, be sure to return inference.NoChange().
234   bool DoPromiseChecks(MapInference* inference);
235 
236   Node* CreateClosureFromBuiltinSharedFunctionInfo(SharedFunctionInfoRef shared,
237                                                    Node* context, Node* effect,
238                                                    Node* control);
239 
240   void CheckIfElementsKind(Node* receiver_elements_kind, ElementsKind kind,
241                            Node* control, Node** if_true, Node** if_false);
242   Node* LoadReceiverElementsKind(Node* receiver, Effect* effect,
243                                  Control control);
244 
245   bool IsBuiltinOrApiFunction(JSFunctionRef target_ref) const;
246 
247   // Check whether an array has the expected length. Returns the new effect.
248   Node* CheckArrayLength(Node* array, ElementsKind elements_kind,
249                          uint32_t array_length,
250                          const FeedbackSource& feedback_source, Effect effect,
251                          Control control);
252 
253   // Check whether the given new target value is a constructor function.
254   void CheckIfConstructor(Node* call);
255 
256   Graph* graph() const;
jsgraph()257   JSGraph* jsgraph() const { return jsgraph_; }
broker()258   JSHeapBroker* broker() const { return broker_; }
temp_zone()259   Zone* temp_zone() const { return temp_zone_; }
260   Isolate* isolate() const;
261   Factory* factory() const;
262   NativeContextRef native_context() const;
263   CommonOperatorBuilder* common() const;
264   JSOperatorBuilder* javascript() const;
265   SimplifiedOperatorBuilder* simplified() const;
flags()266   Flags flags() const { return flags_; }
267 
268   JSGraph* const jsgraph_;
269   JSHeapBroker* const broker_;
270   Zone* const temp_zone_;
271   Flags const flags_;
272   std::set<Node*> waitlist_;
273 
274   // For preventing infinite recursion via ReduceJSCallWithArrayLikeOrSpread.
275   std::unordered_set<Node*> generated_calls_with_array_like_or_spread_;
276 
277   bool has_wasm_calls_ = false;
278 };
279 
280 }  // namespace compiler
281 }  // namespace internal
282 }  // namespace v8
283 
284 #endif  // V8_COMPILER_JS_CALL_REDUCER_H_
285