Skip to content

Commit 4e9c0dc

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
1 parent 90eb045 commit 4e9c0dc

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
@@ -3112,10 +3112,32 @@ struct DIEVisitor {
31123112
SmallVector<AbbrevContent> AbbrevContents;
31133113
};
31143114

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+
31153136
Error visitDIERef(DIEDedupeTopLevelRef Ref);
31163137
Error visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack);
3117-
Error visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
3118-
BinaryStreamReader &Reader, StringRef DIEData);
3138+
Error visitDIEAttrs(BinaryStreamReader &DataReader, StringRef DIEData,
3139+
ArrayRef<AbbrevContent> DIEContents);
3140+
Error materializeAbbrevDIE(unsigned AbbrevIdx);
31193141

31203142
SmallVector<AbbrevEntry> AbbrevEntryCache;
31213143
ArrayRef<StringRef> AbbrevEntries;
@@ -3130,38 +3152,31 @@ struct DIEVisitor {
31303152
std::function<void(StringRef)> NewBlockCallback;
31313153
};
31323154

3133-
Error DIEVisitor::visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
3134-
BinaryStreamReader &DataReader,
3135-
StringRef DIEData) {
3155+
Error DIEVisitor::visitDIEAttrs(BinaryStreamReader &DataReader,
3156+
StringRef DIEData,
3157+
ArrayRef<AbbrevContent> DIEContents) {
31363158
constexpr auto IsLittleEndian = true;
31373159
constexpr auto AddrSize = 8;
31383160
constexpr auto FormParams =
31393161
dwarf::FormParams{4 /*Version*/, AddrSize, dwarf::DwarfFormat::DWARF32};
31403162

3141-
while (true) {
3142-
Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr();
3143-
if (!Attr)
3144-
return Attr.takeError();
3145-
if (*Attr == getEndOfAttributesMarker())
3146-
break;
3147-
3148-
Expected<dwarf::Form> Form = AbbrevReader.readForm();
3149-
if (!Form)
3150-
return Form.takeError();
3151-
3152-
bool DataInDistinct = doesntDedup(*Form, *Attr);
3163+
for (auto Contents : DIEContents) {
3164+
bool DataInDistinct = Contents.FormInDistinctData;
31533165
auto &ReaderForData = DataInDistinct ? DistinctReader : DataReader;
31543166
StringRef DataToUse = DataInDistinct ? DistinctData : DIEData;
31553167
Expected<uint64_t> FormSize =
3156-
getFormSize(*Form, FormParams, DataToUse, ReaderForData.getOffset(),
3157-
IsLittleEndian, AddrSize);
3168+
Contents.FormSize
3169+
? *Contents.FormSize
3170+
: getFormSize(Contents.Form, FormParams, DataToUse,
3171+
ReaderForData.getOffset(), IsLittleEndian, AddrSize);
31583172
if (!FormSize)
31593173
return FormSize.takeError();
31603174

31613175
ArrayRef<char> RawBytes;
31623176
if (auto E = ReaderForData.readArray(RawBytes, *FormSize))
31633177
return E;
3164-
AttrCallback(*Attr, *Form, toStringRef(RawBytes), DataInDistinct);
3178+
AttrCallback(Contents.Attr, Contents.Form, toStringRef(RawBytes),
3179+
DataInDistinct);
31653180
}
31663181
return Error::success();
31673182
}
@@ -3180,6 +3195,111 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
31803195
return AbbrevEntryReader(AbbrevData);
31813196
}
31823197

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+
31833303
/// Restores the state of the \p Reader and \p Data
31843304
/// arguments to a previous state. The algorithm in visitDIERefs is an iterative
31853305
/// implementation of a Depth First Search, and this function is used to
@@ -3232,25 +3352,18 @@ Error DIEVisitor::visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack) {
32323352
}
32333353

32343354
// If we have a legitimate AbbrevIdx, materialize the current DIE.
3235-
AbbrevEntryReader AbbrevReader =
3236-
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
3237-
3238-
if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag())
3239-
StartTagCallback(*MaybeTag, AbbrevIdx);
3240-
else
3241-
return MaybeTag.takeError();
3242-
3243-
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3244-
if (!MaybeHasChildren)
3245-
return MaybeHasChildren.takeError();
3355+
auto &AbbrevEntryCacheVal =
3356+
AbbrevEntryCache[decodeAbbrevIndexAsAbbrevSetIdx(AbbrevIdx)];
3357+
StartTagCallback(AbbrevEntryCacheVal.Tag, AbbrevIdx);
32463358

3247-
if (auto E = visitDIEAttrs(AbbrevReader, Reader, Data))
3359+
if (auto E =
3360+
visitDIEAttrs(Reader, Data, AbbrevEntryCacheVal.AbbrevContents))
32483361
return E;
32493362

32503363
// If the current DIE doesn't have any children, the current CAS Object will
32513364
// not contain any more data, pop the stack to continue materializing its
32523365
// parent's siblings that may exist.
3253-
if (!*MaybeHasChildren) {
3366+
if (!AbbrevEntryCacheVal.HasChildren) {
32543367
if (!StackOfNodes.empty() && Reader.empty())
32553368
popStack(Reader, Data, StackOfNodes);
32563369
EndTagCallback(false /*HadChildren*/);
@@ -3322,8 +3435,8 @@ Error mccasformats::v1::visitDebugInfo(
33223435
HeaderCallback(toStringRef(HeaderData));
33233436

33243437
append_range(TotAbbrevEntries, LoadedTopRef->AbbrevEntries);
3325-
DIEVisitor Visitor{{}, TotAbbrevEntries, DistinctReader,
3326-
DistinctData, HeaderCallback, StartTagCallback,
3327-
AttrCallback, EndTagCallback, NewBlockCallback};
3438+
DIEVisitor Visitor{TotAbbrevEntries, DistinctReader, DistinctData,
3439+
HeaderCallback, StartTagCallback, AttrCallback,
3440+
EndTagCallback, NewBlockCallback};
33283441
return Visitor.visitDIERef(LoadedTopRef->RootDIE);
33293442
}

0 commit comments

Comments
 (0)