Make generic algorithm less generic.

R=jarin@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25064}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25064 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mstarzinger@chromium.org 2014-11-03 10:30:34 +00:00
parent bb78f231ab
commit c63deb9b56
12 changed files with 26 additions and 223 deletions

View File

@ -23,16 +23,9 @@ namespace compiler {
// by specifying custom traits.
class GenericGraphVisit {
public:
enum Control {
CONTINUE = 0x0, // Continue depth-first normally
SKIP = 0x1, // Skip this node and its successors
REENTER = 0x2, // Allow reentering this node
DEFER = SKIP | REENTER
};
// struct Visitor {
// Control Pre(Traits::Node* current);
// Control Post(Traits::Node* current);
// void Pre(Traits::Node* current);
// void Post(Traits::Node* current);
// void PreEdge(Traits::Node* from, int index, Traits::Node* to);
// void PostEdge(Traits::Node* from, int index, Traits::Node* to);
// }
@ -54,9 +47,8 @@ class GenericGraphVisit {
DCHECK(id < Traits::max_id(graph)); // Must be a valid id.
bool visit = !GetVisited(&visited, id);
if (visit) {
Control control = visitor->Pre(current);
visit = !IsSkip(control);
if (!IsReenter(control)) SetVisited(&visited, id, true);
visitor->Pre(current);
SetVisited(&visited, id);
}
Iterator begin(visit ? Traits::begin(current) : Traits::end(current));
Iterator end(Traits::end(current));
@ -66,9 +58,8 @@ class GenericGraphVisit {
NodeState top = stack.top();
if (top.first == top.second) {
if (visit) {
Control control = visitor->Post(post_order_node);
DCHECK(!IsSkip(control));
SetVisited(&visited, post_order_node->id(), !IsReenter(control));
visitor->Post(post_order_node);
SetVisited(&visited, post_order_node->id());
}
stack.pop();
if (stack.empty()) {
@ -101,23 +92,19 @@ class GenericGraphVisit {
template <class B, class S>
struct NullNodeVisitor {
Control Pre(GenericNode<B, S>* node) { return CONTINUE; }
Control Post(GenericNode<B, S>* node) { return CONTINUE; }
void Pre(GenericNode<B, S>* node) {}
void Post(GenericNode<B, S>* node) {}
void PreEdge(GenericNode<B, S>* from, int index, GenericNode<B, S>* to) {}
void PostEdge(GenericNode<B, S>* from, int index, GenericNode<B, S>* to) {}
};
private:
static bool IsSkip(Control c) { return c & SKIP; }
static bool IsReenter(Control c) { return c & REENTER; }
// TODO(turbofan): resizing could be optionally templatized away.
static void SetVisited(BoolVector* visited, int id, bool value) {
static void SetVisited(BoolVector* visited, int id) {
if (id >= static_cast<int>(visited->size())) {
// Resize and set all values to unvisited.
visited->resize((3 * id) / 2, false);
}
visited->at(id) = value;
visited->at(id) = true;
}
static bool GetVisited(BoolVector* visited, int id) {

View File

@ -72,10 +72,7 @@ void GraphReducer::ReduceNode(Node* node) {
// A helper class to reuse the node traversal algorithm.
struct GraphReducerVisitor FINAL : public NullNodeVisitor {
explicit GraphReducerVisitor(GraphReducer* reducer) : reducer_(reducer) {}
GenericGraphVisit::Control Post(Node* node) {
reducer_->ReduceNode(node);
return GenericGraphVisit::CONTINUE;
}
void Post(Node* node) { reducer_->ReduceNode(node); }
GraphReducer* reducer_;
};

View File

@ -24,14 +24,13 @@ void GraphReplayPrinter::PrintReplay(Graph* graph) {
}
GenericGraphVisit::Control GraphReplayPrinter::Pre(Node* node) {
void GraphReplayPrinter::Pre(Node* node) {
PrintReplayOpCreator(node->op());
PrintF(" Node* n%d = graph.NewNode(op", node->id());
for (int i = 0; i < node->InputCount(); ++i) {
PrintF(", nil");
}
PrintF("); USE(n%d);\n", node->id());
return GenericGraphVisit::CONTINUE;
}

View File

@ -25,7 +25,7 @@ class GraphReplayPrinter FINAL : public NullNodeVisitor {
static void PrintReplay(Graph* graph) {}
#endif
GenericGraphVisit::Control Pre(Node* node);
void Pre(Node* node);
void PostEdge(Node* from, int index, Node* to);
private:

View File

@ -66,7 +66,7 @@ class JSONGraphNodeWriter : public NullNodeVisitor {
void Print() { const_cast<Graph*>(graph_)->VisitNodeInputsFromEnd(this); }
GenericGraphVisit::Control Pre(Node* node);
void Pre(Node* node);
private:
std::ostream& os_;
@ -77,7 +77,7 @@ class JSONGraphNodeWriter : public NullNodeVisitor {
};
GenericGraphVisit::Control JSONGraphNodeWriter::Pre(Node* node) {
void JSONGraphNodeWriter::Pre(Node* node) {
if (first_node_) {
first_node_ = false;
} else {
@ -105,7 +105,6 @@ GenericGraphVisit::Control JSONGraphNodeWriter::Pre(Node* node) {
os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
: "false");
os_ << "}";
return GenericGraphVisit::CONTINUE;
}
@ -172,7 +171,7 @@ class GraphVisualizer : public NullNodeVisitor {
void Print();
GenericGraphVisit::Control Pre(Node* node);
void Pre(Node* node);
private:
void AnnotateNode(Node* node);
@ -202,7 +201,7 @@ static Node* GetControlCluster(Node* node) {
}
GenericGraphVisit::Control GraphVisualizer::Pre(Node* node) {
void GraphVisualizer::Pre(Node* node) {
if (all_nodes_.count(node) == 0) {
Node* control_cluster = GetControlCluster(node);
if (control_cluster != NULL) {
@ -215,7 +214,6 @@ GenericGraphVisit::Control GraphVisualizer::Pre(Node* node) {
all_nodes_.insert(node);
if (use_to_def_) white_nodes_.insert(node);
}
return GenericGraphVisit::CONTINUE;
}

View File

@ -20,7 +20,7 @@ class ContextSpecializationVisitor : public NullNodeVisitor {
explicit ContextSpecializationVisitor(JSContextSpecializer* spec)
: spec_(spec) {}
GenericGraphVisit::Control Post(Node* node) {
void Post(Node* node) {
switch (node->opcode()) {
case IrOpcode::kJSLoadContext: {
Reduction r = spec_->ReduceJSLoadContext(node);
@ -41,7 +41,6 @@ class ContextSpecializationVisitor : public NullNodeVisitor {
default:
break;
}
return GenericGraphVisit::CONTINUE;
}
private:

View File

@ -32,7 +32,7 @@ class InlinerVisitor : public NullNodeVisitor {
public:
explicit InlinerVisitor(JSInliner* inliner) : inliner_(inliner) {}
GenericGraphVisit::Control Post(Node* node) {
void Post(Node* node) {
switch (node->opcode()) {
case IrOpcode::kJSCallFunction:
inliner_->TryInlineJSCall(node);
@ -45,7 +45,6 @@ class InlinerVisitor : public NullNodeVisitor {
default:
break;
}
return GenericGraphVisit::CONTINUE;
}
private:
@ -167,7 +166,7 @@ class CopyVisitor : public NullNodeVisitor {
sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "sentinel", 0, 0,
0, 0, 0, 0) {}
GenericGraphVisit::Control Post(Node* original) {
void Post(Node* original) {
NodeVector inputs(temp_zone_);
for (InputIter it = original->inputs().begin();
it != original->inputs().end(); ++it) {
@ -180,7 +179,6 @@ class CopyVisitor : public NullNodeVisitor {
target_graph_->NewNode(original->op(), static_cast<int>(inputs.size()),
(inputs.empty() ? NULL : &inputs.front()));
copies_[original->id()] = copy;
return GenericGraphVisit::CONTINUE;
}
Node* GetCopy(Node* original) {

View File

@ -1012,7 +1012,7 @@ class PrepareUsesVisitor : public NullNodeVisitor {
explicit PrepareUsesVisitor(Scheduler* scheduler)
: scheduler_(scheduler), schedule_(scheduler->schedule_) {}
GenericGraphVisit::Control Pre(Node* node) {
void Pre(Node* node) {
if (scheduler_->GetPlacement(node) == Scheduler::kFixed) {
// Fixed nodes are always roots for schedule late.
scheduler_->schedule_root_nodes_.push_back(node);
@ -1029,8 +1029,6 @@ class PrepareUsesVisitor : public NullNodeVisitor {
schedule_->AddNode(block, node);
}
}
return GenericGraphVisit::CONTINUE;
}
void PostEdge(Node* from, int index, Node* to) {

View File

@ -251,44 +251,19 @@ class Typer::RunVisitor : public Typer::Visitor {
: Visitor(typer),
redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {}
GenericGraphVisit::Control Post(Node* node) {
void Post(Node* node) {
if (node->op()->ValueOutputCount() > 0) {
Bounds bounds = TypeNode(node);
NodeProperties::SetBounds(node, bounds);
// Remember incompletely typed nodes for least fixpoint iteration.
if (!NodeProperties::AllValueInputsAreTyped(node)) redo.insert(node);
}
return GenericGraphVisit::CONTINUE;
}
NodeSet redo;
};
class Typer::NarrowVisitor : public Typer::Visitor {
public:
explicit NarrowVisitor(Typer* typer) : Visitor(typer) {}
GenericGraphVisit::Control Pre(Node* node) {
if (node->op()->ValueOutputCount() > 0) {
Bounds previous = NodeProperties::GetBounds(node);
Bounds current = TypeNode(node);
NodeProperties::SetBounds(node, Bounds::Both(current, previous, zone()));
DCHECK(current.Narrows(previous));
// Stop when nothing changed (but allow re-entry in case it does later).
return previous.Narrows(current) ? GenericGraphVisit::DEFER
: GenericGraphVisit::REENTER;
} else {
return GenericGraphVisit::SKIP;
}
}
GenericGraphVisit::Control Post(Node* node) {
return GenericGraphVisit::REENTER;
}
};
class Typer::WidenVisitor : public Typer::Visitor {
public:
explicit WidenVisitor(Typer* typer)
@ -361,12 +336,6 @@ void Typer::Run() {
}
void Typer::Narrow(Node* start) {
NarrowVisitor typing(this);
graph_->VisitNodeUsesFrom(start, &typing);
}
void Typer::Decorator::Decorate(Node* node) {
if (node->op()->ValueOutputCount() > 0) {
// Only eagerly type-decorate nodes with known input types.

View File

@ -21,7 +21,6 @@ class Typer {
~Typer();
void Run();
void Narrow(Node* node);
Graph* graph() { return graph_; }
MaybeHandle<Context> context() { return context_; }
@ -31,7 +30,6 @@ class Typer {
private:
class Visitor;
class RunVisitor;
class NarrowVisitor;
class WidenVisitor;
class Decorator;

View File

@ -52,7 +52,7 @@ class Verifier::Visitor : public NullNodeVisitor {
Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {}
// Fulfills the PreNodeCallback interface.
GenericGraphVisit::Control Pre(Node* node);
void Pre(Node* node);
Zone* zone;
Typing typing;
@ -120,7 +120,7 @@ class Verifier::Visitor : public NullNodeVisitor {
};
GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
void Verifier::Visitor::Pre(Node* node) {
int value_count = node->op()->ValueInputCount();
int context_count = OperatorProperties::GetContextInputCount(node->op());
int frame_state_count =
@ -728,8 +728,6 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// TODO(rossberg): Check.
break;
}
return GenericGraphVisit::CONTINUE;
}

View File

@ -23,10 +23,9 @@ static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
class PreNodeVisitor : public NullNodeVisitor {
public:
GenericGraphVisit::Control Pre(Node* node) {
void Pre(Node* node) {
printf("NODE ID: %d\n", node->id());
nodes_.push_back(node);
return GenericGraphVisit::CONTINUE;
}
std::vector<Node*> nodes_;
};
@ -34,10 +33,9 @@ class PreNodeVisitor : public NullNodeVisitor {
class PostNodeVisitor : public NullNodeVisitor {
public:
GenericGraphVisit::Control Post(Node* node) {
void Post(Node* node) {
printf("NODE ID: %d\n", node->id());
nodes_.push_back(node);
return GenericGraphVisit::CONTINUE;
}
std::vector<Node*> nodes_;
};
@ -173,142 +171,6 @@ TEST(TestUseNodePreOrderVisitCycle) {
}
struct ReenterNodeVisitor : NullNodeVisitor {
GenericGraphVisit::Control Pre(Node* node) {
printf("[%d] PRE NODE: %d\n", static_cast<int>(nodes_.size()), node->id());
nodes_.push_back(node->id());
int size = static_cast<int>(nodes_.size());
switch (node->id()) {
case 0:
return size < 6 ? GenericGraphVisit::REENTER : GenericGraphVisit::SKIP;
case 1:
return size < 4 ? GenericGraphVisit::DEFER
: GenericGraphVisit::CONTINUE;
default:
return GenericGraphVisit::REENTER;
}
}
GenericGraphVisit::Control Post(Node* node) {
printf("[%d] POST NODE: %d\n", static_cast<int>(nodes_.size()), node->id());
nodes_.push_back(-node->id());
return node->id() == 4 ? GenericGraphVisit::REENTER
: GenericGraphVisit::CONTINUE;
}
void PreEdge(Node* from, int index, Node* to) {
printf("[%d] PRE EDGE: %d-%d\n", static_cast<int>(edges_.size()),
from->id(), to->id());
edges_.push_back(std::make_pair(from->id(), to->id()));
}
void PostEdge(Node* from, int index, Node* to) {
printf("[%d] POST EDGE: %d-%d\n", static_cast<int>(edges_.size()),
from->id(), to->id());
edges_.push_back(std::make_pair(-from->id(), -to->id()));
}
std::vector<int> nodes_;
std::vector<std::pair<int, int> > edges_;
};
TEST(TestUseNodeReenterVisit) {
GraphWithStartNodeTester graph;
Node* n0 = graph.start_node();
Node* n1 = graph.NewNode(&dummy_operator, n0);
Node* n2 = graph.NewNode(&dummy_operator, n0);
Node* n3 = graph.NewNode(&dummy_operator, n2);
Node* n4 = graph.NewNode(&dummy_operator, n0);
Node* n5 = graph.NewNode(&dummy_operator, n4);
n0->AppendInput(graph.main_zone(), n3);
graph.SetStart(n0);
graph.SetEnd(n5);
ReenterNodeVisitor visitor;
graph.VisitNodeUsesFromStart(&visitor);
CHECK_EQ(22, static_cast<int>(visitor.nodes_.size()));
CHECK_EQ(24, static_cast<int>(visitor.edges_.size()));
CHECK(n0->id() == visitor.nodes_[0]);
CHECK(n0->id() == visitor.edges_[0].first);
CHECK(n1->id() == visitor.edges_[0].second);
CHECK(n1->id() == visitor.nodes_[1]);
// N1 is deferred.
CHECK(-n1->id() == visitor.edges_[1].second);
CHECK(-n0->id() == visitor.edges_[1].first);
CHECK(n0->id() == visitor.edges_[2].first);
CHECK(n2->id() == visitor.edges_[2].second);
CHECK(n2->id() == visitor.nodes_[2]);
CHECK(n2->id() == visitor.edges_[3].first);
CHECK(n3->id() == visitor.edges_[3].second);
CHECK(n3->id() == visitor.nodes_[3]);
// Circle back to N0, which we may reenter for now.
CHECK(n3->id() == visitor.edges_[4].first);
CHECK(n0->id() == visitor.edges_[4].second);
CHECK(n0->id() == visitor.nodes_[4]);
CHECK(n0->id() == visitor.edges_[5].first);
CHECK(n1->id() == visitor.edges_[5].second);
CHECK(n1->id() == visitor.nodes_[5]);
// This time N1 is no longer deferred.
CHECK(-n1->id() == visitor.nodes_[6]);
CHECK(-n1->id() == visitor.edges_[6].second);
CHECK(-n0->id() == visitor.edges_[6].first);
CHECK(n0->id() == visitor.edges_[7].first);
CHECK(n2->id() == visitor.edges_[7].second);
CHECK(n2->id() == visitor.nodes_[7]);
CHECK(n2->id() == visitor.edges_[8].first);
CHECK(n3->id() == visitor.edges_[8].second);
CHECK(n3->id() == visitor.nodes_[8]);
CHECK(n3->id() == visitor.edges_[9].first);
CHECK(n0->id() == visitor.edges_[9].second);
CHECK(n0->id() == visitor.nodes_[9]);
// This time we break at N0 and skip it.
CHECK(-n0->id() == visitor.edges_[10].second);
CHECK(-n3->id() == visitor.edges_[10].first);
CHECK(-n3->id() == visitor.nodes_[10]);
CHECK(-n3->id() == visitor.edges_[11].second);
CHECK(-n2->id() == visitor.edges_[11].first);
CHECK(-n2->id() == visitor.nodes_[11]);
CHECK(-n2->id() == visitor.edges_[12].second);
CHECK(-n0->id() == visitor.edges_[12].first);
CHECK(n0->id() == visitor.edges_[13].first);
CHECK(n4->id() == visitor.edges_[13].second);
CHECK(n4->id() == visitor.nodes_[12]);
CHECK(n4->id() == visitor.edges_[14].first);
CHECK(n5->id() == visitor.edges_[14].second);
CHECK(n5->id() == visitor.nodes_[13]);
CHECK(-n5->id() == visitor.nodes_[14]);
CHECK(-n5->id() == visitor.edges_[15].second);
CHECK(-n4->id() == visitor.edges_[15].first);
CHECK(-n4->id() == visitor.nodes_[15]);
CHECK(-n4->id() == visitor.edges_[16].second);
CHECK(-n0->id() == visitor.edges_[16].first);
CHECK(-n0->id() == visitor.nodes_[16]);
CHECK(-n0->id() == visitor.edges_[17].second);
CHECK(-n3->id() == visitor.edges_[17].first);
CHECK(-n3->id() == visitor.nodes_[17]);
CHECK(-n3->id() == visitor.edges_[18].second);
CHECK(-n2->id() == visitor.edges_[18].first);
CHECK(-n2->id() == visitor.nodes_[18]);
CHECK(-n2->id() == visitor.edges_[19].second);
CHECK(-n0->id() == visitor.edges_[19].first);
// N4 may be reentered.
CHECK(n0->id() == visitor.edges_[20].first);
CHECK(n4->id() == visitor.edges_[20].second);
CHECK(n4->id() == visitor.nodes_[19]);
CHECK(n4->id() == visitor.edges_[21].first);
CHECK(n5->id() == visitor.edges_[21].second);
CHECK(-n5->id() == visitor.edges_[22].second);
CHECK(-n4->id() == visitor.edges_[22].first);
CHECK(-n4->id() == visitor.nodes_[20]);
CHECK(-n4->id() == visitor.edges_[23].second);
CHECK(-n0->id() == visitor.edges_[23].first);
CHECK(-n0->id() == visitor.nodes_[21]);
}
TEST(TestPrintNodeGraphToNodeGraphviz) {
GraphWithStartNodeTester graph;
Node* n2 = graph.NewNode(&dummy_operator, graph.start());