Commit 6f60c0d3 authored by Ben L. Titzer's avatar Ben L. Titzer

[turbofan] Add NodeMarker and use it in the GraphReducer.

R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/768763002

Cr-Commit-Position: refs/heads/master@{#25567}
parent 4893c0e3
......@@ -22,10 +22,10 @@ enum class GraphReducer::State : uint8_t {
GraphReducer::GraphReducer(Graph* graph, Zone* zone)
: graph_(graph),
state_(graph, 4),
reducers_(zone),
revisit_(zone),
stack_(zone),
state_(zone) {}
stack_(zone) {}
void GraphReducer::AddReducer(Reducer* reducer) {
......@@ -36,12 +36,8 @@ void GraphReducer::AddReducer(Reducer* reducer) {
void GraphReducer::ReduceNode(Node* node) {
DCHECK(stack_.empty());
DCHECK(revisit_.empty());
std::fill(state_.begin(), state_.end(), State::kUnvisited);
Push(node);
for (;;) {
DCHECK(!stack_.empty() ||
std::find(state_.begin(), state_.end(), State::kOnStack) ==
state_.end());
if (!stack_.empty()) {
// Process the node on the top of the stack, potentially pushing more or
// popping the node off the stack.
......@@ -50,7 +46,7 @@ void GraphReducer::ReduceNode(Node* node) {
// If the stack becomes empty, revisit any nodes in the revisit queue.
Node* const node = revisit_.top();
revisit_.pop();
if (state_[node->id()] == State::kRevisit) {
if (state_.Get(node) == State::kRevisit) {
// state can change while in queue.
Push(node);
}
......@@ -58,8 +54,6 @@ void GraphReducer::ReduceNode(Node* node) {
break;
}
}
DCHECK(std::find(state_.begin(), state_.end(), State::kOnStack) ==
state_.end());
DCHECK(revisit_.empty());
DCHECK(stack_.empty());
}
......@@ -101,7 +95,7 @@ Reduction GraphReducer::Reduce(Node* const node) {
void GraphReducer::ReduceTop() {
NodeState& entry = stack_.top();
Node* node = entry.node;
DCHECK(state_[node->id()] == State::kOnStack);
DCHECK(state_.Get(node) == State::kOnStack);
if (node->IsDead()) return Pop(); // Node was killed while on stack.
......@@ -164,34 +158,29 @@ void GraphReducer::ReduceTop() {
void GraphReducer::Pop() {
Node* const node = stack_.top().node;
state_[node->id()] = State::kVisited;
Node* node = stack_.top().node;
state_.Set(node, State::kVisited);
stack_.pop();
}
void GraphReducer::Push(Node* const node) {
size_t const id = static_cast<size_t>(node->id());
if (id >= state_.size()) state_.resize(id + 1);
DCHECK(id < state_.size());
DCHECK(state_[id] != State::kOnStack);
state_[id] = State::kOnStack;
DCHECK(state_.Get(node) != State::kOnStack);
state_.Set(node, State::kOnStack);
stack_.push({node, 0});
}
bool GraphReducer::Recurse(Node* const node) {
size_t const id = static_cast<size_t>(node->id());
if (id < state_.size() && state_[id] > State::kRevisit) return false;
bool GraphReducer::Recurse(Node* node) {
if (state_.Get(node) > State::kRevisit) return false;
Push(node);
return true;
}
void GraphReducer::Revisit(Node* const node) {
size_t const id = static_cast<size_t>(node->id());
if (id < state_.size() && state_[id] == State::kVisited) {
state_[id] = State::kRevisit;
void GraphReducer::Revisit(Node* node) {
if (state_.Get(node) == State::kVisited) {
state_.Set(node, State::kRevisit);
revisit_.push(node);
}
}
......
......@@ -5,17 +5,13 @@
#ifndef V8_COMPILER_GRAPH_REDUCER_H_
#define V8_COMPILER_GRAPH_REDUCER_H_
#include "src/compiler/graph.h"
#include "src/zone-containers.h"
namespace v8 {
namespace internal {
namespace compiler {
// Forward declarations.
class Graph;
class Node;
// Represents the result of trying to reduce a node in the graph.
class Reduction FINAL {
public:
......@@ -80,17 +76,17 @@ class GraphReducer FINAL {
// Node stack operations.
void Pop();
void Push(Node* const);
void Push(Node* node);
// Revisit queue operations.
bool Recurse(Node* const);
void Revisit(Node* const);
bool Recurse(Node* node);
void Revisit(Node* node);
Graph* graph_;
NodeMarker<State> state_;
ZoneVector<Reducer*> reducers_;
ZoneStack<Node*> revisit_;
ZoneStack<NodeState> stack_;
ZoneDeque<State> state_;
DISALLOW_COPY_AND_ASSIGN(GraphReducer);
};
......
......@@ -19,7 +19,8 @@ namespace v8 {
namespace internal {
namespace compiler {
Graph::Graph(Zone* zone) : GenericGraph<Node>(zone), decorators_(zone) {}
Graph::Graph(Zone* zone)
: GenericGraph<Node>(zone), mark_max_(0), decorators_(zone) {}
void Graph::Decorate(Node* node) {
......
......@@ -19,7 +19,6 @@ namespace compiler {
class GraphDecorator;
class Graph : public GenericGraph<Node> {
public:
explicit Graph(Zone* zone);
......@@ -78,10 +77,50 @@ class Graph : public GenericGraph<Node> {
}
private:
template <typename State>
friend class NodeMarker;
Mark mark_max_;
ZoneVector<GraphDecorator*> decorators_;
};
// A NodeMarker uses monotonically increasing marks to assign local "states"
// to nodes. Only one NodeMarker per graph is valid at a given time.
template <typename State>
class NodeMarker BASE_EMBEDDED {
public:
NodeMarker(Graph* graph, uint32_t num_states)
: mark_min_(graph->mark_max_), mark_max_(graph->mark_max_ += num_states) {
DCHECK(num_states > 0); // user error!
DCHECK(mark_max_ > mark_min_); // check for wraparound.
}
State Get(Node* node) {
Mark mark = node->mark();
if (mark < mark_min_) {
mark = mark_min_;
node->set_mark(mark_min_);
}
DCHECK_LT(mark, mark_max_);
return static_cast<State>(mark - mark_min_);
}
void Set(Node* node, State state) {
Mark local = static_cast<Mark>(state);
DCHECK(local < (mark_max_ - mark_min_));
DCHECK_LT(node->mark(), mark_max_);
node->set_mark(local + mark_min_);
}
private:
Mark mark_min_;
Mark mark_max_;
};
// A graph decorator can be used to add behavior to the creation of nodes
// in a graph.
class GraphDecorator : public ZoneObject {
public:
virtual ~GraphDecorator() {}
......
......@@ -21,6 +21,11 @@ namespace v8 {
namespace internal {
namespace compiler {
// Marks are used during traversal of the graph to distinguish states of nodes.
// Each node has a mark which is a monotonically increasing integer, and a
// {NodeMarker} has a range of values that indicate states of a node.
typedef uint32_t Mark;
class NodeData {
public:
const Operator* op() const { return op_; }
......@@ -34,11 +39,19 @@ class NodeData {
protected:
const Operator* op_;
Bounds bounds_;
Mark mark_;
explicit NodeData(Zone* zone) {}
friend class NodeProperties;
template <typename State>
friend class NodeMarker;
Bounds bounds() { return bounds_; }
void set_bounds(Bounds b) { bounds_ = b; }
// Only NodeMarkers should manipulate the marks on nodes.
Mark mark() { return mark_; }
void set_mark(Mark mark) { mark_ = mark; }
};
// A Node is the basic primitive of an IR graph. In addition to the members
......@@ -51,7 +64,10 @@ class Node FINAL : public GenericNode<NodeData, Node> {
Node(GenericGraphBase* graph, int input_count, int reserve_input_count)
: GenericNode<NodeData, Node>(graph, input_count, reserve_input_count) {}
void Initialize(const Operator* op) { set_op(op); }
void Initialize(const Operator* op) {
set_op(op);
set_mark(0);
}
bool IsDead() const { return InputCount() > 0 && InputAt(0) == NULL; }
void Kill();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment