Skip to content

Commit c2a4ebb

Browse files
Cache AbbrevEntries after materializing
This patch caches abbreviation entries after materializing them onces to avoid rematerializing the same abbreviation entry for every DIE, thus speeding up MCCAS replay (cherry picked from commit 4e9c0dc)
1 parent 55858aa commit c2a4ebb

File tree

1 file changed

+149
-36
lines changed

1 file changed

+149
-36
lines changed

llvm/lib/MCCAS/MCCASObjectV1.cpp

Lines changed: 149 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3100,10 +3100,32 @@ struct DIEVisitor {
31003100
SmallVector<AbbrevContent> AbbrevContents;
31013101
};
31023102

3103+
DIEVisitor() = delete;
3104+
3105+
DIEVisitor(ArrayRef<StringRef> AbbrevEntries,
3106+
BinaryStreamReader DistinctReader, StringRef DistinctData,
3107+
std::function<void(StringRef)> HeaderCallback,
3108+
std::function<void(dwarf::Tag, uint64_t)> StartTagCallback,
3109+
std::function<void(dwarf::Attribute, dwarf::Form, StringRef, bool)>
3110+
AttrCallback,
3111+
std::function<void(bool)> EndTagCallback,
3112+
std::function<void(StringRef)> NewBlockCallback)
3113+
: AbbrevEntries(AbbrevEntries), DistinctReader(DistinctReader),
3114+
DistinctData(DistinctData), HeaderCallback(HeaderCallback),
3115+
StartTagCallback(StartTagCallback), AttrCallback(AttrCallback),
3116+
EndTagCallback(EndTagCallback), NewBlockCallback(NewBlockCallback) {
3117+
AbbrevEntryCache.reserve(AbbrevEntries.size());
3118+
for (unsigned I = 0; I < AbbrevEntries.size(); I++) {
3119+
if (Error E = materializeAbbrevDIE(encodeAbbrevIndex(I)))
3120+
report_fatal_error(std::move(E));
3121+
}
3122+
}
3123+
31033124
Error visitDIERef(DIEDedupeTopLevelRef Ref);
31043125
Error visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack);
3105-
Error visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
3106-
BinaryStreamReader &Reader, StringRef DIEData);
3126+
Error visitDIEAttrs(BinaryStreamReader &DataReader, StringRef DIEData,
3127+
ArrayRef<AbbrevContent> DIEContents);
3128+
Error materializeAbbrevDIE(unsigned AbbrevIdx);
31073129

31083130
SmallVector<AbbrevEntry> AbbrevEntryCache;
31093131
ArrayRef<StringRef> AbbrevEntries;
@@ -3118,38 +3140,31 @@ struct DIEVisitor {
31183140
std::function<void(StringRef)> NewBlockCallback;
31193141
};
31203142

3121-
Error DIEVisitor::visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
3122-
BinaryStreamReader &DataReader,
3123-
StringRef DIEData) {
3143+
Error DIEVisitor::visitDIEAttrs(BinaryStreamReader &DataReader,
3144+
StringRef DIEData,
3145+
ArrayRef<AbbrevContent> DIEContents) {
31243146
constexpr auto IsLittleEndian = true;
31253147
constexpr auto AddrSize = 8;
31263148
constexpr auto FormParams =
31273149
dwarf::FormParams{4 /*Version*/, AddrSize, dwarf::DwarfFormat::DWARF32};
31283150

3129-
while (true) {
3130-
Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr();
3131-
if (!Attr)
3132-
return Attr.takeError();
3133-
if (*Attr == getEndOfAttributesMarker())
3134-
break;
3135-
3136-
Expected<dwarf::Form> Form = AbbrevReader.readForm();
3137-
if (!Form)
3138-
return Form.takeError();
3139-
3140-
bool DataInDistinct = doesntDedup(*Form, *Attr);
3151+
for (auto Contents : DIEContents) {
3152+
bool DataInDistinct = Contents.FormInDistinctData;
31413153
auto &ReaderForData = DataInDistinct ? DistinctReader : DataReader;
31423154
StringRef DataToUse = DataInDistinct ? DistinctData : DIEData;
31433155
Expected<uint64_t> FormSize =
3144-
getFormSize(*Form, FormParams, DataToUse, ReaderForData.getOffset(),
3145-
IsLittleEndian, AddrSize);
3156+
Contents.FormSize
3157+
? *Contents.FormSize
3158+
: getFormSize(Contents.Form, FormParams, DataToUse,
3159+
ReaderForData.getOffset(), IsLittleEndian, AddrSize);
31463160
if (!FormSize)
31473161
return FormSize.takeError();
31483162

31493163
ArrayRef<char> RawBytes;
31503164
if (auto E = ReaderForData.readArray(RawBytes, *FormSize))
31513165
return E;
3152-
AttrCallback(*Attr, *Form, toStringRef(RawBytes), DataInDistinct);
3166+
AttrCallback(Contents.Attr, Contents.Form, toStringRef(RawBytes),
3167+
DataInDistinct);
31533168
}
31543169
return Error::success();
31553170
}
@@ -3168,6 +3183,111 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
31683183
return AbbrevEntryReader(AbbrevData);
31693184
}
31703185

3186+
static std::optional<uint8_t> getNonULEBFormSize(dwarf::Form Form,
3187+
dwarf::FormParams FP) {
3188+
switch (Form) {
3189+
case dwarf::DW_FORM_addr:
3190+
return FP.AddrSize;
3191+
case dwarf::DW_FORM_ref_addr:
3192+
return FP.getRefAddrByteSize();
3193+
case dwarf::DW_FORM_exprloc:
3194+
case dwarf::DW_FORM_block:
3195+
case dwarf::DW_FORM_block1:
3196+
case dwarf::DW_FORM_block2:
3197+
case dwarf::DW_FORM_block4:
3198+
case dwarf::DW_FORM_sdata:
3199+
case dwarf::DW_FORM_udata:
3200+
case dwarf::DW_FORM_ref_udata:
3201+
case dwarf::DW_FORM_ref4_cas:
3202+
case dwarf::DW_FORM_strp_cas:
3203+
case dwarf::DW_FORM_rnglistx:
3204+
case dwarf::DW_FORM_loclistx:
3205+
case dwarf::DW_FORM_GNU_addr_index:
3206+
case dwarf::DW_FORM_GNU_str_index:
3207+
case dwarf::DW_FORM_addrx:
3208+
case dwarf::DW_FORM_strx:
3209+
case dwarf::DW_FORM_LLVM_addrx_offset:
3210+
case dwarf::DW_FORM_string:
3211+
case dwarf::DW_FORM_indirect:
3212+
return std::nullopt;
3213+
3214+
case dwarf::DW_FORM_implicit_const:
3215+
case dwarf::DW_FORM_flag_present:
3216+
return 0;
3217+
case dwarf::DW_FORM_data1:
3218+
case dwarf::DW_FORM_ref1:
3219+
case dwarf::DW_FORM_flag:
3220+
case dwarf::DW_FORM_strx1:
3221+
case dwarf::DW_FORM_addrx1:
3222+
return 1;
3223+
case dwarf::DW_FORM_data2:
3224+
case dwarf::DW_FORM_ref2:
3225+
case dwarf::DW_FORM_strx2:
3226+
case dwarf::DW_FORM_addrx2:
3227+
return 2;
3228+
case dwarf::DW_FORM_strx3:
3229+
return 3;
3230+
case dwarf::DW_FORM_data4:
3231+
case dwarf::DW_FORM_ref4:
3232+
case dwarf::DW_FORM_ref_sup4:
3233+
case dwarf::DW_FORM_strx4:
3234+
case dwarf::DW_FORM_addrx4:
3235+
return 4;
3236+
case dwarf::DW_FORM_ref_sig8:
3237+
case dwarf::DW_FORM_data8:
3238+
case dwarf::DW_FORM_ref8:
3239+
case dwarf::DW_FORM_ref_sup8:
3240+
return 8;
3241+
case dwarf::DW_FORM_data16:
3242+
return 16;
3243+
case dwarf::DW_FORM_strp:
3244+
case dwarf::DW_FORM_sec_offset:
3245+
case dwarf::DW_FORM_GNU_ref_alt:
3246+
case dwarf::DW_FORM_GNU_strp_alt:
3247+
case dwarf::DW_FORM_line_strp:
3248+
case dwarf::DW_FORM_strp_sup:
3249+
return FP.getDwarfOffsetByteSize();
3250+
case dwarf::DW_FORM_addrx3:
3251+
case dwarf::DW_FORM_lo_user:
3252+
llvm_unreachable("usupported form");
3253+
break;
3254+
}
3255+
}
3256+
3257+
Error DIEVisitor::materializeAbbrevDIE(unsigned AbbrevIdx) {
3258+
constexpr auto AddrSize = 8;
3259+
constexpr auto FormParams =
3260+
dwarf::FormParams{4 /*Version*/, AddrSize, dwarf::DwarfFormat::DWARF32};
3261+
3262+
AbbrevEntryReader AbbrevReader =
3263+
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
3264+
Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag();
3265+
if (!MaybeTag)
3266+
return MaybeTag.takeError();
3267+
3268+
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3269+
if (!MaybeHasChildren)
3270+
return MaybeHasChildren.takeError();
3271+
3272+
SmallVector<AbbrevContent> AbbrevVector;
3273+
while (true) {
3274+
Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr();
3275+
if (!Attr)
3276+
return Attr.takeError();
3277+
if (*Attr == getEndOfAttributesMarker())
3278+
break;
3279+
3280+
Expected<dwarf::Form> Form = AbbrevReader.readForm();
3281+
if (!Form)
3282+
return Form.takeError();
3283+
AbbrevVector.push_back({*Attr, *Form, doesntDedup(*Form, *Attr),
3284+
getNonULEBFormSize(*Form, FormParams)});
3285+
}
3286+
AbbrevEntryCache.push_back(
3287+
{*MaybeTag, *MaybeHasChildren, std::move(AbbrevVector)});
3288+
return Error::success();
3289+
}
3290+
31713291
/// Restores the state of the \p Reader and \p Data
31723292
/// arguments to a previous state. The algorithm in visitDIERefs is an iterative
31733293
/// implementation of a Depth First Search, and this function is used to
@@ -3220,25 +3340,18 @@ Error DIEVisitor::visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack) {
32203340
}
32213341

32223342
// If we have a legitimate AbbrevIdx, materialize the current DIE.
3223-
AbbrevEntryReader AbbrevReader =
3224-
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
3225-
3226-
if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag())
3227-
StartTagCallback(*MaybeTag, AbbrevIdx);
3228-
else
3229-
return MaybeTag.takeError();
3230-
3231-
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3232-
if (!MaybeHasChildren)
3233-
return MaybeHasChildren.takeError();
3343+
auto &AbbrevEntryCacheVal =
3344+
AbbrevEntryCache[decodeAbbrevIndexAsAbbrevSetIdx(AbbrevIdx)];
3345+
StartTagCallback(AbbrevEntryCacheVal.Tag, AbbrevIdx);
32343346

3235-
if (auto E = visitDIEAttrs(AbbrevReader, Reader, Data))
3347+
if (auto E =
3348+
visitDIEAttrs(Reader, Data, AbbrevEntryCacheVal.AbbrevContents))
32363349
return E;
32373350

32383351
// If the current DIE doesn't have any children, the current CAS Object will
32393352
// not contain any more data, pop the stack to continue materializing its
32403353
// parent's siblings that may exist.
3241-
if (!*MaybeHasChildren) {
3354+
if (!AbbrevEntryCacheVal.HasChildren) {
32423355
if (!StackOfNodes.empty() && Reader.empty())
32433356
popStack(Reader, Data, StackOfNodes);
32443357
EndTagCallback(false /*HadChildren*/);
@@ -3310,8 +3423,8 @@ Error mccasformats::v1::visitDebugInfo(
33103423
HeaderCallback(toStringRef(HeaderData));
33113424

33123425
append_range(TotAbbrevEntries, LoadedTopRef->AbbrevEntries);
3313-
DIEVisitor Visitor{{}, TotAbbrevEntries, DistinctReader,
3314-
DistinctData, HeaderCallback, StartTagCallback,
3315-
AttrCallback, EndTagCallback, NewBlockCallback};
3426+
DIEVisitor Visitor{TotAbbrevEntries, DistinctReader, DistinctData,
3427+
HeaderCallback, StartTagCallback, AttrCallback,
3428+
EndTagCallback, NewBlockCallback};
33163429
return Visitor.visitDIERef(LoadedTopRef->RootDIE);
33173430
}

0 commit comments

Comments
 (0)