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