X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FProfileData%2FInstrProfReader.cpp;h=5c1993766aacedf4ebb48821057c98e737d9443f;hb=9f92467a5348cecdc5513ba9805add6c67e504c2;hp=8d3ec5d2a3111b51b7a8669b02e72c1e4f7913b5;hpb=5c792faa0e5560bc148c973f3df658eb3bb2061e;p=oota-llvm.git diff --git a/lib/ProfileData/InstrProfReader.cpp b/lib/ProfileData/InstrProfReader.cpp index 8d3ec5d2a31..5c1993766aa 100644 --- a/lib/ProfileData/InstrProfReader.cpp +++ b/lib/ProfileData/InstrProfReader.cpp @@ -20,12 +20,14 @@ #include using namespace llvm; -using std::error_code; -static error_code setupMemoryBuffer(std::string Path, - std::unique_ptr &Buffer) { - if (error_code EC = MemoryBuffer::getFileOrSTDIN(Path, Buffer)) +static std::error_code +setupMemoryBuffer(std::string Path, std::unique_ptr &Buffer) { + ErrorOr> BufferOrErr = + MemoryBuffer::getFileOrSTDIN(Path); + if (std::error_code EC = BufferOrErr.getError()) return EC; + Buffer = std::move(BufferOrErr.get()); // Sanity check the file. if (Buffer->getBufferSize() > std::numeric_limits::max()) @@ -33,15 +35,16 @@ static error_code setupMemoryBuffer(std::string Path, return instrprof_error::success; } -static error_code initializeReader(InstrProfReader &Reader) { +static std::error_code initializeReader(InstrProfReader &Reader) { return Reader.readHeader(); } -error_code InstrProfReader::create(std::string Path, - std::unique_ptr &Result) { +std::error_code +InstrProfReader::create(std::string Path, + std::unique_ptr &Result) { // Set up the buffer to read. std::unique_ptr Buffer; - if (error_code EC = setupMemoryBuffer(Path, Buffer)) + if (std::error_code EC = setupMemoryBuffer(Path, Buffer)) return EC; // Create the reader. @@ -58,11 +61,11 @@ error_code InstrProfReader::create(std::string Path, return initializeReader(*Result); } -error_code IndexedInstrProfReader::create( +std::error_code IndexedInstrProfReader::create( std::string Path, std::unique_ptr &Result) { // Set up the buffer to read. std::unique_ptr Buffer; - if (error_code EC = setupMemoryBuffer(Path, Buffer)) + if (std::error_code EC = setupMemoryBuffer(Path, Buffer)) return EC; // Create the reader. @@ -79,9 +82,9 @@ void InstrProfIterator::Increment() { *this = InstrProfIterator(); } -error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { - // Skip empty lines. - while (!Line.is_at_end() && Line->empty()) +std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { + // Skip empty lines and comments. + while (!Line.is_at_end() && (Line->empty() || Line->startswith("#"))) ++Line; // If we hit EOF while looking for a name, we're done. if (Line.is_at_end()) @@ -158,11 +161,11 @@ bool RawInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { uint64_t Magic = *reinterpret_cast(DataBuffer.getBufferStart()); return getRawMagic() == Magic || - sys::SwapByteOrder(getRawMagic()) == Magic; + sys::getSwappedBytes(getRawMagic()) == Magic; } template -error_code RawInstrProfReader::readHeader() { +std::error_code RawInstrProfReader::readHeader() { if (!hasFormat(*DataBuffer)) return error(instrprof_error::bad_magic); if (DataBuffer->getBufferSize() < sizeof(RawHeader)) @@ -174,7 +177,8 @@ error_code RawInstrProfReader::readHeader() { } template -error_code RawInstrProfReader::readNextHeader(const char *CurrentPos) { +std::error_code +RawInstrProfReader::readNextHeader(const char *CurrentPos) { const char *End = DataBuffer->getBufferEnd(); // Skip zero padding between profiles. while (CurrentPos != End && *CurrentPos == 0) @@ -201,7 +205,8 @@ static uint64_t getRawVersion() { } template -error_code RawInstrProfReader::readHeader(const RawHeader &Header) { +std::error_code +RawInstrProfReader::readHeader(const RawHeader &Header) { if (swap(Header.Version) != getRawVersion()) return error(instrprof_error::unsupported_version); @@ -230,10 +235,10 @@ error_code RawInstrProfReader::readHeader(const RawHeader &Header) { } template -error_code +std::error_code RawInstrProfReader::readNextRecord(InstrProfRecord &Record) { if (Data == DataEnd) - if (error_code EC = readNextHeader(ProfileEnd)) + if (std::error_code EC = readNextHeader(ProfileEnd)) return EC; // Get the raw data. @@ -287,7 +292,7 @@ bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { return Magic == IndexedInstrProf::Magic; } -error_code IndexedInstrProfReader::readHeader() { +std::error_code IndexedInstrProfReader::readHeader() { const unsigned char *Start = (const unsigned char *)DataBuffer->getBufferStart(); const unsigned char *Cur = Start; @@ -302,8 +307,8 @@ error_code IndexedInstrProfReader::readHeader() { return error(instrprof_error::bad_magic); // Read the version. - uint64_t Version = endian::readNext(Cur); - if (Version != IndexedInstrProf::Version) + FormatVersion = endian::readNext(Cur); + if (FormatVersion > IndexedInstrProf::Version) return error(instrprof_error::unsupported_version); // Read the maximal function count. @@ -325,30 +330,64 @@ error_code IndexedInstrProfReader::readHeader() { return success(); } -error_code IndexedInstrProfReader::getFunctionCounts( - StringRef FuncName, uint64_t &FuncHash, std::vector &Counts) { - const auto &Iter = Index->find(FuncName); +std::error_code IndexedInstrProfReader::getFunctionCounts( + StringRef FuncName, uint64_t FuncHash, std::vector &Counts) { + auto Iter = Index->find(FuncName); if (Iter == Index->end()) return error(instrprof_error::unknown_function); - // Found it. Make sure it's valid before giving back a result. - const InstrProfRecord &Record = *Iter; - if (Record.Name.empty()) - return error(instrprof_error::malformed); - FuncHash = Record.Hash; - Counts = Record.Counts; - return success(); + // Found it. Look for counters with the right hash. + ArrayRef Data = (*Iter).Data; + uint64_t NumCounts; + for (uint64_t I = 0, E = Data.size(); I != E; I += NumCounts) { + // The function hash comes first. + uint64_t FoundHash = Data[I++]; + // In v1, we have at least one count. Later, we have the number of counts. + if (I == E) + return error(instrprof_error::malformed); + NumCounts = FormatVersion == 1 ? E - I : Data[I++]; + // If we have more counts than data, this is bogus. + if (I + NumCounts > E) + return error(instrprof_error::malformed); + // Check for a match and fill the vector if there is one. + if (FoundHash == FuncHash) { + Counts = Data.slice(I, NumCounts); + return success(); + } + } + return error(instrprof_error::hash_mismatch); } -error_code IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) { +std::error_code +IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) { // Are we out of records? if (RecordIterator == Index->data_end()) return error(instrprof_error::eof); - // Read the next one. - Record = *RecordIterator; - ++RecordIterator; - if (Record.Name.empty()) + // Record the current function name. + Record.Name = (*RecordIterator).Name; + + ArrayRef Data = (*RecordIterator).Data; + // Valid data starts with a hash and either a count or the number of counts. + if (CurrentOffset + 1 > Data.size()) + return error(instrprof_error::malformed); + // First we have a function hash. + Record.Hash = Data[CurrentOffset++]; + // In version 1 we knew the number of counters implicitly, but in newer + // versions we store the number of counters next. + uint64_t NumCounts = + FormatVersion == 1 ? Data.size() - CurrentOffset : Data[CurrentOffset++]; + if (CurrentOffset + NumCounts > Data.size()) return error(instrprof_error::malformed); + // And finally the counts themselves. + Record.Counts = Data.slice(CurrentOffset, NumCounts); + + // If we've exhausted this function's data, increment the record. + CurrentOffset += NumCounts; + if (CurrentOffset == Data.size()) { + ++RecordIterator; + CurrentOffset = 0; + } + return success(); }