• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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