Chromium Code Reviews| 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 |