[codeview,pdb] Try really hard to conserve memory when reading.
PDBs can be extremely large. We're already mapping the entire
PDB into the process's address space, but to make matters worse
the blocks of the PDB are not arranged contiguously. So, when
we have something like an array or a string embedded into the
stream, we have to make a copy. Since it's convenient to use
traditional data structures to iterate and manipulate these
records, we need the memory to be contiguous.
As a result of this, we were using roughly twice as much memory
as the file size of the PDB, because every stream was copied
out and re-stitched together contiguously.
This patch addresses this by improving the MappedBlockStream
to allocate from a BumpPtrAllocator only when a read requires
a discontiguous read. Furthermore, it introduces some data
structures backed by a stream which can iterate over both
fixed and variable length records of a PDB. Since everything
is backed by a stream and not a buffer, we can read almost
everything from the PDB with zero copies.
Differential Revision: http://reviews.llvm.org/D20654
Reviewed By: ruiu
llvm-svn: 270951
diff --git a/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp b/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
index 362c402..9ccb7ed 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
@@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
+
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/Support/Endian.h"
@@ -16,6 +18,7 @@
using namespace llvm::support;
namespace {
+
struct SCBytes {
ulittle16_t Section;
char Padding1[2];
@@ -60,17 +63,29 @@
// for now since it is unused.
ulittle32_t SrcFileNameNI; // Name Index for src file name
ulittle32_t PdbFilePathNI; // Name Index for path to compiler PDB
- char VarInfo[1]; // Module name followed by Obj File Name
-
- StringRef getModuleName() const { return StringRef(VarInfo); }
-
- StringRef getObjectFileName() const {
- return StringRef(getModuleName().end() + 1);
- }
+ // Null terminated Module name
+ // Null terminated Obj File Name
};
-ModInfo::ModInfo(const uint8_t *Bytes)
- : Layout(reinterpret_cast<const FileLayout *>(Bytes)) {}
+ModInfo::ModInfo(codeview::StreamRef Stream) : Layout(nullptr) {
+ codeview::StreamReader Reader(Stream);
+ if (auto EC = Reader.readObject(Layout)) {
+ consumeError(std::move(EC));
+ return;
+ }
+ if (auto EC = Reader.readZeroString(ModuleName)) {
+ consumeError(std::move(EC));
+ return;
+ }
+ if (auto EC = Reader.readZeroString(ObjFileName)) {
+ consumeError(std::move(EC));
+ return;
+ }
+}
+
+ModInfo::ModInfo(const ModInfo &Info)
+ : ModuleName(Info.ModuleName), ObjFileName(Info.ObjFileName),
+ Layout(Info.Layout) {}
ModInfo::~ModInfo() {}
@@ -100,44 +115,14 @@
return Layout->PdbFilePathNI;
}
-llvm::StringRef ModInfo::getModuleName() const {
- return Layout->getModuleName();
-}
+StringRef ModInfo::getModuleName() const { return ModuleName; }
-llvm::StringRef ModInfo::getObjFileName() const {
- return Layout->getObjectFileName();
-}
+StringRef ModInfo::getObjFileName() const { return ObjFileName; }
-ModInfoIterator::ModInfoIterator(const uint8_t *Stream) : Bytes(Stream) {}
-
-ModInfoIterator::ModInfoIterator(const ModInfoIterator &Other)
- : Bytes(Other.Bytes) {}
-
-ModInfo ModInfoIterator::operator*() { return ModInfo(Bytes); }
-
-ModInfoIterator &ModInfoIterator::operator++() {
- StringRef Obj = ModInfo(Bytes).getObjFileName();
- Bytes = Obj.bytes_end() + 1;
- Bytes = reinterpret_cast<const uint8_t *>(llvm::alignAddr(Bytes, 4));
-
- return *this;
-}
-
-ModInfoIterator ModInfoIterator::operator++(int) {
- ModInfoIterator Copy(*this);
- ++(*this);
- return Copy;
-}
-
-bool ModInfoIterator::operator==(const ModInfoIterator &Other) {
- return Bytes == Other.Bytes;
-}
-
-bool ModInfoIterator::operator!=(const ModInfoIterator &Other) {
- return !(*this == Other);
-}
-
-ModInfoIterator &ModInfoIterator::operator=(const ModInfoIterator &Other) {
- Bytes = Other.Bytes;
- return *this;
+uint32_t ModInfo::getRecordLength() const {
+ uint32_t M = ModuleName.str().size() + 1;
+ uint32_t O = ObjFileName.str().size() + 1;
+ uint32_t Size = sizeof(FileLayout) + M + O;
+ Size = llvm::alignTo(Size, 4);
+ return Size;
}