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