Skip to content

Commit 09b24c2

Browse files
Merge pull request #7852 from rastogishubham/CachingMCCAS
Cache Abbreviation entries after materializing them to speedup MCCAS replay
2 parents 90c4be1 + 4e9c0dc commit 09b24c2

File tree

1 file changed

+161
-33
lines changed

1 file changed

+161
-33
lines changed

llvm/lib/MCCAS/MCCASObjectV1.cpp

Lines changed: 161 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3098,11 +3098,48 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
30983098
}
30993099

31003100
struct DIEVisitor {
3101+
3102+
struct AbbrevContent {
3103+
dwarf::Attribute Attr;
3104+
dwarf::Form Form;
3105+
bool FormInDistinctData;
3106+
std::optional<uint8_t> FormSize;
3107+
};
3108+
3109+
struct AbbrevEntry {
3110+
dwarf::Tag Tag;
3111+
bool HasChildren;
3112+
SmallVector<AbbrevContent> AbbrevContents;
3113+
};
3114+
3115+
DIEVisitor() = delete;
3116+
3117+
DIEVisitor(ArrayRef<StringRef> AbbrevEntries,
3118+
BinaryStreamReader DistinctReader, StringRef DistinctData,
3119+
std::function<void(StringRef)> HeaderCallback,
3120+
std::function<void(dwarf::Tag, uint64_t)> StartTagCallback,
3121+
std::function<void(dwarf::Attribute, dwarf::Form, StringRef, bool)>
3122+
AttrCallback,
3123+
std::function<void(bool)> EndTagCallback,
3124+
std::function<void(StringRef)> NewBlockCallback)
3125+
: AbbrevEntries(AbbrevEntries), DistinctReader(DistinctReader),
3126+
DistinctData(DistinctData), HeaderCallback(HeaderCallback),
3127+
StartTagCallback(StartTagCallback), AttrCallback(AttrCallback),
3128+
EndTagCallback(EndTagCallback), NewBlockCallback(NewBlockCallback) {
3129+
AbbrevEntryCache.reserve(AbbrevEntries.size());
3130+
for (unsigned I = 0; I < AbbrevEntries.size(); I++) {
3131+
if (Error E = materializeAbbrevDIE(encodeAbbrevIndex(I)))
3132+
report_fatal_error(std::move(E));
3133+
}
3134+
}
3135+
31013136
Error visitDIERef(DIEDedupeTopLevelRef Ref);
31023137
Error visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack);
3103-
Error visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
3104-
BinaryStreamReader &Reader, StringRef DIEData);
3138+
Error visitDIEAttrs(BinaryStreamReader &DataReader, StringRef DIEData,
3139+
ArrayRef<AbbrevContent> DIEContents);
3140+
Error materializeAbbrevDIE(unsigned AbbrevIdx);
31053141

3142+
SmallVector<AbbrevEntry> AbbrevEntryCache;
31063143
ArrayRef<StringRef> AbbrevEntries;
31073144
BinaryStreamReader DistinctReader;
31083145
StringRef DistinctData;
@@ -3115,38 +3152,31 @@ struct DIEVisitor {
31153152
std::function<void(StringRef)> NewBlockCallback;
31163153
};
31173154

3118-
Error DIEVisitor::visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
3119-
BinaryStreamReader &DataReader,
3120-
StringRef DIEData) {
3155+
Error DIEVisitor::visitDIEAttrs(BinaryStreamReader &DataReader,
3156+
StringRef DIEData,
3157+
ArrayRef<AbbrevContent> DIEContents) {
31213158
constexpr auto IsLittleEndian = true;
31223159
constexpr auto AddrSize = 8;
31233160
constexpr auto FormParams =
31243161
dwarf::FormParams{4 /*Version*/, AddrSize, dwarf::DwarfFormat::DWARF32};
31253162

3126-
while (true) {
3127-
Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr();
3128-
if (!Attr)
3129-
return Attr.takeError();
3130-
if (*Attr == getEndOfAttributesMarker())
3131-
break;
3132-
3133-
Expected<dwarf::Form> Form = AbbrevReader.readForm();
3134-
if (!Form)
3135-
return Form.takeError();
3136-
3137-
bool DataInDistinct = doesntDedup(*Form, *Attr);
3163+
for (auto Contents : DIEContents) {
3164+
bool DataInDistinct = Contents.FormInDistinctData;
31383165
auto &ReaderForData = DataInDistinct ? DistinctReader : DataReader;
31393166
StringRef DataToUse = DataInDistinct ? DistinctData : DIEData;
31403167
Expected<uint64_t> FormSize =
3141-
getFormSize(*Form, FormParams, DataToUse, ReaderForData.getOffset(),
3142-
IsLittleEndian, AddrSize);
3168+
Contents.FormSize
3169+
? *Contents.FormSize
3170+
: getFormSize(Contents.Form, FormParams, DataToUse,
3171+
ReaderForData.getOffset(), IsLittleEndian, AddrSize);
31433172
if (!FormSize)
31443173
return FormSize.takeError();
31453174

31463175
ArrayRef<char> RawBytes;
31473176
if (auto E = ReaderForData.readArray(RawBytes, *FormSize))
31483177
return E;
3149-
AttrCallback(*Attr, *Form, toStringRef(RawBytes), DataInDistinct);
3178+
AttrCallback(Contents.Attr, Contents.Form, toStringRef(RawBytes),
3179+
DataInDistinct);
31503180
}
31513181
return Error::success();
31523182
}
@@ -3165,6 +3195,111 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
31653195
return AbbrevEntryReader(AbbrevData);
31663196
}
31673197

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

32193354
// If we have a legitimate AbbrevIdx, materialize the current DIE.
3220-
AbbrevEntryReader AbbrevReader =
3221-
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
3222-
3223-
if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag())
3224-
StartTagCallback(*MaybeTag, AbbrevIdx);
3225-
else
3226-
return MaybeTag.takeError();
3227-
3228-
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3229-
if (!MaybeHasChildren)
3230-
return MaybeHasChildren.takeError();
3355+
auto &AbbrevEntryCacheVal =
3356+
AbbrevEntryCache[decodeAbbrevIndexAsAbbrevSetIdx(AbbrevIdx)];
3357+
StartTagCallback(AbbrevEntryCacheVal.Tag, AbbrevIdx);
32313358

3232-
if (auto E = visitDIEAttrs(AbbrevReader, Reader, Data))
3359+
if (auto E =
3360+
visitDIEAttrs(Reader, Data, AbbrevEntryCacheVal.AbbrevContents))
32333361
return E;
32343362

32353363
// If the current DIE doesn't have any children, the current CAS Object will
32363364
// not contain any more data, pop the stack to continue materializing its
32373365
// parent's siblings that may exist.
3238-
if (!*MaybeHasChildren) {
3366+
if (!AbbrevEntryCacheVal.HasChildren) {
32393367
if (!StackOfNodes.empty() && Reader.empty())
32403368
popStack(Reader, Data, StackOfNodes);
32413369
EndTagCallback(false /*HadChildren*/);

0 commit comments

Comments
 (0)