11cb0ef41Sopenharmony_ci// Copyright 2013 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_NODE_PROPERTIES_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_NODE_PROPERTIES_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/common/globals.h" 91cb0ef41Sopenharmony_ci#include "src/compiler/heap-refs.h" 101cb0ef41Sopenharmony_ci#include "src/compiler/node.h" 111cb0ef41Sopenharmony_ci#include "src/compiler/operator-properties.h" 121cb0ef41Sopenharmony_ci#include "src/compiler/types.h" 131cb0ef41Sopenharmony_ci#include "src/objects/map.h" 141cb0ef41Sopenharmony_ci#include "src/zone/zone-handle-set.h" 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cinamespace v8 { 171cb0ef41Sopenharmony_cinamespace internal { 181cb0ef41Sopenharmony_cinamespace compiler { 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ciclass Graph; 211cb0ef41Sopenharmony_ciclass Operator; 221cb0ef41Sopenharmony_ciclass CommonOperatorBuilder; 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci// A facade that simplifies access to the different kinds of inputs to a node. 251cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE NodeProperties { 261cb0ef41Sopenharmony_ci public: 271cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 281cb0ef41Sopenharmony_ci // Input layout. 291cb0ef41Sopenharmony_ci // Inputs are always arranged in order as follows: 301cb0ef41Sopenharmony_ci // 0 [ values, context, frame state, effects, control ] node->InputCount() 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci static int FirstValueIndex(const Node* node) { return 0; } 331cb0ef41Sopenharmony_ci static int FirstContextIndex(Node* node) { return PastValueIndex(node); } 341cb0ef41Sopenharmony_ci static int FirstFrameStateIndex(Node* node) { return PastContextIndex(node); } 351cb0ef41Sopenharmony_ci static int FirstEffectIndex(Node* node) { return PastFrameStateIndex(node); } 361cb0ef41Sopenharmony_ci static int FirstControlIndex(Node* node) { return PastEffectIndex(node); } 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci static int PastValueIndex(Node* node) { 391cb0ef41Sopenharmony_ci return FirstValueIndex(node) + node->op()->ValueInputCount(); 401cb0ef41Sopenharmony_ci } 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci static int PastContextIndex(Node* node) { 431cb0ef41Sopenharmony_ci return FirstContextIndex(node) + 441cb0ef41Sopenharmony_ci OperatorProperties::GetContextInputCount(node->op()); 451cb0ef41Sopenharmony_ci } 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci static int PastFrameStateIndex(Node* node) { 481cb0ef41Sopenharmony_ci return FirstFrameStateIndex(node) + 491cb0ef41Sopenharmony_ci OperatorProperties::GetFrameStateInputCount(node->op()); 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci static int PastEffectIndex(Node* node) { 531cb0ef41Sopenharmony_ci return FirstEffectIndex(node) + node->op()->EffectInputCount(); 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci static int PastControlIndex(Node* node) { 571cb0ef41Sopenharmony_ci return FirstControlIndex(node) + node->op()->ControlInputCount(); 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 611cb0ef41Sopenharmony_ci // Input accessors. 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci static Node* GetValueInput(Node* node, int index) { 641cb0ef41Sopenharmony_ci CHECK_LE(0, index); 651cb0ef41Sopenharmony_ci CHECK_LT(index, node->op()->ValueInputCount()); 661cb0ef41Sopenharmony_ci return node->InputAt(FirstValueIndex(node) + index); 671cb0ef41Sopenharmony_ci } 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci static const Node* GetValueInput(const Node* node, int index) { 701cb0ef41Sopenharmony_ci CHECK_LE(0, index); 711cb0ef41Sopenharmony_ci CHECK_LT(index, node->op()->ValueInputCount()); 721cb0ef41Sopenharmony_ci return node->InputAt(FirstValueIndex(node) + index); 731cb0ef41Sopenharmony_ci } 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci static Node* GetContextInput(Node* node) { 761cb0ef41Sopenharmony_ci CHECK(OperatorProperties::HasContextInput(node->op())); 771cb0ef41Sopenharmony_ci return node->InputAt(FirstContextIndex(node)); 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci static Node* GetFrameStateInput(Node* node) { 811cb0ef41Sopenharmony_ci CHECK(OperatorProperties::HasFrameStateInput(node->op())); 821cb0ef41Sopenharmony_ci return node->InputAt(FirstFrameStateIndex(node)); 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci static Node* GetEffectInput(Node* node, int index = 0) { 861cb0ef41Sopenharmony_ci CHECK_LE(0, index); 871cb0ef41Sopenharmony_ci CHECK_LT(index, node->op()->EffectInputCount()); 881cb0ef41Sopenharmony_ci return node->InputAt(FirstEffectIndex(node) + index); 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci static Node* GetControlInput(Node* node, int index = 0) { 921cb0ef41Sopenharmony_ci CHECK_LE(0, index); 931cb0ef41Sopenharmony_ci CHECK_LT(index, node->op()->ControlInputCount()); 941cb0ef41Sopenharmony_ci return node->InputAt(FirstControlIndex(node) + index); 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 981cb0ef41Sopenharmony_ci // Edge kinds. 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci static bool IsValueEdge(Edge edge); 1011cb0ef41Sopenharmony_ci static bool IsContextEdge(Edge edge); 1021cb0ef41Sopenharmony_ci static bool IsFrameStateEdge(Edge edge); 1031cb0ef41Sopenharmony_ci static bool IsEffectEdge(Edge edge); 1041cb0ef41Sopenharmony_ci static bool IsControlEdge(Edge edge); 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 1071cb0ef41Sopenharmony_ci // Miscellaneous predicates. 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci static bool IsCommon(Node* node) { 1101cb0ef41Sopenharmony_ci return IrOpcode::IsCommonOpcode(node->opcode()); 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci static bool IsControl(Node* node) { 1131cb0ef41Sopenharmony_ci return IrOpcode::IsControlOpcode(node->opcode()); 1141cb0ef41Sopenharmony_ci } 1151cb0ef41Sopenharmony_ci static bool IsConstant(Node* node) { 1161cb0ef41Sopenharmony_ci return IrOpcode::IsConstantOpcode(node->opcode()); 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci static bool IsPhi(Node* node) { 1191cb0ef41Sopenharmony_ci return IrOpcode::IsPhiOpcode(node->opcode()); 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci // Determines whether exceptions thrown by the given node are handled locally 1231cb0ef41Sopenharmony_ci // within the graph (i.e. an IfException projection is present). Optionally 1241cb0ef41Sopenharmony_ci // the present IfException projection is returned via {out_exception}. 1251cb0ef41Sopenharmony_ci static bool IsExceptionalCall(Node* node, Node** out_exception = nullptr); 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci // Returns the node producing the successful control output of {node}. This is 1281cb0ef41Sopenharmony_ci // the IfSuccess projection of {node} if present and {node} itself otherwise. 1291cb0ef41Sopenharmony_ci static Node* FindSuccessfulControlProjection(Node* node); 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci // Returns whether the node acts as the identity function on a value 1321cb0ef41Sopenharmony_ci // input. The input that is passed through is returned via {out_value}. 1331cb0ef41Sopenharmony_ci static bool IsValueIdentity(Node* node, Node** out_value) { 1341cb0ef41Sopenharmony_ci switch (node->opcode()) { 1351cb0ef41Sopenharmony_ci case IrOpcode::kTypeGuard: 1361cb0ef41Sopenharmony_ci *out_value = GetValueInput(node, 0); 1371cb0ef41Sopenharmony_ci return true; 1381cb0ef41Sopenharmony_ci case IrOpcode::kFoldConstant: 1391cb0ef41Sopenharmony_ci *out_value = GetValueInput(node, 1); 1401cb0ef41Sopenharmony_ci return true; 1411cb0ef41Sopenharmony_ci default: 1421cb0ef41Sopenharmony_ci return false; 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci // Determines if {node} has an allocating opcode, or is a builtin known to 1471cb0ef41Sopenharmony_ci // return a fresh object. 1481cb0ef41Sopenharmony_ci static bool IsFreshObject(Node* node); 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 1511cb0ef41Sopenharmony_ci // Miscellaneous mutators. 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci static void ReplaceValueInput(Node* node, Node* value, int index); 1541cb0ef41Sopenharmony_ci static void ReplaceContextInput(Node* node, Node* context); 1551cb0ef41Sopenharmony_ci static void ReplaceControlInput(Node* node, Node* control, int index = 0); 1561cb0ef41Sopenharmony_ci static void ReplaceEffectInput(Node* node, Node* effect, int index = 0); 1571cb0ef41Sopenharmony_ci static void ReplaceFrameStateInput(Node* node, Node* frame_state); 1581cb0ef41Sopenharmony_ci static void RemoveNonValueInputs(Node* node); 1591cb0ef41Sopenharmony_ci static void RemoveValueInputs(Node* node); 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci // Replaces all value inputs of {node} with the single input {value}. 1621cb0ef41Sopenharmony_ci static void ReplaceValueInputs(Node* node, Node* value); 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci // Merge the control node {node} into the end of the graph, introducing a 1651cb0ef41Sopenharmony_ci // merge node or expanding an existing merge node if necessary. 1661cb0ef41Sopenharmony_ci static void MergeControlToEnd(Graph* graph, CommonOperatorBuilder* common, 1671cb0ef41Sopenharmony_ci Node* node); 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci // Removes the control node {node} from the end of the graph, reducing the 1701cb0ef41Sopenharmony_ci // existing merge node's input count. 1711cb0ef41Sopenharmony_ci static void RemoveControlFromEnd(Graph* graph, CommonOperatorBuilder* common, 1721cb0ef41Sopenharmony_ci Node* node); 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci // Replace all uses of {node} with the given replacement nodes. All occurring 1751cb0ef41Sopenharmony_ci // use kinds need to be replaced, {nullptr} is only valid if a use kind is 1761cb0ef41Sopenharmony_ci // guaranteed not to exist. 1771cb0ef41Sopenharmony_ci static void ReplaceUses(Node* node, Node* value, Node* effect = nullptr, 1781cb0ef41Sopenharmony_ci Node* success = nullptr, Node* exception = nullptr); 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci // Safe wrapper to mutate the operator of a node. Checks that the node is 1811cb0ef41Sopenharmony_ci // currently in a state that satisfies constraints of the new operator. 1821cb0ef41Sopenharmony_ci static void ChangeOp(Node* node, const Operator* new_op); 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 1851cb0ef41Sopenharmony_ci // Miscellaneous utilities. 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci // Find the last frame state that is effect-wise before the given node. This 1881cb0ef41Sopenharmony_ci // assumes a linear effect-chain up to a {CheckPoint} node in the graph. 1891cb0ef41Sopenharmony_ci // Returns {unreachable_sentinel} if {node} is determined to be unreachable. 1901cb0ef41Sopenharmony_ci static Node* FindFrameStateBefore(Node* node, Node* unreachable_sentinel); 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci // Collect the output-value projection for the given output index. 1931cb0ef41Sopenharmony_ci static Node* FindProjection(Node* node, size_t projection_index); 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci // Collect the value projections from a node. 1961cb0ef41Sopenharmony_ci static void CollectValueProjections(Node* node, Node** proj, size_t count); 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci // Collect the branch-related projections from a node, such as IfTrue, 1991cb0ef41Sopenharmony_ci // IfFalse, IfSuccess, IfException, IfValue and IfDefault. 2001cb0ef41Sopenharmony_ci // - Branch: [ IfTrue, IfFalse ] 2011cb0ef41Sopenharmony_ci // - Call : [ IfSuccess, IfException ] 2021cb0ef41Sopenharmony_ci // - Switch: [ IfValue, ..., IfDefault ] 2031cb0ef41Sopenharmony_ci static void CollectControlProjections(Node* node, Node** proj, size_t count); 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci // Checks if two nodes are the same, looking past {CheckHeapObject}. 2061cb0ef41Sopenharmony_ci static bool IsSame(Node* a, Node* b); 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci // Check if two nodes have equal operators and reference-equal inputs. Used 2091cb0ef41Sopenharmony_ci // for value numbering/hash-consing. 2101cb0ef41Sopenharmony_ci static bool Equals(Node* a, Node* b); 2111cb0ef41Sopenharmony_ci // A corresponding hash function. 2121cb0ef41Sopenharmony_ci static size_t HashCode(Node* node); 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci // Walks up the {effect} chain to find a witness that provides map 2151cb0ef41Sopenharmony_ci // information about the {receiver}. Can look through potentially 2161cb0ef41Sopenharmony_ci // side effecting nodes. 2171cb0ef41Sopenharmony_ci enum InferMapsResult { 2181cb0ef41Sopenharmony_ci kNoMaps, // No maps inferred. 2191cb0ef41Sopenharmony_ci kReliableMaps, // Maps can be trusted. 2201cb0ef41Sopenharmony_ci kUnreliableMaps // Maps might have changed (side-effect). 2211cb0ef41Sopenharmony_ci }; 2221cb0ef41Sopenharmony_ci // DO NOT USE InferMapsUnsafe IN NEW CODE. Use MapInference instead. 2231cb0ef41Sopenharmony_ci static InferMapsResult InferMapsUnsafe(JSHeapBroker* broker, Node* receiver, 2241cb0ef41Sopenharmony_ci Effect effect, 2251cb0ef41Sopenharmony_ci ZoneRefUnorderedSet<MapRef>* maps_out); 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ci // Return the initial map of the new-target if the allocation can be inlined. 2281cb0ef41Sopenharmony_ci static base::Optional<MapRef> GetJSCreateMap(JSHeapBroker* broker, 2291cb0ef41Sopenharmony_ci Node* receiver); 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci // Walks up the {effect} chain to check that there's no observable side-effect 2321cb0ef41Sopenharmony_ci // between the {effect} and it's {dominator}. Aborts the walk if there's join 2331cb0ef41Sopenharmony_ci // in the effect chain. 2341cb0ef41Sopenharmony_ci static bool NoObservableSideEffectBetween(Node* effect, Node* dominator); 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci // Returns true if the {receiver} can be a primitive value (i.e. is not 2371cb0ef41Sopenharmony_ci // definitely a JavaScript object); might walk up the {effect} chain to 2381cb0ef41Sopenharmony_ci // find map checks on {receiver}. 2391cb0ef41Sopenharmony_ci static bool CanBePrimitive(JSHeapBroker* broker, Node* receiver, 2401cb0ef41Sopenharmony_ci Effect effect); 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci // Returns true if the {receiver} can be null or undefined. Might walk 2431cb0ef41Sopenharmony_ci // up the {effect} chain to find map checks for {receiver}. 2441cb0ef41Sopenharmony_ci static bool CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver, 2451cb0ef41Sopenharmony_ci Effect effect); 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 2481cb0ef41Sopenharmony_ci // Context. 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci // Walk up the context chain from the given {node} until we reduce the {depth} 2511cb0ef41Sopenharmony_ci // to 0 or hit a node that does not extend the context chain ({depth} will be 2521cb0ef41Sopenharmony_ci // updated accordingly). 2531cb0ef41Sopenharmony_ci static Node* GetOuterContext(Node* node, size_t* depth); 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 2561cb0ef41Sopenharmony_ci // Type. 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci static bool IsTyped(const Node* node) { return !node->type().IsInvalid(); } 2591cb0ef41Sopenharmony_ci static Type GetType(const Node* node) { 2601cb0ef41Sopenharmony_ci DCHECK(IsTyped(node)); 2611cb0ef41Sopenharmony_ci return node->type(); 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci static Type GetTypeOrAny(const Node* node); 2641cb0ef41Sopenharmony_ci static void SetType(Node* node, Type type) { 2651cb0ef41Sopenharmony_ci DCHECK(!type.IsInvalid()); 2661cb0ef41Sopenharmony_ci node->set_type(type); 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci static void RemoveType(Node* node) { node->set_type(Type::Invalid()); } 2691cb0ef41Sopenharmony_ci static bool AllValueInputsAreTyped(Node* node); 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci private: 2721cb0ef41Sopenharmony_ci static inline bool IsInputRange(Edge edge, int first, int count); 2731cb0ef41Sopenharmony_ci}; 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci} // namespace compiler 2761cb0ef41Sopenharmony_ci} // namespace internal 2771cb0ef41Sopenharmony_ci} // namespace v8 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci#endif // V8_COMPILER_NODE_PROPERTIES_H_ 280