Index: src/compiler/node-sketch.cc |
diff --git a/src/compiler/node-sketch.cc b/src/compiler/node-sketch.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..66eb0a0f3b033b586c6b33a08ad5db9a5c30c62a |
--- /dev/null |
+++ b/src/compiler/node-sketch.cc |
@@ -0,0 +1,147 @@ |
+// Copyright 2014 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. |
+ |
+#include "src/compiler/opcodes.h" |
+#include "src/compiler/operator.h" |
+#include "src/zone.h" |
+#include "src/zone-allocator.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace compiler { |
+ |
+//==={ Node }=================================================================== |
+// Represents a node in the graph. Every node has 0 or more outputs and 0 or |
+// more inputs. Edges go between inputs and outputs and not between nodes. |
+class Node { |
+ public: |
+ // Represents the different kinds of edges in the graph. |
+ enum EdgeKind { kValue, kEffect, kControl }; |
+ |
+ class Output; |
+ //==={ Input }================================================================ |
+ // Represents an input to a node. Every input has an edge kind and an index. |
+ // An input can be connected to at most one output at a time, and the edge |
+ // kind between the input and the output must always match. |
+ class Input { |
+ public: |
+ // Get the owning node of this input. Note: not the owner of the |
+ // output to which this input is connected. |
+ Node* node(); |
+ |
+ // Get the index of this input relative to all the inputs for |
+ // this node. |
+ int index() { return static_cast<int>(tag_ >> 2); } |
+ |
+ // Get the edge kind of this input. |
+ EdgeKind kind() { return static_cast<EdgeKind>(tag_ & 3); } |
+ |
+ // Get the target output to which this input is connected. |
+ Output* target() { return target_; } |
rossberg
2014/08/07 14:00:45
Isn't this rather a source than a target? The data
|
+ |
+ // Connect this input to the given output. |
+ void Connect(Output* out) { |
+ if (out == target_) return; // Redundant. |
rossberg
2014/08/07 14:00:45
Hm, when would you willingly connect the same edge
|
+ if (out == NULL) { |
+ if (target_ != NULL) target_->RemoveUse(this); |
+ target_ = NULL; |
+ } else { |
+ DCHECK_EQ(kind(), out->kind()); |
+ target_->RemoveUse(this); |
+ target_ = out; |
+ target_->AddUse(this); |
+ } |
+ } |
+ |
+ private: |
+ int32_t tag_; // both the index and the edge kind. |
+ Output* target_; // the target output to which this input is connected. |
+ }; |
+ |
+ //==={ Output }=============================================================== |
+ // Represents an output from a node. Every output has an edge kind and an |
+ // index. Many inputs may be connected to this output, and they are recorded |
+ // in an internal use list. |
+ class Output { |
+ public: |
+ // Get the owning node of this output. |
+ Node* node() { return reinterpret_cast<Node*>(this + index()); } |
+ |
+ // Get the edge kind of this output. |
+ EdgeKind kind() { return static_cast<EdgeKind>(tag_ & 3); } |
+ |
+ // Get the index of this output. |
+ int index() { return tag_ & 0x4 ? tag_ >> 3 : 0; } |
+ |
+ // Replace uses of this output with {that}. |
+ void ReplaceUses(Output* that); |
+ |
+ private: |
+ int32_t tag_; // both the index and the edge kind; if output 0, stores |
+ // the node id. |
+ void* uses; // pointer to either the single {Input} using this or an |
+ // out-of-line array of inputs that use this output. |
+ |
+ friend class Input; |
+ friend class Node; |
+ |
+ void RemoveUse(Input* input); |
+ void AddUse(Input* input); |
+ }; |
+ |
+ //==={ Node public API }====================================================== |
+ |
+ // Get the unique id of this node. |
+ int id() { return output0_.tag_ >> 3; } // id of node is stored in output0. |
+ |
+ // Get the output of this node at the given index. |
+ Output* OutputAt(int index) { return (&output0_) - index; } |
+ |
+ // Get the input of this node at the given index. |
+ Input* InputAt(int index) { return &inputs_[index]; } |
+ |
+ // Get the operator associated with this node. |
+ Operator* op() { return op_; } |
+ |
+ // Get the opcode of this node (from the operator). |
+ IrOpcode::Value opcode() { |
+ return static_cast<IrOpcode::Value>(op_->opcode()); |
+ } |
+ |
+ private: |
+ Output output0_; // The first output of this node. |
+ Operator* op_; // operator of this node. |
+ Input* inputs_; // inputs to this node. |
+}; |
+ |
+ |
+// Graphs are made of nodes. |
+class Graph { |
+ public: |
+ // Get the count of nodes created in this graph so far. |
+ int NodeCount() { return node_count_; } |
+ |
+ // Create a new node in this graph and connect its inputs to the targets. |
+ Node* NewNode(Operator* op, Node::Output** targets, int count); |
+ |
+ // Connect the input of the node at {index} to the output {out}. |
+ void ConnectInputAt(Node* node, int index, Node::Output* out) { |
+ node->InputAt(index)->Connect(out); |
+ } |
+ |
+ // Remove all but {count} inputs from this node. |
+ void TrimInputs(Node* node, int count); |
+ |
+ // Append a new input at the given node and connect it to {out}. |
+ void AppendInput(Node* node, Node::Output* out); |
+ |
+ private: |
+ Zone* zone_; |
+ Node* start_; |
+ Node* end_; |
+ int node_count_; |
+}; |
+} |
+} |
+} // namespace v8::internal::compiler |