OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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 #include "src/compiler/opcodes.h" | |
6 #include "src/compiler/operator.h" | |
7 #include "src/zone.h" | |
8 #include "src/zone-allocator.h" | |
9 | |
10 namespace v8 { | |
11 namespace internal { | |
12 namespace compiler { | |
13 | |
14 //==={ Node }=================================================================== | |
15 // Represents a node in the graph. Every node has 0 or more outputs and 0 or | |
16 // more inputs. Edges go between inputs and outputs and not between nodes. | |
17 class Node { | |
18 public: | |
19 // Represents the different kinds of edges in the graph. | |
20 enum EdgeKind { kValue, kEffect, kControl }; | |
21 | |
22 class Output; | |
23 //==={ Input }================================================================ | |
24 // Represents an input to a node. Every input has an edge kind and an index. | |
25 // An input can be connected to at most one output at a time, and the edge | |
26 // kind between the input and the output must always match. | |
27 class Input { | |
28 public: | |
29 // Get the owning node of this input. Note: not the owner of the | |
30 // output to which this input is connected. | |
31 Node* node(); | |
32 | |
33 // Get the index of this input relative to all the inputs for | |
34 // this node. | |
35 int index() { return static_cast<int>(tag_ >> 2); } | |
36 | |
37 // Get the edge kind of this input. | |
38 EdgeKind kind() { return static_cast<EdgeKind>(tag_ & 3); } | |
39 | |
40 // Get the target output to which this input is connected. | |
41 Output* target() { return target_; } | |
rossberg
2014/08/07 14:00:45
Isn't this rather a source than a target? The data
| |
42 | |
43 // Connect this input to the given output. | |
44 void Connect(Output* out) { | |
45 if (out == target_) return; // Redundant. | |
rossberg
2014/08/07 14:00:45
Hm, when would you willingly connect the same edge
| |
46 if (out == NULL) { | |
47 if (target_ != NULL) target_->RemoveUse(this); | |
48 target_ = NULL; | |
49 } else { | |
50 DCHECK_EQ(kind(), out->kind()); | |
51 target_->RemoveUse(this); | |
52 target_ = out; | |
53 target_->AddUse(this); | |
54 } | |
55 } | |
56 | |
57 private: | |
58 int32_t tag_; // both the index and the edge kind. | |
59 Output* target_; // the target output to which this input is connected. | |
60 }; | |
61 | |
62 //==={ Output }=============================================================== | |
63 // Represents an output from a node. Every output has an edge kind and an | |
64 // index. Many inputs may be connected to this output, and they are recorded | |
65 // in an internal use list. | |
66 class Output { | |
67 public: | |
68 // Get the owning node of this output. | |
69 Node* node() { return reinterpret_cast<Node*>(this + index()); } | |
70 | |
71 // Get the edge kind of this output. | |
72 EdgeKind kind() { return static_cast<EdgeKind>(tag_ & 3); } | |
73 | |
74 // Get the index of this output. | |
75 int index() { return tag_ & 0x4 ? tag_ >> 3 : 0; } | |
76 | |
77 // Replace uses of this output with {that}. | |
78 void ReplaceUses(Output* that); | |
79 | |
80 private: | |
81 int32_t tag_; // both the index and the edge kind; if output 0, stores | |
82 // the node id. | |
83 void* uses; // pointer to either the single {Input} using this or an | |
84 // out-of-line array of inputs that use this output. | |
85 | |
86 friend class Input; | |
87 friend class Node; | |
88 | |
89 void RemoveUse(Input* input); | |
90 void AddUse(Input* input); | |
91 }; | |
92 | |
93 //==={ Node public API }====================================================== | |
94 | |
95 // Get the unique id of this node. | |
96 int id() { return output0_.tag_ >> 3; } // id of node is stored in output0. | |
97 | |
98 // Get the output of this node at the given index. | |
99 Output* OutputAt(int index) { return (&output0_) - index; } | |
100 | |
101 // Get the input of this node at the given index. | |
102 Input* InputAt(int index) { return &inputs_[index]; } | |
103 | |
104 // Get the operator associated with this node. | |
105 Operator* op() { return op_; } | |
106 | |
107 // Get the opcode of this node (from the operator). | |
108 IrOpcode::Value opcode() { | |
109 return static_cast<IrOpcode::Value>(op_->opcode()); | |
110 } | |
111 | |
112 private: | |
113 Output output0_; // The first output of this node. | |
114 Operator* op_; // operator of this node. | |
115 Input* inputs_; // inputs to this node. | |
116 }; | |
117 | |
118 | |
119 // Graphs are made of nodes. | |
120 class Graph { | |
121 public: | |
122 // Get the count of nodes created in this graph so far. | |
123 int NodeCount() { return node_count_; } | |
124 | |
125 // Create a new node in this graph and connect its inputs to the targets. | |
126 Node* NewNode(Operator* op, Node::Output** targets, int count); | |
127 | |
128 // Connect the input of the node at {index} to the output {out}. | |
129 void ConnectInputAt(Node* node, int index, Node::Output* out) { | |
130 node->InputAt(index)->Connect(out); | |
131 } | |
132 | |
133 // Remove all but {count} inputs from this node. | |
134 void TrimInputs(Node* node, int count); | |
135 | |
136 // Append a new input at the given node and connect it to {out}. | |
137 void AppendInput(Node* node, Node::Output* out); | |
138 | |
139 private: | |
140 Zone* zone_; | |
141 Node* start_; | |
142 Node* end_; | |
143 int node_count_; | |
144 }; | |
145 } | |
146 } | |
147 } // namespace v8::internal::compiler | |
OLD | NEW |