diff options
author | Greg Clayton <gclayton@apple.com> | 2016-11-15 01:23:06 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2016-11-15 01:23:06 +0000 |
commit | 6f6e4dbd5dacf9ec1c43921bad76d5a3b3ab67b0 (patch) | |
tree | b5f1b457398183c51166e3fd02e934f1b08ef748 /llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp | |
parent | f83806a8adb4fdc7d785b66d48b42459f7874807 (diff) | |
download | bcm5719-llvm-6f6e4dbd5dacf9ec1c43921bad76d5a3b3ab67b0.tar.gz bcm5719-llvm-6f6e4dbd5dacf9ec1c43921bad76d5a3b3ab67b0.zip |
Improve DWARF parsing speed by improving DWARFAbbreviationDeclaration
This patch gets a DWARF parsing speed improvement by having DWARFAbbreviationDeclaration instances know if they have a fixed byte size. If an abbreviation has a fixed byte size that can be calculated given a DWARFUnit, then parsing a DIE becomes two steps: parse ULEB128 abbrev code, and then add constant size to the offset.
This patch also adds a fixed byte size to each DWARFAbbreviationDeclaration::AttributeSpec so that attributes can quickly skip their values if needed without the need to lookup the fixed for size.
Notable improvements:
- DWARFAbbreviationDeclaration::findAttributeIndex() now returns an Optional<uint32_t> instead of a uint32_t and we no longer have to look for the magic -1U return value
- Optional<uint32_t> DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute attr) const;
- DWARFAbbreviationDeclaration now has a getAttributeValue() function that extracts an attribute value given a DIE offset that takes advantage of the DWARFAbbreviationDeclaration::AttributeSpec::ByteSize
- bool DWARFAbbreviationDeclaration::getAttributeValue(const uint32_t DIEOffset, const dwarf::Attribute Attr, const DWARFUnit &U, DWARFFormValue &FormValue) const;
- A DWARFAbbreviationDeclaration instance can return a fixed byte size for itself so DWARF parsing is faster:
- Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(const DWARFUnit &U) const;
- Any functions that used to take a "const DWARFUnit *U" that would crash if U was NULL now take a "const DWARFUnit &U" and are only called with a valid DWARFUnit
Differential Revision: https://reviews.llvm.org/D26567
llvm-svn: 286924
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp | 109 |
1 files changed, 104 insertions, 5 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp index 637d12ddd43..638830ee568 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -17,8 +19,10 @@ using namespace dwarf; void DWARFAbbreviationDeclaration::clear() { Code = 0; Tag = DW_TAG_null; + CodeByteSize = 0; HasChildren = false; AttributeSpecs.clear(); + FixedAttributeSize.reset(); } DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() { @@ -29,10 +33,12 @@ bool DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint32_t* OffsetPtr) { clear(); + const uint32_t Offset = *OffsetPtr; Code = Data.getULEB128(OffsetPtr); if (Code == 0) { return false; } + CodeByteSize = *OffsetPtr - Offset; Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr)); if (Tag == DW_TAG_null) { clear(); @@ -40,12 +46,52 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data, } uint8_t ChildrenByte = Data.getU8(OffsetPtr); HasChildren = (ChildrenByte == DW_CHILDREN_yes); + // Assign a value to our optional FixedAttributeSize member variable. If + // this member variable still has a value after the while loop below, then + // all attribute data in this abbreviation declaration has a fixed byte size. + FixedAttributeSize = FixedSizeInfo(); + // Read all of the abbreviation attributes and forms. while (true) { auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr)); auto F = static_cast<Form>(Data.getULEB128(OffsetPtr)); if (A && F) { - AttributeSpecs.push_back(AttributeSpec(A, F)); + auto FixedFormByteSize = DWARFFormValue::getFixedByteSize(F); + AttributeSpecs.push_back(AttributeSpec(A, F, FixedFormByteSize)); + // If this abbrevation still has a fixed byte size, then update the + // FixedAttributeSize as needed. + if (FixedAttributeSize) { + if (FixedFormByteSize) + FixedAttributeSize->NumBytes += *FixedFormByteSize; + else { + switch (F) { + case DW_FORM_addr: + ++FixedAttributeSize->NumAddrs; + break; + + case DW_FORM_ref_addr: + ++FixedAttributeSize->NumRefAddrs; + break; + + case DW_FORM_strp: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: + case DW_FORM_line_strp: + case DW_FORM_sec_offset: + case DW_FORM_strp_sup: + case DW_FORM_ref_sup: + ++FixedAttributeSize->NumDwarfOffsets; + break; + + default: + // Indicate we no longer have a fixed byte size for this + // abbreviation by clearing the FixedAttributeSize optional value + // so it doesn't have a value. + FixedAttributeSize.reset(); + break; + } + } + } } else if (A == 0 && F == 0) { // We successfully reached the end of this abbreviation declaration // since both attribute and form are zero. @@ -88,11 +134,64 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { OS << '\n'; } -uint32_t -DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute attr) const { +Optional<uint32_t> +DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const { for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) { - if (AttributeSpecs[i].Attr == attr) + if (AttributeSpecs[i].Attr == Attr) return i; } - return -1U; + return None; +} + +bool DWARFAbbreviationDeclaration::getAttributeValue( + const uint32_t DIEOffset, const dwarf::Attribute Attr, const DWARFUnit &U, + DWARFFormValue &FormValue) const { + Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr); + if (!MatchAttrIndex) + return false; + + auto DebugInfoData = U.getDebugInfoExtractor(); + + // Add the byte size of ULEB that for the abbrev Code so we can start + // skipping the attribute data. + uint32_t Offset = DIEOffset + CodeByteSize; + uint32_t AttrIndex = 0; + for (const auto &Spec : AttributeSpecs) { + if (*MatchAttrIndex == AttrIndex) { + // We have arrived at the attribute to extract, extract if from Offset. + FormValue.setForm(Spec.Form); + return FormValue.extractValue(DebugInfoData, &Offset, &U); + } + // March Offset along until we get to the attribute we want. + if (Optional<uint8_t> FixedSize = Spec.getByteSize(U)) + Offset += *FixedSize; + else + DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, &U); + ++AttrIndex; + } + return false; +} + +size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize( + const DWARFUnit &U) const { + size_t ByteSize = NumBytes; + if (NumAddrs) + ByteSize += NumAddrs * U.getAddressByteSize(); + if (NumRefAddrs) + ByteSize += NumRefAddrs * U.getRefAddrByteSize(); + if (NumDwarfOffsets) + ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize(); + return ByteSize; +} + +Optional<uint8_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize( + const DWARFUnit &U) const { + return ByteSize ? ByteSize : DWARFFormValue::getFixedByteSize(Form, &U); +} + +Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize( + const DWARFUnit &U) const { + if (FixedAttributeSize) + return FixedAttributeSize->getByteSize(U); + return None; } |