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