forked from OSchip/llvm-project
[PDB] Remove unique_ptr wrapper around C13 line table subsections
This accounts for a large portion of the memory allocations in LLD. This DebugSubsectionRecordBuilder object can be stored directly in C13Builders, it mostly wraps other subsections. Remove the container kind field from the object. It is always the same for all elements in the vector, and we can pass it in during writing.
This commit is contained in:
parent
bd7ea8641e
commit
7af4bb1641
|
@ -35,44 +35,38 @@ struct DebugSubsectionHeader {
|
||||||
class DebugSubsectionRecord {
|
class DebugSubsectionRecord {
|
||||||
public:
|
public:
|
||||||
DebugSubsectionRecord();
|
DebugSubsectionRecord();
|
||||||
DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data,
|
DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data);
|
||||||
CodeViewContainer Container);
|
|
||||||
|
|
||||||
static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info,
|
static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info);
|
||||||
CodeViewContainer Container);
|
|
||||||
|
|
||||||
uint32_t getRecordLength() const;
|
uint32_t getRecordLength() const;
|
||||||
DebugSubsectionKind kind() const;
|
DebugSubsectionKind kind() const;
|
||||||
BinaryStreamRef getRecordData() const;
|
BinaryStreamRef getRecordData() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CodeViewContainer Container = CodeViewContainer::ObjectFile;
|
|
||||||
DebugSubsectionKind Kind = DebugSubsectionKind::None;
|
DebugSubsectionKind Kind = DebugSubsectionKind::None;
|
||||||
BinaryStreamRef Data;
|
BinaryStreamRef Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DebugSubsectionRecordBuilder {
|
class DebugSubsectionRecordBuilder {
|
||||||
public:
|
public:
|
||||||
DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection,
|
DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection);
|
||||||
CodeViewContainer Container);
|
|
||||||
|
|
||||||
/// Use this to copy existing subsections directly from source to destination.
|
/// Use this to copy existing subsections directly from source to destination.
|
||||||
/// For example, line table subsections in an object file only need to be
|
/// For example, line table subsections in an object file only need to be
|
||||||
/// relocated before being copied into the PDB.
|
/// relocated before being copied into the PDB.
|
||||||
DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents,
|
DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents);
|
||||||
CodeViewContainer Container);
|
|
||||||
|
|
||||||
uint32_t calculateSerializedLength();
|
uint32_t calculateSerializedLength() const;
|
||||||
Error commit(BinaryStreamWriter &Writer) const;
|
Error commit(BinaryStreamWriter &Writer, CodeViewContainer Container) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The subsection to build. Will be null if Contents is non-empty.
|
/// The subsection to build. Will be null if Contents is non-empty.
|
||||||
std::shared_ptr<DebugSubsection> Subsection;
|
std::shared_ptr<DebugSubsection> Subsection;
|
||||||
|
|
||||||
/// The bytes of the subsection. Only non-empty if Subsection is null.
|
/// The bytes of the subsection. Only non-empty if Subsection is null.
|
||||||
|
/// FIXME: Reduce the size of this.
|
||||||
DebugSubsectionRecord Contents;
|
DebugSubsectionRecord Contents;
|
||||||
|
|
||||||
CodeViewContainer Container;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace codeview
|
} // end namespace codeview
|
||||||
|
@ -83,8 +77,7 @@ template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> {
|
||||||
// FIXME: We need to pass the container type through to this function. In
|
// FIXME: We need to pass the container type through to this function. In
|
||||||
// practice this isn't super important since the subsection header describes
|
// practice this isn't super important since the subsection header describes
|
||||||
// its length and we can just skip it. It's more important when writing.
|
// its length and we can just skip it. It's more important when writing.
|
||||||
if (auto EC = codeview::DebugSubsectionRecord::initialize(
|
if (auto EC = codeview::DebugSubsectionRecord::initialize(Stream, Info))
|
||||||
Stream, Info, codeview::CodeViewContainer::Pdb))
|
|
||||||
return EC;
|
return EC;
|
||||||
Length = alignTo(Info.getRecordLength(), 4);
|
Length = alignTo(Info.getRecordLength(), 4);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
|
|
|
@ -93,8 +93,7 @@ private:
|
||||||
std::vector<std::string> SourceFiles;
|
std::vector<std::string> SourceFiles;
|
||||||
std::vector<ArrayRef<uint8_t>> Symbols;
|
std::vector<ArrayRef<uint8_t>> Symbols;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<codeview::DebugSubsectionRecordBuilder>>
|
std::vector<codeview::DebugSubsectionRecordBuilder> C13Builders;
|
||||||
C13Builders;
|
|
||||||
|
|
||||||
ModuleInfoHeader Layout;
|
ModuleInfoHeader Layout;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,13 +23,11 @@ using namespace llvm::codeview;
|
||||||
DebugSubsectionRecord::DebugSubsectionRecord() = default;
|
DebugSubsectionRecord::DebugSubsectionRecord() = default;
|
||||||
|
|
||||||
DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
|
DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
|
||||||
BinaryStreamRef Data,
|
BinaryStreamRef Data)
|
||||||
CodeViewContainer Container)
|
: Kind(Kind), Data(Data) {}
|
||||||
: Container(Container), Kind(Kind), Data(Data) {}
|
|
||||||
|
|
||||||
Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
|
Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
|
||||||
DebugSubsectionRecord &Info,
|
DebugSubsectionRecord &Info) {
|
||||||
CodeViewContainer Container) {
|
|
||||||
const DebugSubsectionHeader *Header;
|
const DebugSubsectionHeader *Header;
|
||||||
BinaryStreamReader Reader(Stream);
|
BinaryStreamReader Reader(Stream);
|
||||||
if (auto EC = Reader.readObject(Header))
|
if (auto EC = Reader.readObject(Header))
|
||||||
|
@ -39,7 +37,6 @@ Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
|
||||||
static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
|
static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
|
||||||
if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
|
if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
|
||||||
return EC;
|
return EC;
|
||||||
Info.Container = Container;
|
|
||||||
Info.Kind = Kind;
|
Info.Kind = Kind;
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
@ -53,14 +50,14 @@ DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
|
||||||
BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
|
BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
|
||||||
|
|
||||||
DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
|
DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
|
||||||
std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
|
std::shared_ptr<DebugSubsection> Subsection)
|
||||||
: Subsection(std::move(Subsection)), Container(Container) {}
|
: Subsection(std::move(Subsection)) {}
|
||||||
|
|
||||||
DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
|
DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
|
||||||
const DebugSubsectionRecord &Contents, CodeViewContainer Container)
|
const DebugSubsectionRecord &Contents)
|
||||||
: Contents(Contents), Container(Container) {}
|
: Contents(Contents) {}
|
||||||
|
|
||||||
uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
|
uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() const {
|
||||||
uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
|
uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
|
||||||
: Contents.getRecordData().getLength();
|
: Contents.getRecordData().getLength();
|
||||||
// The length of the entire subsection is always padded to 4 bytes,
|
// The length of the entire subsection is always padded to 4 bytes,
|
||||||
|
@ -68,7 +65,8 @@ uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
|
||||||
return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
|
return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {
|
Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer,
|
||||||
|
CodeViewContainer Container) const {
|
||||||
assert(Writer.getOffset() % alignOf(Container) == 0 &&
|
assert(Writer.getOffset() % alignOf(Container) == 0 &&
|
||||||
"Debug Subsection not properly aligned");
|
"Debug Subsection not properly aligned");
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
|
||||||
uint32_t Result = 0;
|
uint32_t Result = 0;
|
||||||
for (const auto &Builder : C13Builders) {
|
for (const auto &Builder : C13Builders) {
|
||||||
assert(Builder && "Empty C13 Fragment Builder!");
|
assert(Builder && "Empty C13 Fragment Builder!");
|
||||||
Result += Builder->calculateSerializedLength();
|
Result += Builder.calculateSerializedLength();
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
|
||||||
// TODO: Write C11 Line data
|
// TODO: Write C11 Line data
|
||||||
for (const auto &Builder : C13Builders) {
|
for (const auto &Builder : C13Builders) {
|
||||||
assert(Builder && "Empty C13 Fragment Builder!");
|
assert(Builder && "Empty C13 Fragment Builder!");
|
||||||
if (auto EC = Builder->commit(SymbolWriter))
|
if (auto EC = Builder.commit(SymbolWriter, CodeViewContainer::Pdb))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,12 +180,10 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
|
||||||
void DbiModuleDescriptorBuilder::addDebugSubsection(
|
void DbiModuleDescriptorBuilder::addDebugSubsection(
|
||||||
std::shared_ptr<DebugSubsection> Subsection) {
|
std::shared_ptr<DebugSubsection> Subsection) {
|
||||||
assert(Subsection);
|
assert(Subsection);
|
||||||
C13Builders.push_back(std::make_unique<DebugSubsectionRecordBuilder>(
|
C13Builders.push_back(DebugSubsectionRecordBuilder(std::move(Subsection)));
|
||||||
std::move(Subsection), CodeViewContainer::Pdb));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbiModuleDescriptorBuilder::addDebugSubsection(
|
void DbiModuleDescriptorBuilder::addDebugSubsection(
|
||||||
const DebugSubsectionRecord &SubsectionContents) {
|
const DebugSubsectionRecord &SubsectionContents) {
|
||||||
C13Builders.push_back(std::make_unique<DebugSubsectionRecordBuilder>(
|
C13Builders.push_back(DebugSubsectionRecordBuilder(SubsectionContents));
|
||||||
SubsectionContents, CodeViewContainer::Pdb));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,7 +187,7 @@ toDebugS(ArrayRef<CodeViewYAML::YAMLDebugSubsection> Subsections,
|
||||||
std::vector<DebugSubsectionRecordBuilder> Builders;
|
std::vector<DebugSubsectionRecordBuilder> Builders;
|
||||||
uint32_t Size = sizeof(uint32_t);
|
uint32_t Size = sizeof(uint32_t);
|
||||||
for (auto &SS : CVSS) {
|
for (auto &SS : CVSS) {
|
||||||
DebugSubsectionRecordBuilder B(SS, CodeViewContainer::ObjectFile);
|
DebugSubsectionRecordBuilder B(SS);
|
||||||
Size += B.calculateSerializedLength();
|
Size += B.calculateSerializedLength();
|
||||||
Builders.push_back(std::move(B));
|
Builders.push_back(std::move(B));
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ toDebugS(ArrayRef<CodeViewYAML::YAMLDebugSubsection> Subsections,
|
||||||
|
|
||||||
Err(Writer.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC));
|
Err(Writer.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC));
|
||||||
for (const auto &B : Builders) {
|
for (const auto &B : Builders) {
|
||||||
Err(B.commit(Writer));
|
Err(B.commit(Writer, CodeViewContainer::ObjectFile));
|
||||||
}
|
}
|
||||||
return {Output};
|
return {Output};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue