Index: src/compiler/graph-builder.h |
diff --git a/src/compiler/graph-builder.h b/src/compiler/graph-builder.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ac42f6e7f678e9fe93cca457a127d5710ff2e3b6 |
--- /dev/null |
+++ b/src/compiler/graph-builder.h |
@@ -0,0 +1,232 @@ |
+// Copyright 2013 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef V8_COMPILER_GRAPH_BUILDER_H_ |
+#define V8_COMPILER_GRAPH_BUILDER_H_ |
+ |
+#include "src/v8.h" |
+ |
+#include "src/allocation.h" |
+#include "src/compiler/common-operator.h" |
+#include "src/compiler/graph.h" |
+#include "src/unique.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace compiler { |
+ |
+class Node; |
+ |
+// A common base class for anything that creates nodes in a graph. |
+class GraphBuilder { |
+ public: |
+ explicit GraphBuilder(Graph* graph) : graph_(graph) {} |
+ virtual ~GraphBuilder() {} |
+ |
+ Node* NewNode(Operator* op) { |
+ return MakeNode(op, 0, static_cast<Node**>(NULL)); |
+ } |
+ |
+ Node* NewNode(Operator* op, Node* n1) { return MakeNode(op, 1, &n1); } |
+ |
+ Node* NewNode(Operator* op, Node* n1, Node* n2) { |
+ Node* buffer[] = {n1, n2}; |
+ return MakeNode(op, ARRAY_SIZE(buffer), buffer); |
+ } |
+ |
+ Node* NewNode(Operator* op, Node* n1, Node* n2, Node* n3) { |
+ Node* buffer[] = {n1, n2, n3}; |
+ return MakeNode(op, ARRAY_SIZE(buffer), buffer); |
+ } |
+ |
+ Node* NewNode(Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) { |
+ Node* buffer[] = {n1, n2, n3, n4}; |
+ return MakeNode(op, ARRAY_SIZE(buffer), buffer); |
+ } |
+ |
+ Node* NewNode(Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, |
+ Node* n5) { |
+ Node* buffer[] = {n1, n2, n3, n4, n5}; |
+ return MakeNode(op, ARRAY_SIZE(buffer), buffer); |
+ } |
+ |
+ Node* NewNode(Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, Node* n5, |
+ Node* n6) { |
+ Node* nodes[] = {n1, n2, n3, n4, n5, n6}; |
+ return MakeNode(op, ARRAY_SIZE(nodes), nodes); |
+ } |
+ |
+ Node* NewNode(Operator* op, int value_input_count, Node** value_inputs) { |
+ return MakeNode(op, value_input_count, value_inputs); |
+ } |
+ |
+ Graph* graph() const { return graph_; } |
+ |
+ protected: |
+ // Base implementation used by all factory methods. |
+ virtual Node* MakeNode(Operator* op, int value_input_count, |
+ Node** value_inputs) = 0; |
+ |
+ private: |
+ Graph* graph_; |
+}; |
+ |
+ |
+// The StructuredGraphBuilder produces a high-level IR graph. It is used as the |
+// base class for concrete implementations (e.g the AstGraphBuilder or the |
+// StubGraphBuilder). |
+class StructuredGraphBuilder : public GraphBuilder { |
+ public: |
+ StructuredGraphBuilder(Graph* graph, CommonOperatorBuilder* common); |
+ virtual ~StructuredGraphBuilder() {} |
+ |
+ // Creates a new Phi node having {count} input values. |
+ Node* NewPhi(int count, Node* input, Node* control); |
+ Node* NewEffectPhi(int count, Node* input, Node* control); |
+ |
+ // Helpers for merging control, effect or value dependencies. |
+ Node* MergeControl(Node* control, Node* other); |
+ Node* MergeEffect(Node* value, Node* other, Node* control); |
+ Node* MergeValue(Node* value, Node* other, Node* control); |
+ |
+ // Helpers to create new control nodes. |
+ Node* NewIfTrue() { return NewNode(common()->IfTrue()); } |
+ Node* NewIfFalse() { return NewNode(common()->IfFalse()); } |
+ Node* NewMerge() { return NewNode(common()->Merge(1)); } |
+ Node* NewLoop() { return NewNode(common()->Loop(1)); } |
+ Node* NewBranch(Node* condition) { |
+ return NewNode(common()->Branch(), condition); |
+ } |
+ |
+ protected: |
+ class Environment; |
+ friend class ControlBuilder; |
+ |
+ // The following method creates a new node having the specified operator and |
+ // ensures effect and control dependencies are wired up. The dependencies |
+ // tracked by the environment might be mutated. |
+ virtual Node* MakeNode(Operator* op, int value_input_count, |
+ Node** value_inputs); |
+ |
+ Environment* environment_internal() const { return environment_; } |
+ void set_environment(Environment* env) { environment_ = env; } |
+ |
+ Node* current_context() const { return current_context_; } |
+ void set_current_context(Node* context) { current_context_ = context; } |
+ |
+ Node* exit_control() const { return exit_control_; } |
+ void set_exit_control(Node* node) { exit_control_ = node; } |
+ |
+ Node* dead_control(); |
+ |
+ // TODO(mstarzinger): Use phase-local zone instead! |
+ Zone* zone() const { return graph()->zone(); } |
+ Isolate* isolate() const { return zone()->isolate(); } |
+ CommonOperatorBuilder* common() const { return common_; } |
+ |
+ // Helper to wrap a Handle<T> into a Unique<T>. |
+ template <class T> |
+ PrintableUnique<T> MakeUnique(Handle<T> object) { |
+ return PrintableUnique<T>::CreateUninitialized(zone(), object); |
+ } |
+ |
+ // Support for control flow builders. The concrete type of the environment |
+ // depends on the graph builder, but environments themselves are not virtual. |
+ virtual Environment* CopyEnvironment(Environment* env); |
+ |
+ // Helper when creating node that depends on control. |
+ Node* GetControlDependency(); |
+ |
+ // Helper when creating node that updates control. |
+ void UpdateControlDependency(Node* new_control); |
+ |
+ // Helper to indicate a node exits the function body. |
+ void UpdateControlDependencyToLeaveFunction(Node* exit); |
+ |
+ private: |
+ CommonOperatorBuilder* common_; |
+ Environment* environment_; |
+ |
+ // Node representing the control dependency for dead code. |
+ SetOncePointer<Node> dead_control_; |
+ |
+ // Node representing the current context within the function body. |
+ Node* current_context_; |
+ |
+ // Merge of all control nodes that exit the function body. |
+ Node* exit_control_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(StructuredGraphBuilder); |
+}; |
+ |
+ |
+// The abstract execution environment contains static knowledge about |
+// execution state at arbitrary control-flow points. It allows for |
+// simulation of the control-flow at compile time. |
+class StructuredGraphBuilder::Environment : public ZoneObject { |
+ public: |
+ Environment(StructuredGraphBuilder* builder, Node* control_dependency); |
+ Environment(const Environment& copy); |
+ |
+ // Control dependency tracked by this environment. |
+ Node* GetControlDependency() { return control_dependency_; } |
+ void UpdateControlDependency(Node* dependency) { |
+ control_dependency_ = dependency; |
+ } |
+ |
+ // Effect dependency tracked by this environment. |
+ Node* GetEffectDependency() { return effect_dependency_; } |
+ void UpdateEffectDependency(Node* dependency) { |
+ effect_dependency_ = dependency; |
+ } |
+ |
+ // Mark this environment as being unreachable. |
+ void MarkAsUnreachable() { |
+ UpdateControlDependency(builder()->dead_control()); |
+ } |
+ bool IsMarkedAsUnreachable() { |
+ return GetControlDependency()->opcode() == IrOpcode::kDead; |
+ } |
+ |
+ // Merge another environment into this one. |
+ void Merge(Environment* other); |
+ |
+ // Copies this environment at a control-flow split point. |
+ Environment* CopyForConditional() { return builder()->CopyEnvironment(this); } |
+ |
+ // Copies this environment to a potentially unreachable control-flow point. |
+ Environment* CopyAsUnreachable() { |
+ Environment* env = builder()->CopyEnvironment(this); |
+ env->MarkAsUnreachable(); |
+ return env; |
+ } |
+ |
+ // Copies this environment at a loop header control-flow point. |
+ Environment* CopyForLoop() { |
+ PrepareForLoop(); |
+ return builder()->CopyEnvironment(this); |
+ } |
+ |
+ protected: |
+ // TODO(mstarzinger): Use phase-local zone instead! |
+ Zone* zone() const { return graph()->zone(); } |
+ Graph* graph() const { return builder_->graph(); } |
+ StructuredGraphBuilder* builder() const { return builder_; } |
+ CommonOperatorBuilder* common() { return builder_->common(); } |
+ NodeVector* values() { return &values_; } |
+ |
+ // Prepare environment to be used as loop header. |
+ void PrepareForLoop(); |
+ |
+ private: |
+ StructuredGraphBuilder* builder_; |
+ Node* control_dependency_; |
+ Node* effect_dependency_; |
+ NodeVector values_; |
+}; |
+} |
+} |
+} // namespace v8::internal::compiler |
+ |
+#endif // V8_COMPILER_GRAPH_BUILDER_H__ |