graph_visualizer.cc revision 0d3f578909d0d1ea072ca68d78301b6fb7a44451
1f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray/*
2f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray *
4f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * you may not use this file except in compliance with the License.
6f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * You may obtain a copy of the License at
7f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray *
8f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray *
10f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * See the License for the specific language governing permissions and
14f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * limitations under the License.
15f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray */
16f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
17f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray#include "graph_visualizer.h"
18f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
19f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray#include "driver/dex_compilation_unit.h"
20f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray#include "nodes.h"
21f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
22f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffraynamespace art {
23f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
24f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray/**
25f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * HGraph visitor to generate a file suitable for the c1visualizer tool and IRHydra.
26f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray */
27f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffrayclass HGraphVisualizerPrinter : public HGraphVisitor {
28f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray public:
29f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  HGraphVisualizerPrinter(HGraph* graph, std::ostream& output)
30f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      : HGraphVisitor(graph), output_(output), indent_(0) {}
31f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
32f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void StartTag(const char* name) {
33f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
34f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << "begin_" << name << std::endl;
35f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    indent_++;
36f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
37f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
38f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void EndTag(const char* name) {
39f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    indent_--;
40f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
41f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << "end_" << name << std::endl;
42f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
43f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
44f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintProperty(const char* name, const char* property) {
45f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
46f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << " \"" << property << "\"" << std::endl;
47f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
48f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
49f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintProperty(const char* name, const char* property, int id) {
50f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
51f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << " \"" << property << id << "\"" << std::endl;
52f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
53f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
54f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintEmptyProperty(const char* name) {
55f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
56f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << std::endl;
57f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
58f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
59f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintTime(const char* name) {
60f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
61f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << " " << time(NULL) << std::endl;
62f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
63f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
64f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintInt(const char* name, int value) {
65f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
66f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << " " << value << std::endl;
67f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
68f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
69f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void AddIndent() {
70f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (size_t i = 0; i < indent_; ++i) {
71f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << "  ";
72f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
73f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
74f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
75f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintPredecessors(HBasicBlock* block) {
76f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
77f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << "predecessors";
78f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
79f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      HBasicBlock* predecessor = block->GetPredecessors().Get(i);
80f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << " \"B" << predecessor->GetBlockId() << "\" ";
81f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
82f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_<< std::endl;
83f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
84f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
85f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintSuccessors(HBasicBlock* block) {
86f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
87f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << "successors";
88f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (size_t i = 0, e = block->GetSuccessors().Size(); i < e; ++i) {
89f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      HBasicBlock* successor = block->GetSuccessors().Get(i);
90f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << " \"B" << successor->GetBlockId() << "\" ";
91f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
92f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_<< std::endl;
93f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
94f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
95f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
96f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void VisitInstruction(HInstruction* instruction) {
97f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << instruction->DebugName();
98f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    if (instruction->InputCount() > 0) {
99f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << " [ ";
100f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) {
101f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray        output_ << "v" << inputs.Current()->GetId() << " ";
102f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      }
103f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << "]";
104f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
105f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
106f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
107f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintInstructions(const HInstructionList& list) {
108f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    const char* kEndInstructionMarker = "<|@";
109f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (HInstructionIterator it(list); !it.Done(); it.Advance()) {
110f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      HInstruction* instruction = it.Current();
111f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      AddIndent();
112f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      int bci = 0;
113f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << bci << " " << instruction->NumberOfUses() << " v" << instruction->GetId() << " ";
114f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      instruction->Accept(this);
115f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << kEndInstructionMarker << std::endl;
116f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
117f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
118f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
119f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void Run(const char* pass_name) {
120f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("cfg");
121f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintProperty("name", pass_name);
122f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    VisitInsertionOrder();
123f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("cfg");
124f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
125f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
126f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void VisitBasicBlock(HBasicBlock* block) {
127f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("block");
128f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintProperty("name", "B", block->GetBlockId());
129f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintInt("from_bci", -1);
130f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintInt("to_bci", -1);
131f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintPredecessors(block);
132f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintSuccessors(block);
133f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintEmptyProperty("xhandlers");
134f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintEmptyProperty("flags");
135f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    if (block->GetDominator() != nullptr) {
136f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      PrintProperty("dominator", "B", block->GetDominator()->GetBlockId());
137f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
138f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
139f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("states");
140f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("locals");
141f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintInt("size", 0);
142f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintProperty("method", "None");
143f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
144f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      AddIndent();
145f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      HInstruction* instruction = it.Current();
146f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << instruction->GetId() << " v" << instruction->GetId() << "[ ";
147f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) {
148f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray        output_ << inputs.Current()->GetId() << " ";
149f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      }
150f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << "]" << std::endl;
151f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
152f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("locals");
153f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("states");
154f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
155f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("HIR");
156f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintInstructions(block->GetPhis());
157f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintInstructions(block->GetInstructions());
158f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("HIR");
159f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("block");
160f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
161f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
162f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray private:
163f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  std::ostream& output_;
164f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  size_t indent_;
165f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
166f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(HGraphVisualizerPrinter);
167f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray};
168f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
169f635e63318447ca04731b265a86a573c9ed1737cNicolas GeoffrayHGraphVisualizer::HGraphVisualizer(std::ostream* output,
170f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray                                   HGraph* graph,
171f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray                                   const char* string_filter,
172f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray                                   const DexCompilationUnit& cu)
173f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    : output_(output), graph_(graph), is_enabled_(false) {
174f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  if (output == nullptr) {
175f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    return;
176f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
177f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  std::string pretty_name = PrettyMethod(cu.GetDexMethodIndex(), *cu.GetDexFile());
178f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  if (pretty_name.find(string_filter) == std::string::npos) {
179f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    return;
180f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
181f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
182f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  is_enabled_ = true;
183f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  HGraphVisualizerPrinter printer(graph, *output_);
184f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.StartTag("compilation");
185f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.PrintProperty("name", pretty_name.c_str());
186f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.PrintProperty("method", pretty_name.c_str());
187f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.PrintTime("date");
188f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.EndTag("compilation");
189f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray}
190f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
1910d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas GeoffrayHGraphVisualizer::HGraphVisualizer(std::ostream* output,
1920d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray                                   HGraph* graph,
1930d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray                                   const char* name)
1940d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray    : output_(output), graph_(graph), is_enabled_(false) {
1950d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  if (output == nullptr) {
1960d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray    return;
1970d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  }
1980d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray
1990d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  is_enabled_ = true;
2000d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  HGraphVisualizerPrinter printer(graph, *output_);
2010d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.StartTag("compilation");
2020d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.PrintProperty("name", name);
2030d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.PrintProperty("method", name);
2040d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.PrintTime("date");
2050d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.EndTag("compilation");
2060d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray}
2070d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray
208f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffrayvoid HGraphVisualizer::DumpGraph(const char* pass_name) {
209f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  if (!is_enabled_) {
210f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    return;
211f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
212f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  HGraphVisualizerPrinter printer(graph_, *output_);
213f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.Run(pass_name);
214f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray}
215f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
216f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray}  // namespace art
217