11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_JS_CALL_REDUCER_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_JS_CALL_REDUCER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/flags.h" 91cb0ef41Sopenharmony_ci#include "src/compiler/frame-states.h" 101cb0ef41Sopenharmony_ci#include "src/compiler/globals.h" 111cb0ef41Sopenharmony_ci#include "src/compiler/graph-reducer.h" 121cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h" 131cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimize-reason.h" 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cinamespace v8 { 161cb0ef41Sopenharmony_cinamespace internal { 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci// Forward declarations. 191cb0ef41Sopenharmony_ciclass Factory; 201cb0ef41Sopenharmony_ciclass JSGlobalProxy; 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cinamespace compiler { 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci// Forward declarations. 251cb0ef41Sopenharmony_ciclass CallFrequency; 261cb0ef41Sopenharmony_ciclass CommonOperatorBuilder; 271cb0ef41Sopenharmony_ciclass CompilationDependencies; 281cb0ef41Sopenharmony_cistruct FeedbackSource; 291cb0ef41Sopenharmony_cistruct FieldAccess; 301cb0ef41Sopenharmony_ciclass JSCallReducerAssembler; 311cb0ef41Sopenharmony_ciclass JSGraph; 321cb0ef41Sopenharmony_ciclass JSHeapBroker; 331cb0ef41Sopenharmony_ciclass JSOperatorBuilder; 341cb0ef41Sopenharmony_ciclass MapInference; 351cb0ef41Sopenharmony_ciclass NodeProperties; 361cb0ef41Sopenharmony_ciclass SimplifiedOperatorBuilder; 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci// Performs strength reduction on {JSConstruct} and {JSCall} nodes, 391cb0ef41Sopenharmony_ci// which might allow inlining or other optimizations to be performed afterwards. 401cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { 411cb0ef41Sopenharmony_ci public: 421cb0ef41Sopenharmony_ci // Flags that control the mode of operation. 431cb0ef41Sopenharmony_ci enum Flag { 441cb0ef41Sopenharmony_ci kNoFlags = 0u, 451cb0ef41Sopenharmony_ci kBailoutOnUninitialized = 1u << 0, 461cb0ef41Sopenharmony_ci kInlineJSToWasmCalls = 1u << 1, 471cb0ef41Sopenharmony_ci }; 481cb0ef41Sopenharmony_ci using Flags = base::Flags<Flag>; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci JSCallReducer(Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker, 511cb0ef41Sopenharmony_ci Zone* temp_zone, Flags flags) 521cb0ef41Sopenharmony_ci : AdvancedReducer(editor), 531cb0ef41Sopenharmony_ci jsgraph_(jsgraph), 541cb0ef41Sopenharmony_ci broker_(broker), 551cb0ef41Sopenharmony_ci temp_zone_(temp_zone), 561cb0ef41Sopenharmony_ci flags_(flags) {} 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci // Max string length for inlining entire match sequence for 591cb0ef41Sopenharmony_ci // String.prototype.startsWith in JSCallReducer. 601cb0ef41Sopenharmony_ci static constexpr int kMaxInlineMatchSequence = 3; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci const char* reducer_name() const override { return "JSCallReducer"; } 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci Reduction Reduce(Node* node) final; 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci // Processes the waitlist gathered while the reducer was running, 671cb0ef41Sopenharmony_ci // and does a final attempt to reduce the nodes in the waitlist. 681cb0ef41Sopenharmony_ci void Finalize() final; 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci // JSCallReducer outsources much work to a graph assembler. 711cb0ef41Sopenharmony_ci void RevisitForGraphAssembler(Node* node) { Revisit(node); } 721cb0ef41Sopenharmony_ci Zone* ZoneForGraphAssembler() const { return temp_zone(); } 731cb0ef41Sopenharmony_ci JSGraph* JSGraphForGraphAssembler() const { return jsgraph(); } 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci bool has_wasm_calls() const { return has_wasm_calls_; } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci CompilationDependencies* dependencies() const; 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci private: 801cb0ef41Sopenharmony_ci Reduction ReduceBooleanConstructor(Node* node); 811cb0ef41Sopenharmony_ci Reduction ReduceCallApiFunction(Node* node, 821cb0ef41Sopenharmony_ci const SharedFunctionInfoRef& shared); 831cb0ef41Sopenharmony_ci Reduction ReduceCallWasmFunction(Node* node, 841cb0ef41Sopenharmony_ci const SharedFunctionInfoRef& shared); 851cb0ef41Sopenharmony_ci Reduction ReduceFunctionPrototypeApply(Node* node); 861cb0ef41Sopenharmony_ci Reduction ReduceFunctionPrototypeBind(Node* node); 871cb0ef41Sopenharmony_ci Reduction ReduceFunctionPrototypeCall(Node* node); 881cb0ef41Sopenharmony_ci Reduction ReduceFunctionPrototypeHasInstance(Node* node); 891cb0ef41Sopenharmony_ci Reduction ReduceObjectConstructor(Node* node); 901cb0ef41Sopenharmony_ci Reduction ReduceObjectGetPrototype(Node* node, Node* object); 911cb0ef41Sopenharmony_ci Reduction ReduceObjectGetPrototypeOf(Node* node); 921cb0ef41Sopenharmony_ci Reduction ReduceObjectIs(Node* node); 931cb0ef41Sopenharmony_ci Reduction ReduceObjectPrototypeGetProto(Node* node); 941cb0ef41Sopenharmony_ci Reduction ReduceObjectPrototypeHasOwnProperty(Node* node); 951cb0ef41Sopenharmony_ci Reduction ReduceObjectPrototypeIsPrototypeOf(Node* node); 961cb0ef41Sopenharmony_ci Reduction ReduceObjectCreate(Node* node); 971cb0ef41Sopenharmony_ci Reduction ReduceReflectApply(Node* node); 981cb0ef41Sopenharmony_ci Reduction ReduceReflectConstruct(Node* node); 991cb0ef41Sopenharmony_ci Reduction ReduceReflectGet(Node* node); 1001cb0ef41Sopenharmony_ci Reduction ReduceReflectGetPrototypeOf(Node* node); 1011cb0ef41Sopenharmony_ci Reduction ReduceReflectHas(Node* node); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci Reduction ReduceArrayConstructor(Node* node); 1041cb0ef41Sopenharmony_ci Reduction ReduceArrayEvery(Node* node, const SharedFunctionInfoRef& shared); 1051cb0ef41Sopenharmony_ci Reduction ReduceArrayFilter(Node* node, const SharedFunctionInfoRef& shared); 1061cb0ef41Sopenharmony_ci Reduction ReduceArrayFindIndex(Node* node, 1071cb0ef41Sopenharmony_ci const SharedFunctionInfoRef& shared); 1081cb0ef41Sopenharmony_ci Reduction ReduceArrayFind(Node* node, const SharedFunctionInfoRef& shared); 1091cb0ef41Sopenharmony_ci Reduction ReduceArrayForEach(Node* node, const SharedFunctionInfoRef& shared); 1101cb0ef41Sopenharmony_ci Reduction ReduceArrayIncludes(Node* node); 1111cb0ef41Sopenharmony_ci Reduction ReduceArrayIndexOf(Node* node); 1121cb0ef41Sopenharmony_ci Reduction ReduceArrayIsArray(Node* node); 1131cb0ef41Sopenharmony_ci Reduction ReduceArrayMap(Node* node, const SharedFunctionInfoRef& shared); 1141cb0ef41Sopenharmony_ci Reduction ReduceArrayPrototypePop(Node* node); 1151cb0ef41Sopenharmony_ci Reduction ReduceArrayPrototypePush(Node* node); 1161cb0ef41Sopenharmony_ci Reduction ReduceArrayPrototypeShift(Node* node); 1171cb0ef41Sopenharmony_ci Reduction ReduceArrayPrototypeSlice(Node* node); 1181cb0ef41Sopenharmony_ci Reduction ReduceArrayReduce(Node* node, const SharedFunctionInfoRef& shared); 1191cb0ef41Sopenharmony_ci Reduction ReduceArrayReduceRight(Node* node, 1201cb0ef41Sopenharmony_ci const SharedFunctionInfoRef& shared); 1211cb0ef41Sopenharmony_ci Reduction ReduceArraySome(Node* node, const SharedFunctionInfoRef& shared); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci enum class ArrayIteratorKind { kArrayLike, kTypedArray }; 1241cb0ef41Sopenharmony_ci Reduction ReduceArrayIterator(Node* node, ArrayIteratorKind array_kind, 1251cb0ef41Sopenharmony_ci IterationKind iteration_kind); 1261cb0ef41Sopenharmony_ci Reduction ReduceArrayIteratorPrototypeNext(Node* node); 1271cb0ef41Sopenharmony_ci Reduction ReduceFastArrayIteratorNext(InstanceType type, Node* node, 1281cb0ef41Sopenharmony_ci IterationKind kind); 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci Reduction ReduceCallOrConstructWithArrayLikeOrSpreadOfCreateArguments( 1311cb0ef41Sopenharmony_ci Node* node, Node* arguments_list, int arraylike_or_spread_index, 1321cb0ef41Sopenharmony_ci CallFrequency const& frequency, FeedbackSource const& feedback, 1331cb0ef41Sopenharmony_ci SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation); 1341cb0ef41Sopenharmony_ci Reduction ReduceCallOrConstructWithArrayLikeOrSpread( 1351cb0ef41Sopenharmony_ci Node* node, int argument_count, int arraylike_or_spread_index, 1361cb0ef41Sopenharmony_ci CallFrequency const& frequency, FeedbackSource const& feedback_source, 1371cb0ef41Sopenharmony_ci SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation, 1381cb0ef41Sopenharmony_ci Node* target, Effect effect, Control control); 1391cb0ef41Sopenharmony_ci Reduction ReduceJSConstruct(Node* node); 1401cb0ef41Sopenharmony_ci Reduction ReduceJSConstructWithArrayLike(Node* node); 1411cb0ef41Sopenharmony_ci Reduction ReduceJSConstructWithSpread(Node* node); 1421cb0ef41Sopenharmony_ci Reduction ReduceJSCall(Node* node); 1431cb0ef41Sopenharmony_ci Reduction ReduceJSCall(Node* node, const SharedFunctionInfoRef& shared); 1441cb0ef41Sopenharmony_ci Reduction ReduceJSCallWithArrayLike(Node* node); 1451cb0ef41Sopenharmony_ci Reduction ReduceJSCallWithSpread(Node* node); 1461cb0ef41Sopenharmony_ci Reduction ReduceRegExpPrototypeTest(Node* node); 1471cb0ef41Sopenharmony_ci Reduction ReduceReturnReceiver(Node* node); 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci enum class StringIndexOfIncludesVariant { kIncludes, kIndexOf }; 1501cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeIndexOfIncludes( 1511cb0ef41Sopenharmony_ci Node* node, StringIndexOfIncludesVariant variant); 1521cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeSubstring(Node* node); 1531cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeSlice(Node* node); 1541cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeSubstr(Node* node); 1551cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeStringAt( 1561cb0ef41Sopenharmony_ci const Operator* string_access_operator, Node* node); 1571cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeCharAt(Node* node); 1581cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeStartsWith(Node* node); 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT 1611cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeToLowerCaseIntl(Node* node); 1621cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeToUpperCaseIntl(Node* node); 1631cb0ef41Sopenharmony_ci#endif // V8_INTL_SUPPORT 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci Reduction ReduceStringFromCharCode(Node* node); 1661cb0ef41Sopenharmony_ci Reduction ReduceStringFromCodePoint(Node* node); 1671cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeIterator(Node* node); 1681cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeLocaleCompare(Node* node); 1691cb0ef41Sopenharmony_ci Reduction ReduceStringIteratorPrototypeNext(Node* node); 1701cb0ef41Sopenharmony_ci Reduction ReduceStringPrototypeConcat(Node* node); 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci Reduction ReducePromiseConstructor(Node* node); 1731cb0ef41Sopenharmony_ci Reduction ReducePromiseInternalConstructor(Node* node); 1741cb0ef41Sopenharmony_ci Reduction ReducePromiseInternalReject(Node* node); 1751cb0ef41Sopenharmony_ci Reduction ReducePromiseInternalResolve(Node* node); 1761cb0ef41Sopenharmony_ci Reduction ReducePromisePrototypeCatch(Node* node); 1771cb0ef41Sopenharmony_ci Reduction ReducePromisePrototypeFinally(Node* node); 1781cb0ef41Sopenharmony_ci Reduction ReducePromisePrototypeThen(Node* node); 1791cb0ef41Sopenharmony_ci Reduction ReducePromiseResolveTrampoline(Node* node); 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci Reduction ReduceTypedArrayConstructor(Node* node, 1821cb0ef41Sopenharmony_ci const SharedFunctionInfoRef& shared); 1831cb0ef41Sopenharmony_ci Reduction ReduceTypedArrayPrototypeToStringTag(Node* node); 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci Reduction ReduceForInsufficientFeedback(Node* node, DeoptimizeReason reason); 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci Reduction ReduceMathUnary(Node* node, const Operator* op); 1881cb0ef41Sopenharmony_ci Reduction ReduceMathBinary(Node* node, const Operator* op); 1891cb0ef41Sopenharmony_ci Reduction ReduceMathImul(Node* node); 1901cb0ef41Sopenharmony_ci Reduction ReduceMathClz32(Node* node); 1911cb0ef41Sopenharmony_ci Reduction ReduceMathMinMax(Node* node, const Operator* op, Node* empty_value); 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci Reduction ReduceNumberIsFinite(Node* node); 1941cb0ef41Sopenharmony_ci Reduction ReduceNumberIsInteger(Node* node); 1951cb0ef41Sopenharmony_ci Reduction ReduceNumberIsSafeInteger(Node* node); 1961cb0ef41Sopenharmony_ci Reduction ReduceNumberIsNaN(Node* node); 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci Reduction ReduceGlobalIsFinite(Node* node); 1991cb0ef41Sopenharmony_ci Reduction ReduceGlobalIsNaN(Node* node); 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci Reduction ReduceMapPrototypeHas(Node* node); 2021cb0ef41Sopenharmony_ci Reduction ReduceMapPrototypeGet(Node* node); 2031cb0ef41Sopenharmony_ci Reduction ReduceCollectionIteration(Node* node, 2041cb0ef41Sopenharmony_ci CollectionKind collection_kind, 2051cb0ef41Sopenharmony_ci IterationKind iteration_kind); 2061cb0ef41Sopenharmony_ci Reduction ReduceCollectionPrototypeSize(Node* node, 2071cb0ef41Sopenharmony_ci CollectionKind collection_kind); 2081cb0ef41Sopenharmony_ci Reduction ReduceCollectionIteratorPrototypeNext( 2091cb0ef41Sopenharmony_ci Node* node, int entry_size, Handle<HeapObject> empty_collection, 2101cb0ef41Sopenharmony_ci InstanceType collection_iterator_instance_type_first, 2111cb0ef41Sopenharmony_ci InstanceType collection_iterator_instance_type_last); 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci Reduction ReduceArrayBufferIsView(Node* node); 2141cb0ef41Sopenharmony_ci Reduction ReduceArrayBufferViewAccessor(Node* node, 2151cb0ef41Sopenharmony_ci InstanceType instance_type, 2161cb0ef41Sopenharmony_ci FieldAccess const& access); 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci enum class DataViewAccess { kGet, kSet }; 2191cb0ef41Sopenharmony_ci Reduction ReduceDataViewAccess(Node* node, DataViewAccess access, 2201cb0ef41Sopenharmony_ci ExternalArrayType element_type); 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci Reduction ReduceDatePrototypeGetTime(Node* node); 2231cb0ef41Sopenharmony_ci Reduction ReduceDateNow(Node* node); 2241cb0ef41Sopenharmony_ci Reduction ReduceNumberParseInt(Node* node); 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci Reduction ReduceNumberConstructor(Node* node); 2271cb0ef41Sopenharmony_ci Reduction ReduceBigIntAsN(Node* node, Builtin builtin); 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci // The pendant to ReplaceWithValue when using GraphAssembler-based reductions. 2301cb0ef41Sopenharmony_ci Reduction ReplaceWithSubgraph(JSCallReducerAssembler* gasm, Node* subgraph); 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci // Helper to verify promise receiver maps are as expected. 2331cb0ef41Sopenharmony_ci // On bailout from a reduction, be sure to return inference.NoChange(). 2341cb0ef41Sopenharmony_ci bool DoPromiseChecks(MapInference* inference); 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci Node* CreateClosureFromBuiltinSharedFunctionInfo(SharedFunctionInfoRef shared, 2371cb0ef41Sopenharmony_ci Node* context, Node* effect, 2381cb0ef41Sopenharmony_ci Node* control); 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ci void CheckIfElementsKind(Node* receiver_elements_kind, ElementsKind kind, 2411cb0ef41Sopenharmony_ci Node* control, Node** if_true, Node** if_false); 2421cb0ef41Sopenharmony_ci Node* LoadReceiverElementsKind(Node* receiver, Effect* effect, 2431cb0ef41Sopenharmony_ci Control control); 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci bool IsBuiltinOrApiFunction(JSFunctionRef target_ref) const; 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci // Check whether an array has the expected length. Returns the new effect. 2481cb0ef41Sopenharmony_ci Node* CheckArrayLength(Node* array, ElementsKind elements_kind, 2491cb0ef41Sopenharmony_ci uint32_t array_length, 2501cb0ef41Sopenharmony_ci const FeedbackSource& feedback_source, Effect effect, 2511cb0ef41Sopenharmony_ci Control control); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci // Check whether the given new target value is a constructor function. 2541cb0ef41Sopenharmony_ci void CheckIfConstructor(Node* call); 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci Graph* graph() const; 2571cb0ef41Sopenharmony_ci JSGraph* jsgraph() const { return jsgraph_; } 2581cb0ef41Sopenharmony_ci JSHeapBroker* broker() const { return broker_; } 2591cb0ef41Sopenharmony_ci Zone* temp_zone() const { return temp_zone_; } 2601cb0ef41Sopenharmony_ci Isolate* isolate() const; 2611cb0ef41Sopenharmony_ci Factory* factory() const; 2621cb0ef41Sopenharmony_ci NativeContextRef native_context() const; 2631cb0ef41Sopenharmony_ci CommonOperatorBuilder* common() const; 2641cb0ef41Sopenharmony_ci JSOperatorBuilder* javascript() const; 2651cb0ef41Sopenharmony_ci SimplifiedOperatorBuilder* simplified() const; 2661cb0ef41Sopenharmony_ci Flags flags() const { return flags_; } 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci JSGraph* const jsgraph_; 2691cb0ef41Sopenharmony_ci JSHeapBroker* const broker_; 2701cb0ef41Sopenharmony_ci Zone* const temp_zone_; 2711cb0ef41Sopenharmony_ci Flags const flags_; 2721cb0ef41Sopenharmony_ci std::set<Node*> waitlist_; 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci // For preventing infinite recursion via ReduceJSCallWithArrayLikeOrSpread. 2751cb0ef41Sopenharmony_ci std::unordered_set<Node*> generated_calls_with_array_like_or_spread_; 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ci bool has_wasm_calls_ = false; 2781cb0ef41Sopenharmony_ci}; 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci} // namespace compiler 2811cb0ef41Sopenharmony_ci} // namespace internal 2821cb0ef41Sopenharmony_ci} // namespace v8 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ci#endif // V8_COMPILER_JS_CALL_REDUCER_H_ 285