Commit 01766cd8 authored by bgeron's avatar bgeron Committed by Commit bot

[turbolizer] Visualize also the dead nodes.

R=danno,jarin
BUG=

Review-Url: https://codereview.chromium.org/2226293002
Cr-Commit-Position: refs/heads/master@{#38502}
parent 9243d5e3
...@@ -10,25 +10,33 @@ namespace v8 { ...@@ -10,25 +10,33 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
AllNodes::AllNodes(Zone* local_zone, const Graph* graph) AllNodes::AllNodes(Zone* local_zone, const Graph* graph, bool only_inputs)
: live(local_zone), is_live(graph->NodeCount(), false, local_zone) { : reachable(local_zone),
is_reachable_(graph->NodeCount(), false, local_zone),
only_inputs_(only_inputs) {
Node* end = graph->end(); Node* end = graph->end();
is_live[end->id()] = true; is_reachable_[end->id()] = true;
live.push_back(end); reachable.push_back(end);
// Find all live nodes reachable from end. // Find all nodes reachable from end.
for (size_t i = 0; i < live.size(); i++) { for (size_t i = 0; i < reachable.size(); i++) {
for (Node* const input : live[i]->inputs()) { for (Node* input : reachable[i]->inputs()) {
if (input == nullptr) { if (input == nullptr || input->id() >= graph->NodeCount()) {
// TODO(titzer): print a warning.
continue; continue;
} }
if (input->id() >= graph->NodeCount()) { if (!is_reachable_[input->id()]) {
// TODO(titzer): print a warning. is_reachable_[input->id()] = true;
continue; reachable.push_back(input);
} }
if (!is_live[input->id()]) { }
is_live[input->id()] = true; if (!only_inputs) {
live.push_back(input); for (Node* use : reachable[i]->uses()) {
if (use == nullptr || use->id() >= graph->NodeCount()) {
continue;
}
if (!is_reachable_[use->id()]) {
is_reachable_[use->id()] = true;
reachable.push_back(use);
}
} }
} }
} }
......
...@@ -16,19 +16,27 @@ namespace compiler { ...@@ -16,19 +16,27 @@ namespace compiler {
// from end. // from end.
class AllNodes { class AllNodes {
public: public:
// Constructor. Traverses the graph and builds the {live} sets. // Constructor. Traverses the graph and builds the {reachable} sets. When
AllNodes(Zone* local_zone, const Graph* graph); // {only_inputs} is true, find the nodes reachable through input edges;
// these are all live nodes.
AllNodes(Zone* local_zone, const Graph* graph, bool only_inputs = true);
bool IsLive(Node* node) { bool IsLive(Node* node) {
CHECK(only_inputs_);
return IsReachable(node);
}
bool IsReachable(Node* node) {
if (!node) return false; if (!node) return false;
size_t id = node->id(); size_t id = node->id();
return id < is_live.size() && is_live[id]; return id < is_reachable_.size() && is_reachable_[id];
} }
NodeVector live; // Nodes reachable from end. NodeVector reachable; // Nodes reachable from end.
private: private:
BoolVector is_live; BoolVector is_reachable_;
const bool only_inputs_;
}; };
} // namespace compiler } // namespace compiler
......
...@@ -331,7 +331,7 @@ Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index, ...@@ -331,7 +331,7 @@ Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index,
void EscapeAnalysisReducer::VerifyReplacement() const { void EscapeAnalysisReducer::VerifyReplacement() const {
#ifdef DEBUG #ifdef DEBUG
AllNodes all(zone(), jsgraph()->graph()); AllNodes all(zone(), jsgraph()->graph());
for (Node* node : all.live) { for (Node* node : all.reachable) {
if (node->opcode() == IrOpcode::kAllocate) { if (node->opcode() == IrOpcode::kAllocate) {
CHECK(!escape_analysis_->IsVirtual(node)); CHECK(!escape_analysis_->IsVirtual(node));
} }
......
...@@ -24,7 +24,7 @@ void GraphReplayPrinter::PrintReplay(Graph* graph) { ...@@ -24,7 +24,7 @@ void GraphReplayPrinter::PrintReplay(Graph* graph) {
AllNodes nodes(&zone, graph); AllNodes nodes(&zone, graph);
// Allocate the nodes first. // Allocate the nodes first.
for (Node* node : nodes.live) { for (Node* node : nodes.reachable) {
PrintReplayOpCreator(node->op()); PrintReplayOpCreator(node->op());
PrintF(" Node* n%d = graph()->NewNode(op", node->id()); PrintF(" Node* n%d = graph()->NewNode(op", node->id());
for (int i = 0; i < node->InputCount(); ++i) { for (int i = 0; i < node->InputCount(); ++i) {
...@@ -34,7 +34,7 @@ void GraphReplayPrinter::PrintReplay(Graph* graph) { ...@@ -34,7 +34,7 @@ void GraphReplayPrinter::PrintReplay(Graph* graph) {
} }
// Connect the nodes to their inputs. // Connect the nodes to their inputs.
for (Node* node : nodes.live) { for (Node* node : nodes.reachable) {
for (int i = 0; i < node->InputCount(); i++) { for (int i = 0; i < node->InputCount(); i++) {
PrintF(" n%d->ReplaceInput(%d, n%d);\n", node->id(), i, PrintF(" n%d->ReplaceInput(%d, n%d);\n", node->id(), i,
node->InputAt(i)->id()); node->InputAt(i)->id());
......
...@@ -113,10 +113,14 @@ class JSONGraphNodeWriter { ...@@ -113,10 +113,14 @@ class JSONGraphNodeWriter {
public: public:
JSONGraphNodeWriter(std::ostream& os, Zone* zone, const Graph* graph, JSONGraphNodeWriter(std::ostream& os, Zone* zone, const Graph* graph,
const SourcePositionTable* positions) const SourcePositionTable* positions)
: os_(os), all_(zone, graph), positions_(positions), first_node_(true) {} : os_(os),
all_(zone, graph, false),
live_(zone, graph, true),
positions_(positions),
first_node_(true) {}
void Print() { void Print() {
for (Node* const node : all_.live) PrintNode(node); for (Node* const node : all_.reachable) PrintNode(node);
os_ << "\n"; os_ << "\n";
} }
...@@ -133,6 +137,7 @@ class JSONGraphNodeWriter { ...@@ -133,6 +137,7 @@ class JSONGraphNodeWriter {
os_ << "{\"id\":" << SafeId(node) << ",\"label\":\"" << Escaped(label, "\"") os_ << "{\"id\":" << SafeId(node) << ",\"label\":\"" << Escaped(label, "\"")
<< "\"" << "\""
<< ",\"title\":\"" << Escaped(title, "\"") << "\"" << ",\"title\":\"" << Escaped(title, "\"") << "\""
<< ",\"live\": " << (live_.IsLive(node) ? "true" : "false")
<< ",\"properties\":\"" << Escaped(properties, "\"") << "\""; << ",\"properties\":\"" << Escaped(properties, "\"") << "\"";
IrOpcode::Value opcode = node->opcode(); IrOpcode::Value opcode = node->opcode();
if (IrOpcode::IsPhiOpcode(opcode)) { if (IrOpcode::IsPhiOpcode(opcode)) {
...@@ -173,6 +178,7 @@ class JSONGraphNodeWriter { ...@@ -173,6 +178,7 @@ class JSONGraphNodeWriter {
private: private:
std::ostream& os_; std::ostream& os_;
AllNodes all_; AllNodes all_;
AllNodes live_;
const SourcePositionTable* positions_; const SourcePositionTable* positions_;
bool first_node_; bool first_node_;
...@@ -183,10 +189,10 @@ class JSONGraphNodeWriter { ...@@ -183,10 +189,10 @@ class JSONGraphNodeWriter {
class JSONGraphEdgeWriter { class JSONGraphEdgeWriter {
public: public:
JSONGraphEdgeWriter(std::ostream& os, Zone* zone, const Graph* graph) JSONGraphEdgeWriter(std::ostream& os, Zone* zone, const Graph* graph)
: os_(os), all_(zone, graph), first_edge_(true) {} : os_(os), all_(zone, graph, false), first_edge_(true) {}
void Print() { void Print() {
for (Node* const node : all_.live) PrintEdges(node); for (Node* const node : all_.reachable) PrintEdges(node);
os_ << "\n"; os_ << "\n";
} }
......
...@@ -84,8 +84,8 @@ static void PeelOuterLoopsForOsr(Graph* graph, CommonOperatorBuilder* common, ...@@ -84,8 +84,8 @@ static void PeelOuterLoopsForOsr(Graph* graph, CommonOperatorBuilder* common,
} }
// Copy all nodes. // Copy all nodes.
for (size_t i = 0; i < all.live.size(); i++) { for (size_t i = 0; i < all.reachable.size(); i++) {
Node* orig = all.live[i]; Node* orig = all.reachable[i];
Node* copy = mapping->at(orig->id()); Node* copy = mapping->at(orig->id());
if (copy != sentinel) { if (copy != sentinel) {
// Mapping already exists. // Mapping already exists.
...@@ -113,7 +113,7 @@ static void PeelOuterLoopsForOsr(Graph* graph, CommonOperatorBuilder* common, ...@@ -113,7 +113,7 @@ static void PeelOuterLoopsForOsr(Graph* graph, CommonOperatorBuilder* common,
} }
// Fix missing inputs. // Fix missing inputs.
for (Node* orig : all.live) { for (Node* orig : all.reachable) {
Node* copy = mapping->at(orig->id()); Node* copy = mapping->at(orig->id());
for (int j = 0; j < copy->InputCount(); j++) { for (int j = 0; j < copy->InputCount(); j++) {
if (copy->InputAt(j) == sentinel) { if (copy->InputAt(j) == sentinel) {
......
...@@ -130,7 +130,7 @@ void StoreStoreElimination::Run() { ...@@ -130,7 +130,7 @@ void StoreStoreElimination::Run() {
NodeVector eligible(temp_zone()); // loops over all nodes NodeVector eligible(temp_zone()); // loops over all nodes
AllNodes all(temp_zone(), jsgraph()->graph()); AllNodes all(temp_zone(), jsgraph()->graph());
for (Node* node : all.live) { for (Node* node : all.reachable) {
if (IsEligibleNode(node)) { if (IsEligibleNode(node)) {
eligible.push_back(node); eligible.push_back(node);
} }
......
...@@ -1266,10 +1266,10 @@ void Verifier::Run(Graph* graph, Typing typing, CheckInputs check_inputs) { ...@@ -1266,10 +1266,10 @@ void Verifier::Run(Graph* graph, Typing typing, CheckInputs check_inputs) {
Zone zone(graph->zone()->allocator()); Zone zone(graph->zone()->allocator());
Visitor visitor(&zone, typing, check_inputs); Visitor visitor(&zone, typing, check_inputs);
AllNodes all(&zone, graph); AllNodes all(&zone, graph);
for (Node* node : all.live) visitor.Check(node); for (Node* node : all.reachable) visitor.Check(node);
// Check the uniqueness of projections. // Check the uniqueness of projections.
for (Node* proj : all.live) { for (Node* proj : all.reachable) {
if (proj->opcode() != IrOpcode::kProjection) continue; if (proj->opcode() != IrOpcode::kProjection) continue;
Node* node = proj->InputAt(0); Node* node = proj->InputAt(0);
for (Node* other : node->uses()) { for (Node* other : node->uses()) {
......
...@@ -120,10 +120,10 @@ class OsrDeconstructorTester : public HandleAndZoneScope { ...@@ -120,10 +120,10 @@ class OsrDeconstructorTester : public HandleAndZoneScope {
CHECK(!nodes.IsLive(osr_normal_entry)); CHECK(!nodes.IsLive(osr_normal_entry));
CHECK(!nodes.IsLive(osr_loop_entry)); CHECK(!nodes.IsLive(osr_loop_entry));
// No dangling nodes should be left over. // No dangling nodes should be left over.
for (Node* const node : nodes.live) { for (Node* const node : nodes.reachable) {
for (Node* const use : node->uses()) { for (Node* const use : node->uses()) {
CHECK(std::find(nodes.live.begin(), nodes.live.end(), use) != CHECK(std::find(nodes.reachable.begin(), nodes.reachable.end(), use) !=
nodes.live.end()); nodes.reachable.end());
} }
} }
} }
......
...@@ -125,6 +125,7 @@ class GraphView extends View { ...@@ -125,6 +125,7 @@ class GraphView extends View {
d3.select("#upload").on("click", partial(this.uploadAction, graph)); d3.select("#upload").on("click", partial(this.uploadAction, graph));
d3.select("#layout").on("click", partial(this.layoutAction, graph)); d3.select("#layout").on("click", partial(this.layoutAction, graph));
d3.select("#show-all").on("click", partial(this.showAllAction, graph)); d3.select("#show-all").on("click", partial(this.showAllAction, graph));
d3.select("#hide-dead").on("click", partial(this.hideDeadAction, graph));
d3.select("#hide-unselected").on("click", partial(this.hideUnselectedAction, graph)); d3.select("#hide-unselected").on("click", partial(this.hideUnselectedAction, graph));
d3.select("#hide-selected").on("click", partial(this.hideSelectedAction, graph)); d3.select("#hide-selected").on("click", partial(this.hideSelectedAction, graph));
d3.select("#zoom-selection").on("click", partial(this.zoomSelectionAction, graph)); d3.select("#zoom-selection").on("click", partial(this.zoomSelectionAction, graph));
...@@ -463,6 +464,11 @@ class GraphView extends View { ...@@ -463,6 +464,11 @@ class GraphView extends View {
graph.viewWholeGraph(); graph.viewWholeGraph();
} }
hideDeadAction(graph) {
graph.nodes.filter(function(n) { if (!n.live) n.visible = false; })
graph.updateGraphVisibility();
}
hideUnselectedAction(graph) { hideUnselectedAction(graph) {
var unselected = graph.visibleNodes.filter(function(n) { var unselected = graph.visibleNodes.filter(function(n) {
return !this.classList.contains("selected"); return !this.classList.contains("selected");
...@@ -725,6 +731,8 @@ class GraphView extends View { ...@@ -725,6 +731,8 @@ class GraphView extends View {
.append("g"); .append("g");
newGs.classed("control", function(n) { return n.isControl(); }) newGs.classed("control", function(n) { return n.isControl(); })
.classed("live", function(n) { return n.isLive(); })
.classed("dead", function(n) { return !n.isLive(); })
.classed("javascript", function(n) { return n.isJavaScript(); }) .classed("javascript", function(n) { return n.isJavaScript(); })
.classed("input", function(n) { return n.isInput(); }) .classed("input", function(n) { return n.isInput(); })
.classed("simplified", function(n) { return n.isSimplified(); }) .classed("simplified", function(n) { return n.isSimplified(); })
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
alt="layout graph" class="button-input"> alt="layout graph" class="button-input">
<input id="show-all" type="image" title="show all nodes" src="expand-all.jpg" <input id="show-all" type="image" title="show all nodes" src="expand-all.jpg"
alt="show all nodes" class="button-input"> alt="show all nodes" class="button-input">
<input id="hide-dead" type="image" title="only live nodes" src="live.png"
alt="only live nodes" class="button-input">
<input id="hide-unselected" type="image" title="hide unselected nodes" <input id="hide-unselected" type="image" title="hide unselected nodes"
src="hide-unselected.png" alt="hide unselected nodes" class="button-input"> src="hide-unselected.png" alt="hide unselected nodes" class="button-input">
<input id="hide-selected" type="image" title="hide selected nodes" <input id="hide-selected" type="image" title="hide selected nodes"
......
This diff was suppressed by a .gitattributes entry.
...@@ -21,6 +21,9 @@ var Node = { ...@@ -21,6 +21,9 @@ var Node = {
isInput: function() { isInput: function() {
return this.opcode == 'Parameter' || this.opcode.endsWith('Constant'); return this.opcode == 'Parameter' || this.opcode.endsWith('Constant');
}, },
isLive: function() {
return this.live;
},
isJavaScript: function() { isJavaScript: function() {
return this.opcode.startsWith('JS'); return this.opcode.startsWith('JS');
}, },
......
...@@ -85,6 +85,10 @@ g rect { ...@@ -85,6 +85,10 @@ g rect {
stroke-width: 2px; stroke-width: 2px;
} }
g.dead {
opacity: .5;
}
g.unsorted rect { g.unsorted rect {
opacity: 0.5; opacity: 0.5;
} }
......
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