OLD | NEW |
(Empty) | |
| 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_GRAPH_BUILDER_H_ |
| 6 #define V8_COMPILER_GRAPH_BUILDER_H_ |
| 7 |
| 8 #include "src/v8.h" |
| 9 |
| 10 #include "src/allocation.h" |
| 11 #include "src/compiler/common-operator.h" |
| 12 #include "src/compiler/graph.h" |
| 13 #include "src/unique.h" |
| 14 |
| 15 namespace v8 { |
| 16 namespace internal { |
| 17 namespace compiler { |
| 18 |
| 19 class Node; |
| 20 |
| 21 // A common base class for anything that creates nodes in a graph. |
| 22 class GraphBuilder { |
| 23 public: |
| 24 explicit GraphBuilder(Graph* graph) : graph_(graph) {} |
| 25 virtual ~GraphBuilder() {} |
| 26 |
| 27 Node* NewNode(Operator* op) { |
| 28 return MakeNode(op, 0, static_cast<Node**>(NULL)); |
| 29 } |
| 30 |
| 31 Node* NewNode(Operator* op, Node* n1) { return MakeNode(op, 1, &n1); } |
| 32 |
| 33 Node* NewNode(Operator* op, Node* n1, Node* n2) { |
| 34 Node* buffer[] = {n1, n2}; |
| 35 return MakeNode(op, ARRAY_SIZE(buffer), buffer); |
| 36 } |
| 37 |
| 38 Node* NewNode(Operator* op, Node* n1, Node* n2, Node* n3) { |
| 39 Node* buffer[] = {n1, n2, n3}; |
| 40 return MakeNode(op, ARRAY_SIZE(buffer), buffer); |
| 41 } |
| 42 |
| 43 Node* NewNode(Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) { |
| 44 Node* buffer[] = {n1, n2, n3, n4}; |
| 45 return MakeNode(op, ARRAY_SIZE(buffer), buffer); |
| 46 } |
| 47 |
| 48 Node* NewNode(Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, |
| 49 Node* n5) { |
| 50 Node* buffer[] = {n1, n2, n3, n4, n5}; |
| 51 return MakeNode(op, ARRAY_SIZE(buffer), buffer); |
| 52 } |
| 53 |
| 54 Node* NewNode(Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, Node* n5, |
| 55 Node* n6) { |
| 56 Node* nodes[] = {n1, n2, n3, n4, n5, n6}; |
| 57 return MakeNode(op, ARRAY_SIZE(nodes), nodes); |
| 58 } |
| 59 |
| 60 Node* NewNode(Operator* op, int value_input_count, Node** value_inputs) { |
| 61 return MakeNode(op, value_input_count, value_inputs); |
| 62 } |
| 63 |
| 64 Graph* graph() const { return graph_; } |
| 65 |
| 66 protected: |
| 67 // Base implementation used by all factory methods. |
| 68 virtual Node* MakeNode(Operator* op, int value_input_count, |
| 69 Node** value_inputs) = 0; |
| 70 |
| 71 private: |
| 72 Graph* graph_; |
| 73 }; |
| 74 |
| 75 |
| 76 // The StructuredGraphBuilder produces a high-level IR graph. It is used as the |
| 77 // base class for concrete implementations (e.g the AstGraphBuilder or the |
| 78 // StubGraphBuilder). |
| 79 class StructuredGraphBuilder : public GraphBuilder { |
| 80 public: |
| 81 StructuredGraphBuilder(Graph* graph, CommonOperatorBuilder* common); |
| 82 virtual ~StructuredGraphBuilder() {} |
| 83 |
| 84 // Creates a new Phi node having {count} input values. |
| 85 Node* NewPhi(int count, Node* input, Node* control); |
| 86 Node* NewEffectPhi(int count, Node* input, Node* control); |
| 87 |
| 88 // Helpers for merging control, effect or value dependencies. |
| 89 Node* MergeControl(Node* control, Node* other); |
| 90 Node* MergeEffect(Node* value, Node* other, Node* control); |
| 91 Node* MergeValue(Node* value, Node* other, Node* control); |
| 92 |
| 93 // Helpers to create new control nodes. |
| 94 Node* NewIfTrue() { return NewNode(common()->IfTrue()); } |
| 95 Node* NewIfFalse() { return NewNode(common()->IfFalse()); } |
| 96 Node* NewMerge() { return NewNode(common()->Merge(1)); } |
| 97 Node* NewLoop() { return NewNode(common()->Loop(1)); } |
| 98 Node* NewBranch(Node* condition) { |
| 99 return NewNode(common()->Branch(), condition); |
| 100 } |
| 101 |
| 102 protected: |
| 103 class Environment; |
| 104 friend class ControlBuilder; |
| 105 |
| 106 // The following method creates a new node having the specified operator and |
| 107 // ensures effect and control dependencies are wired up. The dependencies |
| 108 // tracked by the environment might be mutated. |
| 109 virtual Node* MakeNode(Operator* op, int value_input_count, |
| 110 Node** value_inputs); |
| 111 |
| 112 Environment* environment_internal() const { return environment_; } |
| 113 void set_environment(Environment* env) { environment_ = env; } |
| 114 |
| 115 Node* current_context() const { return current_context_; } |
| 116 void set_current_context(Node* context) { current_context_ = context; } |
| 117 |
| 118 Node* exit_control() const { return exit_control_; } |
| 119 void set_exit_control(Node* node) { exit_control_ = node; } |
| 120 |
| 121 Node* dead_control(); |
| 122 |
| 123 // TODO(mstarzinger): Use phase-local zone instead! |
| 124 Zone* zone() const { return graph()->zone(); } |
| 125 Isolate* isolate() const { return zone()->isolate(); } |
| 126 CommonOperatorBuilder* common() const { return common_; } |
| 127 |
| 128 // Helper to wrap a Handle<T> into a Unique<T>. |
| 129 template <class T> |
| 130 PrintableUnique<T> MakeUnique(Handle<T> object) { |
| 131 return PrintableUnique<T>::CreateUninitialized(zone(), object); |
| 132 } |
| 133 |
| 134 // Support for control flow builders. The concrete type of the environment |
| 135 // depends on the graph builder, but environments themselves are not virtual. |
| 136 virtual Environment* CopyEnvironment(Environment* env); |
| 137 |
| 138 // Helper when creating node that depends on control. |
| 139 Node* GetControlDependency(); |
| 140 |
| 141 // Helper when creating node that updates control. |
| 142 void UpdateControlDependency(Node* new_control); |
| 143 |
| 144 // Helper to indicate a node exits the function body. |
| 145 void UpdateControlDependencyToLeaveFunction(Node* exit); |
| 146 |
| 147 private: |
| 148 CommonOperatorBuilder* common_; |
| 149 Environment* environment_; |
| 150 |
| 151 // Node representing the control dependency for dead code. |
| 152 SetOncePointer<Node> dead_control_; |
| 153 |
| 154 // Node representing the current context within the function body. |
| 155 Node* current_context_; |
| 156 |
| 157 // Merge of all control nodes that exit the function body. |
| 158 Node* exit_control_; |
| 159 |
| 160 DISALLOW_COPY_AND_ASSIGN(StructuredGraphBuilder); |
| 161 }; |
| 162 |
| 163 |
| 164 // The abstract execution environment contains static knowledge about |
| 165 // execution state at arbitrary control-flow points. It allows for |
| 166 // simulation of the control-flow at compile time. |
| 167 class StructuredGraphBuilder::Environment : public ZoneObject { |
| 168 public: |
| 169 Environment(StructuredGraphBuilder* builder, Node* control_dependency); |
| 170 Environment(const Environment& copy); |
| 171 |
| 172 // Control dependency tracked by this environment. |
| 173 Node* GetControlDependency() { return control_dependency_; } |
| 174 void UpdateControlDependency(Node* dependency) { |
| 175 control_dependency_ = dependency; |
| 176 } |
| 177 |
| 178 // Effect dependency tracked by this environment. |
| 179 Node* GetEffectDependency() { return effect_dependency_; } |
| 180 void UpdateEffectDependency(Node* dependency) { |
| 181 effect_dependency_ = dependency; |
| 182 } |
| 183 |
| 184 // Mark this environment as being unreachable. |
| 185 void MarkAsUnreachable() { |
| 186 UpdateControlDependency(builder()->dead_control()); |
| 187 } |
| 188 bool IsMarkedAsUnreachable() { |
| 189 return GetControlDependency()->opcode() == IrOpcode::kDead; |
| 190 } |
| 191 |
| 192 // Merge another environment into this one. |
| 193 void Merge(Environment* other); |
| 194 |
| 195 // Copies this environment at a control-flow split point. |
| 196 Environment* CopyForConditional() { return builder()->CopyEnvironment(this); } |
| 197 |
| 198 // Copies this environment to a potentially unreachable control-flow point. |
| 199 Environment* CopyAsUnreachable() { |
| 200 Environment* env = builder()->CopyEnvironment(this); |
| 201 env->MarkAsUnreachable(); |
| 202 return env; |
| 203 } |
| 204 |
| 205 // Copies this environment at a loop header control-flow point. |
| 206 Environment* CopyForLoop() { |
| 207 PrepareForLoop(); |
| 208 return builder()->CopyEnvironment(this); |
| 209 } |
| 210 |
| 211 protected: |
| 212 // TODO(mstarzinger): Use phase-local zone instead! |
| 213 Zone* zone() const { return graph()->zone(); } |
| 214 Graph* graph() const { return builder_->graph(); } |
| 215 StructuredGraphBuilder* builder() const { return builder_; } |
| 216 CommonOperatorBuilder* common() { return builder_->common(); } |
| 217 NodeVector* values() { return &values_; } |
| 218 |
| 219 // Prepare environment to be used as loop header. |
| 220 void PrepareForLoop(); |
| 221 |
| 222 private: |
| 223 StructuredGraphBuilder* builder_; |
| 224 Node* control_dependency_; |
| 225 Node* effect_dependency_; |
| 226 NodeVector values_; |
| 227 }; |
| 228 } |
| 229 } |
| 230 } // namespace v8::internal::compiler |
| 231 |
| 232 #endif // V8_COMPILER_GRAPH_BUILDER_H__ |
OLD | NEW |