// 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);
// }
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));
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()) {
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) {
// 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_;
};
}
-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;
}
static void PrintReplay(Graph* graph) {}
#endif
- GenericGraphVisit::Control Pre(Node* node);
+ void Pre(Node* node);
void PostEdge(Node* from, int index, Node* to);
private:
void Print() { const_cast<Graph*>(graph_)->VisitNodeInputsFromEnd(this); }
- GenericGraphVisit::Control Pre(Node* node);
+ void Pre(Node* node);
private:
std::ostream& os_;
};
-GenericGraphVisit::Control JSONGraphNodeWriter::Pre(Node* node) {
+void JSONGraphNodeWriter::Pre(Node* node) {
if (first_node_) {
first_node_ = false;
} else {
os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
: "false");
os_ << "}";
- return GenericGraphVisit::CONTINUE;
}
void Print();
- GenericGraphVisit::Control Pre(Node* node);
+ void Pre(Node* node);
private:
void AnnotateNode(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) {
all_nodes_.insert(node);
if (use_to_def_) white_nodes_.insert(node);
}
- return GenericGraphVisit::CONTINUE;
}
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);
default:
break;
}
- return GenericGraphVisit::CONTINUE;
}
private:
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);
default:
break;
}
- return GenericGraphVisit::CONTINUE;
}
private:
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) {
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) {
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);
schedule_->AddNode(block, node);
}
}
-
- return GenericGraphVisit::CONTINUE;
}
void PostEdge(Node* from, int index, Node* to) {
: 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)
}
-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.
~Typer();
void Run();
- void Narrow(Node* node);
Graph* graph() { return graph_; }
MaybeHandle<Context> context() { return context_; }
private:
class Visitor;
class RunVisitor;
- class NarrowVisitor;
class WidenVisitor;
class Decorator;
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;
};
-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 =
// TODO(rossberg): Check.
break;
}
-
- return GenericGraphVisit::CONTINUE;
}
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_;
};
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_;
};
}
-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());