diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/ProfileData/SampleProfReader.cpp | |
parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) |
Notes
Diffstat (limited to 'lib/ProfileData/SampleProfReader.cpp')
-rw-r--r-- | lib/ProfileData/SampleProfReader.cpp | 167 |
1 files changed, 154 insertions, 13 deletions
diff --git a/lib/ProfileData/SampleProfReader.cpp b/lib/ProfileData/SampleProfReader.cpp index 79335e67cd98..a68d1e9d3ab0 100644 --- a/lib/ProfileData/SampleProfReader.cpp +++ b/lib/ProfileData/SampleProfReader.cpp @@ -30,6 +30,7 @@ #include "llvm/Support/ErrorOr.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/LineIterator.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -320,6 +321,21 @@ ErrorOr<StringRef> SampleProfileReaderBinary::readString() { } template <typename T> +ErrorOr<T> SampleProfileReaderBinary::readUnencodedNumber() { + std::error_code EC; + + if (Data + sizeof(T) > End) { + EC = sampleprof_error::truncated; + reportError(0, EC.message()); + return EC; + } + + using namespace support; + T Val = endian::readNext<T, little, unaligned>(Data); + return Val; +} + +template <typename T> inline ErrorOr<uint32_t> SampleProfileReaderBinary::readStringIndex(T &Table) { std::error_code EC; auto Idx = readNumber<uint32_t>(); @@ -423,29 +439,51 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { return sampleprof_error::success; } -std::error_code SampleProfileReaderBinary::read() { - while (!at_eof()) { - auto NumHeadSamples = readNumber<uint64_t>(); - if (std::error_code EC = NumHeadSamples.getError()) - return EC; +std::error_code SampleProfileReaderBinary::readFuncProfile() { + auto NumHeadSamples = readNumber<uint64_t>(); + if (std::error_code EC = NumHeadSamples.getError()) + return EC; - auto FName(readStringFromTable()); - if (std::error_code EC = FName.getError()) - return EC; + auto FName(readStringFromTable()); + if (std::error_code EC = FName.getError()) + return EC; - Profiles[*FName] = FunctionSamples(); - FunctionSamples &FProfile = Profiles[*FName]; - FProfile.setName(*FName); + Profiles[*FName] = FunctionSamples(); + FunctionSamples &FProfile = Profiles[*FName]; + FProfile.setName(*FName); - FProfile.addHeadSamples(*NumHeadSamples); + FProfile.addHeadSamples(*NumHeadSamples); + + if (std::error_code EC = readProfile(FProfile)) + return EC; + return sampleprof_error::success; +} - if (std::error_code EC = readProfile(FProfile)) +std::error_code SampleProfileReaderBinary::read() { + while (!at_eof()) { + if (std::error_code EC = readFuncProfile()) return EC; } return sampleprof_error::success; } +std::error_code SampleProfileReaderCompactBinary::read() { + for (auto Name : FuncsToUse) { + auto GUID = std::to_string(MD5Hash(Name)); + auto iter = FuncOffsetTable.find(StringRef(GUID)); + if (iter == FuncOffsetTable.end()) + continue; + const uint8_t *SavedData = Data; + Data = reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()) + + iter->second; + if (std::error_code EC = readFuncProfile()) + return EC; + Data = SavedData; + } + return sampleprof_error::success; +} + std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t Magic) { if (Magic == SPMagic()) return sampleprof_error::success; @@ -514,6 +552,53 @@ std::error_code SampleProfileReaderBinary::readHeader() { return sampleprof_error::success; } +std::error_code SampleProfileReaderCompactBinary::readHeader() { + SampleProfileReaderBinary::readHeader(); + if (std::error_code EC = readFuncOffsetTable()) + return EC; + return sampleprof_error::success; +} + +std::error_code SampleProfileReaderCompactBinary::readFuncOffsetTable() { + auto TableOffset = readUnencodedNumber<uint64_t>(); + if (std::error_code EC = TableOffset.getError()) + return EC; + + const uint8_t *SavedData = Data; + const uint8_t *TableStart = + reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()) + + *TableOffset; + Data = TableStart; + + auto Size = readNumber<uint64_t>(); + if (std::error_code EC = Size.getError()) + return EC; + + FuncOffsetTable.reserve(*Size); + for (uint32_t I = 0; I < *Size; ++I) { + auto FName(readStringFromTable()); + if (std::error_code EC = FName.getError()) + return EC; + + auto Offset = readNumber<uint64_t>(); + if (std::error_code EC = Offset.getError()) + return EC; + + FuncOffsetTable[*FName] = *Offset; + } + End = TableStart; + Data = SavedData; + return sampleprof_error::success; +} + +void SampleProfileReaderCompactBinary::collectFuncsToUse(const Module &M) { + FuncsToUse.clear(); + for (auto &F : M) { + StringRef Fname = F.getName().split('.').first; + FuncsToUse.insert(Fname); + } +} + std::error_code SampleProfileReaderBinary::readSummaryEntry( std::vector<ProfileSummaryEntry> &Entries) { auto Cutoff = readNumber<uint64_t>(); @@ -827,6 +912,40 @@ bool SampleProfileReaderGCC::hasFormat(const MemoryBuffer &Buffer) { return Magic == "adcg*704"; } +std::error_code SampleProfileReaderItaniumRemapper::read() { + // If the underlying data is in compact format, we can't remap it because + // we don't know what the original function names were. + if (getFormat() == SPF_Compact_Binary) { + Ctx.diagnose(DiagnosticInfoSampleProfile( + Buffer->getBufferIdentifier(), + "Profile data remapping cannot be applied to profile data " + "in compact format (original mangled names are not available).", + DS_Warning)); + return sampleprof_error::success; + } + + if (Error E = Remappings.read(*Buffer)) { + handleAllErrors( + std::move(E), [&](const SymbolRemappingParseError &ParseError) { + reportError(ParseError.getLineNum(), ParseError.getMessage()); + }); + return sampleprof_error::malformed; + } + + for (auto &Sample : getProfiles()) + if (auto Key = Remappings.insert(Sample.first())) + SampleMap.insert({Key, &Sample.second}); + + return sampleprof_error::success; +} + +FunctionSamples * +SampleProfileReaderItaniumRemapper::getSamplesFor(StringRef Fname) { + if (auto Key = Remappings.lookup(Fname)) + return SampleMap.lookup(Key); + return SampleProfileReader::getSamplesFor(Fname); +} + /// Prepare a memory buffer for the contents of \p Filename. /// /// \returns an error code indicating the status of the buffer. @@ -859,6 +978,27 @@ SampleProfileReader::create(const Twine &Filename, LLVMContext &C) { return create(BufferOrError.get(), C); } +/// Create a sample profile remapper from the given input, to remap the +/// function names in the given profile data. +/// +/// \param Filename The file to open. +/// +/// \param C The LLVM context to use to emit diagnostics. +/// +/// \param Underlying The underlying profile data reader to remap. +/// +/// \returns an error code indicating the status of the created reader. +ErrorOr<std::unique_ptr<SampleProfileReader>> +SampleProfileReaderItaniumRemapper::create( + const Twine &Filename, LLVMContext &C, + std::unique_ptr<SampleProfileReader> Underlying) { + auto BufferOrError = setupMemoryBuffer(Filename); + if (std::error_code EC = BufferOrError.getError()) + return EC; + return llvm::make_unique<SampleProfileReaderItaniumRemapper>( + std::move(BufferOrError.get()), C, std::move(Underlying)); +} + /// Create a sample profile reader based on the format of the input data. /// /// \param B The memory buffer to create the reader from (assumes ownership). @@ -880,6 +1020,7 @@ SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C) { else return sampleprof_error::unrecognized_format; + FunctionSamples::Format = Reader->getFormat(); if (std::error_code EC = Reader->readHeader()) return EC; |