1 // Copyright 2013 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_NODE_PROPERTIES_H_ 6 #define V8_COMPILER_NODE_PROPERTIES_H_ 7 8 #include "src/compiler/node.h" 9 #include "src/compiler/types.h" 10 #include "src/globals.h" 11 #include "src/objects/map.h" 12 #include "src/zone/zone-handle-set.h" 13 14 namespace v8 { 15 namespace internal { 16 namespace compiler { 17 18 class Graph; 19 class Operator; 20 class CommonOperatorBuilder; 21 22 // A facade that simplifies access to the different kinds of inputs to a node. 23 class V8_EXPORT_PRIVATE NodeProperties final { 24 public: 25 // --------------------------------------------------------------------------- 26 // Input layout. 27 // Inputs are always arranged in order as follows: 28 // 0 [ values, context, frame state, effects, control ] node->InputCount() 29 FirstValueIndex(Node * node)30 static int FirstValueIndex(Node* node) { return 0; } FirstContextIndex(Node * node)31 static int FirstContextIndex(Node* node) { return PastValueIndex(node); } FirstFrameStateIndex(Node * node)32 static int FirstFrameStateIndex(Node* node) { return PastContextIndex(node); } FirstEffectIndex(Node * node)33 static int FirstEffectIndex(Node* node) { return PastFrameStateIndex(node); } FirstControlIndex(Node * node)34 static int FirstControlIndex(Node* node) { return PastEffectIndex(node); } 35 static int PastValueIndex(Node* node); 36 static int PastContextIndex(Node* node); 37 static int PastFrameStateIndex(Node* node); 38 static int PastEffectIndex(Node* node); 39 static int PastControlIndex(Node* node); 40 41 42 // --------------------------------------------------------------------------- 43 // Input accessors. 44 45 static Node* GetValueInput(Node* node, int index); 46 static Node* GetContextInput(Node* node); 47 static Node* GetFrameStateInput(Node* node); 48 static Node* GetEffectInput(Node* node, int index = 0); 49 static Node* GetControlInput(Node* node, int index = 0); 50 51 52 // --------------------------------------------------------------------------- 53 // Edge kinds. 54 55 static bool IsValueEdge(Edge edge); 56 static bool IsContextEdge(Edge edge); 57 static bool IsFrameStateEdge(Edge edge); 58 static bool IsEffectEdge(Edge edge); 59 static bool IsControlEdge(Edge edge); 60 61 62 // --------------------------------------------------------------------------- 63 // Miscellaneous predicates. 64 IsCommon(Node * node)65 static bool IsCommon(Node* node) { 66 return IrOpcode::IsCommonOpcode(node->opcode()); 67 } IsControl(Node * node)68 static bool IsControl(Node* node) { 69 return IrOpcode::IsControlOpcode(node->opcode()); 70 } IsConstant(Node * node)71 static bool IsConstant(Node* node) { 72 return IrOpcode::IsConstantOpcode(node->opcode()); 73 } IsPhi(Node * node)74 static bool IsPhi(Node* node) { 75 return IrOpcode::IsPhiOpcode(node->opcode()); 76 } 77 78 // Determines whether exceptions thrown by the given node are handled locally 79 // within the graph (i.e. an IfException projection is present). Optionally 80 // the present IfException projection is returned via {out_exception}. 81 static bool IsExceptionalCall(Node* node, Node** out_exception = nullptr); 82 83 // Returns the node producing the successful control output of {node}. This is 84 // the IfSuccess projection of {node} if present and {node} itself otherwise. 85 static Node* FindSuccessfulControlProjection(Node* node); 86 87 // --------------------------------------------------------------------------- 88 // Miscellaneous mutators. 89 90 static void ReplaceValueInput(Node* node, Node* value, int index); 91 static void ReplaceContextInput(Node* node, Node* context); 92 static void ReplaceControlInput(Node* node, Node* control, int index = 0); 93 static void ReplaceEffectInput(Node* node, Node* effect, int index = 0); 94 static void ReplaceFrameStateInput(Node* node, Node* frame_state); 95 static void RemoveNonValueInputs(Node* node); 96 static void RemoveValueInputs(Node* node); 97 98 // Replaces all value inputs of {node} with the single input {value}. 99 static void ReplaceValueInputs(Node* node, Node* value); 100 101 // Merge the control node {node} into the end of the graph, introducing a 102 // merge node or expanding an existing merge node if necessary. 103 static void MergeControlToEnd(Graph* graph, CommonOperatorBuilder* common, 104 Node* node); 105 106 // Replace all uses of {node} with the given replacement nodes. All occurring 107 // use kinds need to be replaced, {nullptr} is only valid if a use kind is 108 // guaranteed not to exist. 109 static void ReplaceUses(Node* node, Node* value, Node* effect = nullptr, 110 Node* success = nullptr, Node* exception = nullptr); 111 112 // Safe wrapper to mutate the operator of a node. Checks that the node is 113 // currently in a state that satisfies constraints of the new operator. 114 static void ChangeOp(Node* node, const Operator* new_op); 115 116 // --------------------------------------------------------------------------- 117 // Miscellaneous utilities. 118 119 // Find the last frame state that is effect-wise before the given node. This 120 // assumes a linear effect-chain up to a {CheckPoint} node in the graph. 121 static Node* FindFrameStateBefore(Node* node); 122 123 // Collect the output-value projection for the given output index. 124 static Node* FindProjection(Node* node, size_t projection_index); 125 126 // Collect the value projections from a node. 127 static void CollectValueProjections(Node* node, Node** proj, size_t count); 128 129 // Collect the branch-related projections from a node, such as IfTrue, 130 // IfFalse, IfSuccess, IfException, IfValue and IfDefault. 131 // - Branch: [ IfTrue, IfFalse ] 132 // - Call : [ IfSuccess, IfException ] 133 // - Switch: [ IfValue, ..., IfDefault ] 134 static void CollectControlProjections(Node* node, Node** proj, size_t count); 135 136 // Checks if two nodes are the same, looking past {CheckHeapObject}. 137 static bool IsSame(Node* a, Node* b); 138 139 // Check if two nodes have equal operators and reference-equal inputs. Used 140 // for value numbering/hash-consing. 141 static bool Equals(Node* a, Node* b); 142 // A corresponding hash function. 143 static size_t HashCode(Node* node); 144 145 // Walks up the {effect} chain to find a witness that provides map 146 // information about the {receiver}. Can look through potentially 147 // side effecting nodes. 148 enum InferReceiverMapsResult { 149 kNoReceiverMaps, // No receiver maps inferred. 150 kReliableReceiverMaps, // Receiver maps can be trusted. 151 kUnreliableReceiverMaps // Receiver maps might have changed (side-effect), 152 // but instance type is reliable. 153 }; 154 static InferReceiverMapsResult InferReceiverMaps( 155 Isolate* isolate, Node* receiver, Node* effect, 156 ZoneHandleSet<Map>* maps_return); 157 158 static MaybeHandle<Map> GetMapWitness(Isolate* isolate, Node* node); 159 static bool HasInstanceTypeWitness(Isolate* isolate, Node* receiver, 160 Node* effect, InstanceType instance_type); 161 162 // Walks up the {effect} chain to check that there's no observable side-effect 163 // between the {effect} and it's {dominator}. Aborts the walk if there's join 164 // in the effect chain. 165 static bool NoObservableSideEffectBetween(Node* effect, Node* dominator); 166 167 // Returns true if the {receiver} can be a primitive value (i.e. is not 168 // definitely a JavaScript object); might walk up the {effect} chain to 169 // find map checks on {receiver}. 170 static bool CanBePrimitive(Isolate* isolate, Node* receiver, Node* effect); 171 172 // Returns true if the {receiver} can be null or undefined. Might walk 173 // up the {effect} chain to find map checks for {receiver}. 174 static bool CanBeNullOrUndefined(Isolate* isolate, Node* receiver, 175 Node* effect); 176 177 // --------------------------------------------------------------------------- 178 // Context. 179 180 // Walk up the context chain from the given {node} until we reduce the {depth} 181 // to 0 or hit a node that does not extend the context chain ({depth} will be 182 // updated accordingly). 183 static Node* GetOuterContext(Node* node, size_t* depth); 184 185 // --------------------------------------------------------------------------- 186 // Type. 187 IsTyped(Node * node)188 static bool IsTyped(Node* node) { return !node->type().IsInvalid(); } GetType(Node * node)189 static Type GetType(Node* node) { 190 DCHECK(IsTyped(node)); 191 return node->type(); 192 } 193 static Type GetTypeOrAny(Node* node); SetType(Node * node,Type type)194 static void SetType(Node* node, Type type) { 195 DCHECK(!type.IsInvalid()); 196 node->set_type(type); 197 } RemoveType(Node * node)198 static void RemoveType(Node* node) { node->set_type(Type::Invalid()); } 199 static bool AllValueInputsAreTyped(Node* node); 200 201 private: 202 static inline bool IsInputRange(Edge edge, int first, int count); 203 }; 204 205 } // namespace compiler 206 } // namespace internal 207 } // namespace v8 208 209 #endif // V8_COMPILER_NODE_PROPERTIES_H_ 210