diff --git a/llvm/include/llvm/ProfileData/RawMemProfReader.h b/llvm/include/llvm/ProfileData/RawMemProfReader.h --- a/llvm/include/llvm/ProfileData/RawMemProfReader.h +++ b/llvm/include/llvm/ProfileData/RawMemProfReader.h @@ -26,19 +26,96 @@ #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" -#include +#include namespace llvm { namespace memprof { +// A class for memprof profile data populated directly from external +// sources. +// TODO: Rename this file to MemProfReader.h to better reflect the contents. +class MemProfReader { +public: + // The MemProfReader only holds memory profile information. + InstrProfKind getProfileKind() const { return InstrProfKind::MemProf; } + + using GuidMemProfRecordPair = std::pair; + using Iterator = InstrProfIterator; + Iterator end() { return Iterator(); } + Iterator begin() { + Iter = FunctionProfileData.begin(); + return Iterator(this); + } + + // Return a const reference to the internal Id to Frame mappings. + const llvm::DenseMap &getFrameMapping() const { + return IdToFrame; + } + + // Return a const reference to the internal function profile data. + const llvm::MapVector & + getProfileData() const { + return FunctionProfileData; + } + + virtual Error + readNextRecord(GuidMemProfRecordPair &GuidRecord, + std::function Callback = nullptr) { + if (FunctionProfileData.empty()) + return make_error(instrprof_error::empty_raw_profile); + + if (Iter == FunctionProfileData.end()) + return make_error(instrprof_error::eof); + + if (Callback == nullptr) { + Callback = + std::bind(&MemProfReader::idToFrame, this, std::placeholders::_1); + } + + const IndexedMemProfRecord &IndexedRecord = Iter->second; + GuidRecord = {Iter->first, MemProfRecord(IndexedRecord, Callback)}; + Iter++; + return Error::success(); + } + + // Allow default construction for derived classes which can populate the + // contents after construction. + MemProfReader() = default; + virtual ~MemProfReader() = default; + + // Initialize the MemProfReader with the frame mappings and profile contents. + MemProfReader( + llvm::DenseMap FrameIdMap, + llvm::MapVector ProfData) + : IdToFrame(std::move(FrameIdMap)), + FunctionProfileData(std::move(ProfData)) {} + +protected: + // A helper method to extract the frame from the IdToFrame map. + const Frame &idToFrame(const FrameId Id) const { + auto It = IdToFrame.find(Id); + assert(It != IdToFrame.end() && "Id not found in map."); + return It->getSecond(); + } + // A mapping from FrameId (a hash of the contents) to the frame. + llvm::DenseMap IdToFrame; + // A mapping from function GUID, hash of the canonical function symbol to the + // memprof profile data for that function, i.e allocation and callsite info. + llvm::MapVector FunctionProfileData; + // An iterator to the internal function profile data structure. + llvm::MapVector::iterator Iter; +}; // Map from id (recorded from sanitizer stack depot) to virtual addresses for // each program counter address in the callstack. using CallStackMap = llvm::DenseMap>; -class RawMemProfReader { +// Specializes the MemProfReader class to populate the contents from raw binary +// memprof profiles from instrumentation based profiling. +class RawMemProfReader final : public MemProfReader { public: RawMemProfReader(const RawMemProfReader &) = delete; RawMemProfReader &operator=(const RawMemProfReader &) = delete; + virtual ~RawMemProfReader() override = default; // Prints the contents of the profile in YAML format. void printYAML(raw_ostream &OS); @@ -62,18 +139,9 @@ // Returns a list of build ids recorded in the segment information. static std::vector peekBuildIds(MemoryBuffer *DataBuffer); - using GuidMemProfRecordPair = std::pair; - using Iterator = InstrProfIterator; - Iterator end() { return Iterator(); } - Iterator begin() { - Iter = FunctionProfileData.begin(); - return Iterator(this); - } - - Error readNextRecord(GuidMemProfRecordPair &GuidRecord); - - // The RawMemProfReader only holds memory profile information. - InstrProfKind getProfileKind() const { return InstrProfKind::MemProf; } + virtual Error + readNextRecord(GuidMemProfRecordPair &GuidRecord, + std::function Callback) override; // Constructor for unittests only. RawMemProfReader(std::unique_ptr Sym, @@ -93,17 +161,6 @@ report_fatal_error(std::move(E)); } - // Return a const reference to the internal Id to Frame mappings. - const llvm::DenseMap &getFrameMapping() const { - return IdToFrame; - } - - // Return a const reference to the internal function profile data. - const llvm::MapVector & - getProfileData() const { - return FunctionProfileData; - } - private: RawMemProfReader(object::OwningBinary &&Bin, bool KeepName) : Binary(std::move(Bin)), KeepSymbolName(KeepName) {} @@ -123,13 +180,6 @@ // callsite data or both. Error mapRawProfileToRecords(); - // A helper method to extract the frame from the IdToFrame map. - const Frame &idToFrame(const FrameId Id) const { - auto It = IdToFrame.find(Id); - assert(It != IdToFrame.end() && "Id not found in map."); - return It->getSecond(); - } - object::SectionedAddress getModuleOffset(uint64_t VirtualAddress); // The profiled binary. @@ -154,10 +204,6 @@ // Cached symbolization from PC to Frame. llvm::DenseMap> SymbolizedFrame; - llvm::DenseMap IdToFrame; - - llvm::MapVector FunctionProfileData; - llvm::MapVector::iterator Iter; // Whether to keep the symbol name for each frame after hashing. bool KeepSymbolName = false; diff --git a/llvm/lib/ProfileData/RawMemProfReader.cpp b/llvm/lib/ProfileData/RawMemProfReader.cpp --- a/llvm/lib/ProfileData/RawMemProfReader.cpp +++ b/llvm/lib/ProfileData/RawMemProfReader.cpp @@ -645,13 +645,12 @@ return object::SectionedAddress{VirtualAddress}; } -Error RawMemProfReader::readNextRecord(GuidMemProfRecordPair &GuidRecord) { - if (FunctionProfileData.empty()) - return make_error(instrprof_error::empty_raw_profile); - - if (Iter == FunctionProfileData.end()) - return make_error(instrprof_error::eof); - +Error RawMemProfReader::readNextRecord( + GuidMemProfRecordPair &GuidRecord, + std::function Callback) { + // Create a new callback for the RawMemProfRecord iterator so that we can + // provide the symbol name if the reader was initialized with KeepSymbolName = + // true. This is useful for debugging and testing. auto IdToFrameCallback = [this](const FrameId Id) { Frame F = this->idToFrame(Id); if (!this->KeepSymbolName) @@ -661,11 +660,7 @@ F.SymbolName = Iter->getSecond(); return F; }; - - const IndexedMemProfRecord &IndexedRecord = Iter->second; - GuidRecord = {Iter->first, MemProfRecord(IndexedRecord, IdToFrameCallback)}; - Iter++; - return Error::success(); + return MemProfReader::readNextRecord(GuidRecord, IdToFrameCallback); } } // namespace memprof } // namespace llvm