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