• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
18 #define ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
19 
20 #include <functional>
21 #include <ostream>
22 
23 #include "arch/instruction_set.h"
24 #include "base/arena_containers.h"
25 #include "base/macros.h"
26 #include "base/value_object.h"
27 #include "block_namer.h"
28 
29 namespace art HIDDEN {
30 
31 class CodeGenerator;
32 class DexCompilationUnit;
33 class HGraph;
34 class HInstruction;
35 class SlowPathCode;
36 
37 /**
38  * This class outputs the HGraph in the C1visualizer format.
39  * Note: Currently only works if the compiler is single threaded.
40  */
41 struct GeneratedCodeInterval {
42   size_t start;
43   size_t end;
44 };
45 
46 struct SlowPathCodeInfo {
47   const SlowPathCode* slow_path;
48   GeneratedCodeInterval code_interval;
49 };
50 
51 // This information is filled by the code generator. It will be used by the
52 // graph visualizer to associate disassembly of the generated code with the
53 // instructions and slow paths. We assume that the generated code follows the
54 // following structure:
55 //   - frame entry
56 //   - instructions
57 //   - slow paths
58 class DisassemblyInformation {
59  public:
DisassemblyInformation(ArenaAllocator * allocator)60   explicit DisassemblyInformation(ArenaAllocator* allocator)
61       : frame_entry_interval_({0, 0}),
62         instruction_intervals_(std::less<const HInstruction*>(), allocator->Adapter()),
63         slow_path_intervals_(allocator->Adapter()) {}
64 
SetFrameEntryInterval(size_t start,size_t end)65   void SetFrameEntryInterval(size_t start, size_t end) {
66     frame_entry_interval_ = {start, end};
67   }
68 
AddInstructionInterval(HInstruction * instr,size_t start,size_t end)69   void AddInstructionInterval(HInstruction* instr, size_t start, size_t end) {
70     instruction_intervals_.Put(instr, {start, end});
71   }
72 
AddSlowPathInterval(SlowPathCode * slow_path,size_t start,size_t end)73   void AddSlowPathInterval(SlowPathCode* slow_path, size_t start, size_t end) {
74     slow_path_intervals_.push_back({slow_path, {start, end}});
75   }
76 
GetFrameEntryInterval()77   GeneratedCodeInterval GetFrameEntryInterval() const {
78     return frame_entry_interval_;
79   }
80 
GetFrameEntryInterval()81   GeneratedCodeInterval* GetFrameEntryInterval() {
82     return &frame_entry_interval_;
83   }
84 
GetInstructionIntervals()85   const ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>& GetInstructionIntervals() const {
86     return instruction_intervals_;
87   }
88 
GetInstructionIntervals()89   ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>* GetInstructionIntervals() {
90     return &instruction_intervals_;
91   }
92 
GetSlowPathIntervals()93   const ArenaVector<SlowPathCodeInfo>& GetSlowPathIntervals() const { return slow_path_intervals_; }
94 
GetSlowPathIntervals()95   ArenaVector<SlowPathCodeInfo>* GetSlowPathIntervals() { return &slow_path_intervals_; }
96 
97  private:
98   GeneratedCodeInterval frame_entry_interval_;
99   ArenaSafeMap<const HInstruction*, GeneratedCodeInterval> instruction_intervals_;
100   ArenaVector<SlowPathCodeInfo> slow_path_intervals_;
101 };
102 
103 class HGraphVisualizer : public ValueObject {
104  public:
105   HGraphVisualizer(std::ostream* output,
106                    HGraph* graph,
107                    const CodeGenerator* codegen,
108                    std::optional<std::reference_wrapper<const BlockNamer>> namer = std::nullopt);
109 
110   void PrintHeader(const char* method_name) const;
111   void DumpGraph(const char* pass_name, bool is_after_pass, bool graph_in_bad_state) const;
112   void DumpGraphDebug() const;
113   void DumpGraphWithDisassembly() const;
114 
115   // C1visualizer file format does not support inserting arbitrary metadata into a cfg
116   // file. As a workaround a fake compilation block with the metadata in the name and the
117   // method attributes is used. Such empty blocks don't break the c1visualizer parser.
118   static std::string InsertMetaDataAsCompilationBlock(const std::string& meta_data);
119 
120   static void DumpInstruction(std::ostream* output, HGraph* graph, HInstruction* instruction);
121 
122  private:
123   class OptionalDefaultNamer final : public BlockNamer {
124    public:
OptionalDefaultNamer(std::optional<std::reference_wrapper<const BlockNamer>> inner)125     explicit OptionalDefaultNamer(std::optional<std::reference_wrapper<const BlockNamer>> inner)
126         : namer_(inner) {}
127 
128     std::ostream& PrintName(std::ostream& os, HBasicBlock* blk) const override;
129 
130    private:
131     std::optional<std::reference_wrapper<const BlockNamer>> namer_;
132   };
133 
134   std::ostream* const output_;
135   HGraph* const graph_;
136   const CodeGenerator* codegen_;
137   OptionalDefaultNamer namer_;
138 
139   DISALLOW_COPY_AND_ASSIGN(HGraphVisualizer);
140 };
141 
142 }  // namespace art
143 
144 #endif  // ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
145