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   };
47   using Flags = base::Flags<Flag>;
48 
JSCallReducer(Editor * editor,JSGraph * jsgraph,JSHeapBroker * broker,Zone * temp_zone,Flags flags,CompilationDependencies * dependencies)49   JSCallReducer(Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker,
50                 Zone* temp_zone, Flags flags,
51                 CompilationDependencies* dependencies)
52       : AdvancedReducer(editor),
53         jsgraph_(jsgraph),
54         broker_(broker),
55         temp_zone_(temp_zone),
56         flags_(flags),
57         dependencies_(dependencies) {}
58 
reducer_name()59   const char* reducer_name() const override { return "JSCallReducer"; }
60 
61   Reduction Reduce(Node* node) final;
62 
63   // Processes the waitlist gathered while the reducer was running,
64   // and does a final attempt to reduce the nodes in the waitlist.
65   void Finalize() final;
66 
67  private:
68   Reduction ReduceBooleanConstructor(Node* node);
69   Reduction ReduceCallApiFunction(Node* node,
70                                   const SharedFunctionInfoRef& shared);
71   Reduction ReduceFunctionPrototypeApply(Node* node);
72   Reduction ReduceFunctionPrototypeBind(Node* node);
73   Reduction ReduceFunctionPrototypeCall(Node* node);
74   Reduction ReduceFunctionPrototypeHasInstance(Node* node);
75   Reduction ReduceObjectConstructor(Node* node);
76   Reduction ReduceObjectGetPrototype(Node* node, Node* object);
77   Reduction ReduceObjectGetPrototypeOf(Node* node);
78   Reduction ReduceObjectIs(Node* node);
79   Reduction ReduceObjectPrototypeGetProto(Node* node);
80   Reduction ReduceObjectPrototypeHasOwnProperty(Node* node);
81   Reduction ReduceObjectPrototypeIsPrototypeOf(Node* node);
82   Reduction ReduceObjectCreate(Node* node);
83   Reduction ReduceReflectApply(Node* node);
84   Reduction ReduceReflectConstruct(Node* node);
85   Reduction ReduceReflectGet(Node* node);
86   Reduction ReduceReflectGetPrototypeOf(Node* node);
87   Reduction ReduceReflectHas(Node* node);
88 
89   Reduction ReduceArrayConstructor(Node* node);
90   Reduction ReduceArrayEvery(Node* node, const SharedFunctionInfoRef& shared);
91   Reduction ReduceArrayFilter(Node* node, const SharedFunctionInfoRef& shared);
92   Reduction ReduceArrayFindIndex(Node* node,
93                                  const SharedFunctionInfoRef& shared);
94   Reduction ReduceArrayFind(Node* node, const SharedFunctionInfoRef& shared);
95   Reduction ReduceArrayForEach(Node* node, const SharedFunctionInfoRef& shared);
96   Reduction ReduceArrayIncludes(Node* node);
97   Reduction ReduceArrayIndexOf(Node* node);
98   Reduction ReduceArrayIsArray(Node* node);
99   Reduction ReduceArrayMap(Node* node, const SharedFunctionInfoRef& shared);
100   Reduction ReduceArrayPrototypePop(Node* node);
101   Reduction ReduceArrayPrototypePush(Node* node);
102   Reduction ReduceArrayPrototypeShift(Node* node);
103   Reduction ReduceArrayPrototypeSlice(Node* node);
104   Reduction ReduceArrayReduce(Node* node, const SharedFunctionInfoRef& shared);
105   Reduction ReduceArrayReduceRight(Node* node,
106                                    const SharedFunctionInfoRef& shared);
107   Reduction ReduceArraySome(Node* node, const SharedFunctionInfoRef& shared);
108 
109   enum class ArrayIteratorKind { kArray, kTypedArray };
110   Reduction ReduceArrayIterator(Node* node, IterationKind kind);
111   Reduction ReduceArrayIteratorPrototypeNext(Node* node);
112   Reduction ReduceFastArrayIteratorNext(InstanceType type, Node* node,
113                                         IterationKind kind);
114 
115   Reduction ReduceCallOrConstructWithArrayLikeOrSpread(
116       Node* node, int arity, CallFrequency const& frequency,
117       FeedbackSource const& feedback, SpeculationMode speculation_mode,
118       CallFeedbackRelation feedback_relation);
119   Reduction ReduceJSConstruct(Node* node);
120   Reduction ReduceJSConstructWithArrayLike(Node* node);
121   Reduction ReduceJSConstructWithSpread(Node* node);
122   Reduction ReduceJSCall(Node* node);
123   Reduction ReduceJSCall(Node* node, const SharedFunctionInfoRef& shared);
124   Reduction ReduceJSCallWithArrayLike(Node* node);
125   Reduction ReduceJSCallWithSpread(Node* node);
126   Reduction ReduceRegExpPrototypeTest(Node* node);
127   Reduction ReduceReturnReceiver(Node* node);
128   Reduction ReduceStringPrototypeIndexOf(Node* node);
129   Reduction ReduceStringPrototypeSubstring(Node* node);
130   Reduction ReduceStringPrototypeSlice(Node* node);
131   Reduction ReduceStringPrototypeSubstr(Node* node);
132   Reduction ReduceStringPrototypeStringAt(
133       const Operator* string_access_operator, Node* node);
134   Reduction ReduceStringPrototypeCharAt(Node* node);
135   Reduction ReduceStringPrototypeStartsWith(Node* node);
136 
137 #ifdef V8_INTL_SUPPORT
138   Reduction ReduceStringPrototypeToLowerCaseIntl(Node* node);
139   Reduction ReduceStringPrototypeToUpperCaseIntl(Node* node);
140 #endif  // V8_INTL_SUPPORT
141 
142   Reduction ReduceStringFromCharCode(Node* node);
143   Reduction ReduceStringFromCodePoint(Node* node);
144   Reduction ReduceStringPrototypeIterator(Node* node);
145   Reduction ReduceStringIteratorPrototypeNext(Node* node);
146   Reduction ReduceStringPrototypeConcat(Node* node);
147 
148   Reduction ReducePromiseConstructor(Node* node);
149   Reduction ReducePromiseInternalConstructor(Node* node);
150   Reduction ReducePromiseInternalReject(Node* node);
151   Reduction ReducePromiseInternalResolve(Node* node);
152   Reduction ReducePromisePrototypeCatch(Node* node);
153   Reduction ReducePromisePrototypeFinally(Node* node);
154   Reduction ReducePromisePrototypeThen(Node* node);
155   Reduction ReducePromiseResolveTrampoline(Node* node);
156 
157   Reduction ReduceTypedArrayConstructor(Node* node,
158                                         const SharedFunctionInfoRef& shared);
159   Reduction ReduceTypedArrayPrototypeToStringTag(Node* node);
160 
161   Reduction ReduceSoftDeoptimize(Node* node, DeoptimizeReason reason);
162 
163   Reduction ReduceMathUnary(Node* node, const Operator* op);
164   Reduction ReduceMathBinary(Node* node, const Operator* op);
165   Reduction ReduceMathImul(Node* node);
166   Reduction ReduceMathClz32(Node* node);
167   Reduction ReduceMathMinMax(Node* node, const Operator* op, Node* empty_value);
168 
169   Reduction ReduceNumberIsFinite(Node* node);
170   Reduction ReduceNumberIsInteger(Node* node);
171   Reduction ReduceNumberIsSafeInteger(Node* node);
172   Reduction ReduceNumberIsNaN(Node* node);
173 
174   Reduction ReduceGlobalIsFinite(Node* node);
175   Reduction ReduceGlobalIsNaN(Node* node);
176 
177   Reduction ReduceMapPrototypeHas(Node* node);
178   Reduction ReduceMapPrototypeGet(Node* node);
179   Reduction ReduceCollectionIteration(Node* node,
180                                       CollectionKind collection_kind,
181                                       IterationKind iteration_kind);
182   Reduction ReduceCollectionPrototypeSize(Node* node,
183                                           CollectionKind collection_kind);
184   Reduction ReduceCollectionIteratorPrototypeNext(
185       Node* node, int entry_size, Handle<HeapObject> empty_collection,
186       InstanceType collection_iterator_instance_type_first,
187       InstanceType collection_iterator_instance_type_last);
188 
189   Reduction ReduceArrayBufferIsView(Node* node);
190   Reduction ReduceArrayBufferViewAccessor(Node* node,
191                                           InstanceType instance_type,
192                                           FieldAccess const& access);
193 
194   enum class DataViewAccess { kGet, kSet };
195   Reduction ReduceDataViewAccess(Node* node, DataViewAccess access,
196                                  ExternalArrayType element_type);
197 
198   Reduction ReduceDatePrototypeGetTime(Node* node);
199   Reduction ReduceDateNow(Node* node);
200   Reduction ReduceNumberParseInt(Node* node);
201 
202   Reduction ReduceNumberConstructor(Node* node);
203   Reduction ReduceBigIntAsUintN(Node* node);
204 
205   // The pendant to ReplaceWithValue when using GraphAssembler-based reductions.
206   Reduction ReplaceWithSubgraph(JSCallReducerAssembler* gasm, Node* subgraph);
207 
208   // Helper to verify promise receiver maps are as expected.
209   // On bailout from a reduction, be sure to return inference.NoChange().
210   bool DoPromiseChecks(MapInference* inference);
211 
212   Node* CreateClosureFromBuiltinSharedFunctionInfo(SharedFunctionInfoRef shared,
213                                                    Node* context, Node* effect,
214                                                    Node* control);
215 
216   void CheckIfElementsKind(Node* receiver_elements_kind, ElementsKind kind,
217                            Node* control, Node** if_true, Node** if_false);
218   Node* LoadReceiverElementsKind(Node* receiver, Node** effect, Node** control);
219 
220   Graph* graph() const;
jsgraph()221   JSGraph* jsgraph() const { return jsgraph_; }
broker()222   JSHeapBroker* broker() const { return broker_; }
temp_zone()223   Zone* temp_zone() const { return temp_zone_; }
224   Isolate* isolate() const;
225   Factory* factory() const;
226   NativeContextRef native_context() const;
227   CommonOperatorBuilder* common() const;
228   JSOperatorBuilder* javascript() const;
229   SimplifiedOperatorBuilder* simplified() const;
flags()230   Flags flags() const { return flags_; }
dependencies()231   CompilationDependencies* dependencies() const { return dependencies_; }
232   bool should_disallow_heap_access() const;
233 
234   JSGraph* const jsgraph_;
235   JSHeapBroker* const broker_;
236   Zone* const temp_zone_;
237   Flags const flags_;
238   CompilationDependencies* const dependencies_;
239   std::set<Node*> waitlist_;
240 };
241 
242 }  // namespace compiler
243 }  // namespace internal
244 }  // namespace v8
245 
246 #endif  // V8_COMPILER_JS_CALL_REDUCER_H_
247