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 <ostream>
21 
22 #include "arch/instruction_set.h"
23 #include "base/arena_containers.h"
24 #include "base/value_object.h"
25 
26 namespace art {
27 
28 class CodeGenerator;
29 class DexCompilationUnit;
30 class HGraph;
31 class HInstruction;
32 class SlowPathCode;
33 
34 /**
35  * This class outputs the HGraph in the C1visualizer format.
36  * Note: Currently only works if the compiler is single threaded.
37  */
38 struct GeneratedCodeInterval {
39   size_t start;
40   size_t end;
41 };
42 
43 struct SlowPathCodeInfo {
44   const SlowPathCode* slow_path;
45   GeneratedCodeInterval code_interval;
46 };
47 
48 // This information is filled by the code generator. It will be used by the
49 // graph visualizer to associate disassembly of the generated code with the
50 // instructions and slow paths. We assume that the generated code follows the
51 // following structure:
52 //   - frame entry
53 //   - instructions
54 //   - slow paths
55 class DisassemblyInformation {
56  public:
DisassemblyInformation(ArenaAllocator * allocator)57   explicit DisassemblyInformation(ArenaAllocator* allocator)
58       : frame_entry_interval_({0, 0}),
59         instruction_intervals_(std::less<const HInstruction*>(), allocator->Adapter()),
60         slow_path_intervals_(allocator->Adapter()) {}
61 
SetFrameEntryInterval(size_t start,size_t end)62   void SetFrameEntryInterval(size_t start, size_t end) {
63     frame_entry_interval_ = {start, end};
64   }
65 
AddInstructionInterval(HInstruction * instr,size_t start,size_t end)66   void AddInstructionInterval(HInstruction* instr, size_t start, size_t end) {
67     instruction_intervals_.Put(instr, {start, end});
68   }
69 
AddSlowPathInterval(SlowPathCode * slow_path,size_t start,size_t end)70   void AddSlowPathInterval(SlowPathCode* slow_path, size_t start, size_t end) {
71     slow_path_intervals_.push_back({slow_path, {start, end}});
72   }
73 
GetFrameEntryInterval()74   GeneratedCodeInterval GetFrameEntryInterval() const {
75     return frame_entry_interval_;
76   }
77 
GetFrameEntryInterval()78   GeneratedCodeInterval* GetFrameEntryInterval() {
79     return &frame_entry_interval_;
80   }
81 
GetInstructionIntervals()82   const ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>& GetInstructionIntervals() const {
83     return instruction_intervals_;
84   }
85 
GetInstructionIntervals()86   ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>* GetInstructionIntervals() {
87     return &instruction_intervals_;
88   }
89 
GetSlowPathIntervals()90   const ArenaVector<SlowPathCodeInfo>& GetSlowPathIntervals() const { return slow_path_intervals_; }
91 
GetSlowPathIntervals()92   ArenaVector<SlowPathCodeInfo>* GetSlowPathIntervals() { return &slow_path_intervals_; }
93 
94  private:
95   GeneratedCodeInterval frame_entry_interval_;
96   ArenaSafeMap<const HInstruction*, GeneratedCodeInterval> instruction_intervals_;
97   ArenaVector<SlowPathCodeInfo> slow_path_intervals_;
98 };
99 
100 class HGraphVisualizer : public ValueObject {
101  public:
102   HGraphVisualizer(std::ostream* output,
103                    HGraph* graph,
104                    const CodeGenerator& codegen);
105 
106   void PrintHeader(const char* method_name) const;
107   void DumpGraph(const char* pass_name, bool is_after_pass, bool graph_in_bad_state) const;
108   void DumpGraphWithDisassembly() const;
109 
110   // C1visualizer file format does not support inserting arbitrary metadata into a cfg
111   // file. As a workaround a fake compilation block with the metadata in the name and the
112   // method attributes is used. Such empty blocks don't break the c1visualizer parser.
113   static std::string InsertMetaDataAsCompilationBlock(const std::string& meta_data);
114 
115  private:
116   std::ostream* const output_;
117   HGraph* const graph_;
118   const CodeGenerator& codegen_;
119 
120   DISALLOW_COPY_AND_ASSIGN(HGraphVisualizer);
121 };
122 
123 }  // namespace art
124 
125 #endif  // ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
126