Skip to content

Commit dfd6383

Browse files
committed
⚡ [Lex] Better reservations for improved performance/memory usage.
1 parent 357bda5 commit dfd6383

File tree

2 files changed

+93
-21
lines changed

2 files changed

+93
-21
lines changed

clang/include/clang/Lex/Preprocessor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2729,14 +2729,14 @@ class Preprocessor {
27292729
const FileEntry *LookupFromFile = nullptr);
27302730
void HandleEmbedDirectiveNaive(SourceLocation HashLoc,
27312731
SourceLocation FilenameTok,
2732-
LexEmbedParametersResult &Params,
2732+
const LexEmbedParametersResult &Params,
27332733
StringRef BinaryContents,
27342734
const size_t TargetCharWidth);
27352735
void HandleEmbedDirectiveBuiltin(SourceLocation HashLoc,
27362736
const Token &FilenameTok,
27372737
StringRef ResolvedFilename,
27382738
StringRef SearchPath, StringRef RelativePath,
2739-
LexEmbedParametersResult &Params,
2739+
const LexEmbedParametersResult &Params,
27402740
StringRef BinaryContents,
27412741
const size_t TargetCharWidth);
27422742

clang/lib/Lex/PPDirectives.cpp

Lines changed: 91 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3854,11 +3854,59 @@ inline constexpr const char *IntegerLiterals[] = {
38543854
"242", "243", "244", "245", "246", "247", "248", "249", "250", "251", "252",
38553855
"253", "254", "255"};
38563856

3857-
void Preprocessor::HandleEmbedDirectiveNaive(SourceLocation HashLoc,
3858-
SourceLocation FilenameLoc,
3859-
LexEmbedParametersResult &Params,
3860-
StringRef BinaryContents,
3861-
const size_t TargetCharWidth) {
3857+
static size_t
3858+
ComputeNaiveReserveSize(const Preprocessor::LexEmbedParametersResult &Params,
3859+
StringRef TypeName, StringRef BinaryContents,
3860+
SmallVectorImpl<char> &TokSpellingBuffer) {
3861+
size_t ReserveSize = 0;
3862+
if (BinaryContents.empty()) {
3863+
if (Params.MaybeIfEmptyParam) {
3864+
for (const auto &Tok : Params.MaybeIfEmptyParam->Tokens) {
3865+
const size_t TokLen = Tok.getLength();
3866+
if (TokLen > TokSpellingBuffer.size()) {
3867+
TokSpellingBuffer.resize(TokLen);
3868+
}
3869+
ReserveSize += TokLen;
3870+
}
3871+
}
3872+
} else {
3873+
if (Params.MaybePrefixParam) {
3874+
for (const auto &Tok : Params.MaybePrefixParam->Tokens) {
3875+
const size_t TokLen = Tok.getLength();
3876+
if (TokLen > TokSpellingBuffer.size()) {
3877+
TokSpellingBuffer.resize(TokLen);
3878+
}
3879+
ReserveSize += TokLen;
3880+
}
3881+
}
3882+
for (const auto &Byte : BinaryContents) {
3883+
ReserveSize += 3 + TypeName.size(); // ((type-name)
3884+
if (Byte > 99) {
3885+
ReserveSize += 3; // ###
3886+
} else if (Byte > 9) {
3887+
ReserveSize += 2; // ##
3888+
} else {
3889+
ReserveSize += 1; // #
3890+
}
3891+
ReserveSize += 2; // ),
3892+
}
3893+
if (Params.MaybePrefixParam) {
3894+
for (const auto &Tok : Params.MaybePrefixParam->Tokens) {
3895+
const size_t TokLen = Tok.getLength();
3896+
if (TokLen > TokSpellingBuffer.size()) {
3897+
TokSpellingBuffer.resize(TokLen);
3898+
}
3899+
ReserveSize += TokLen;
3900+
}
3901+
}
3902+
}
3903+
return ReserveSize;
3904+
}
3905+
3906+
void Preprocessor::HandleEmbedDirectiveNaive(
3907+
SourceLocation HashLoc, SourceLocation FilenameLoc,
3908+
const LexEmbedParametersResult &Params, StringRef BinaryContents,
3909+
const size_t TargetCharWidth) {
38623910
// Load up a new embed buffer for this file and set of parameters in
38633911
// particular.
38643912
EmbedBuffers.push_back("");
@@ -3869,30 +3917,37 @@ void Preprocessor::HandleEmbedDirectiveNaive(SourceLocation HashLoc,
38693917
return PrefixNumber.concat(">");
38703918
}(EmbedBufferNumberVal);
38713919
std::string &TargetEmbedBuffer = EmbedBuffers.back();
3920+
const size_t TotalSize = BinaryContents.size();
3921+
// In the future, this might change/improve.
3922+
const StringRef TypeName = "unsigned char";
38723923

3873-
// In the future, this might improve.
3874-
const StringRef SmallestType = "unsigned char";
3924+
SmallVector<char, 32> TokSpellingBuffer(32, 0);
3925+
const size_t ReserveSize = ComputeNaiveReserveSize(
3926+
Params, TypeName, BinaryContents, TokSpellingBuffer);
3927+
TargetEmbedBuffer.reserve(ReserveSize);
38753928

38763929
// Generate the look-alike source file
38773930
if (BinaryContents.empty()) {
38783931
if (Params.MaybeIfEmptyParam) {
3879-
PPEmbedParameterIfEmpty &EmptyParam = *Params.MaybeIfEmptyParam;
3932+
const PPEmbedParameterIfEmpty &EmptyParam = *Params.MaybeIfEmptyParam;
38803933
for (const auto &Tok : EmptyParam.Tokens) {
3881-
TargetEmbedBuffer.append(this->getSpelling(Tok));
3934+
StringRef Spelling = this->getSpelling(Tok, TokSpellingBuffer);
3935+
TargetEmbedBuffer.append(Spelling.data(), Spelling.size());
38823936
}
38833937
}
38843938
} else {
38853939
if (Params.MaybePrefixParam) {
3886-
PPEmbedParameterPrefix &PrefixParam = *Params.MaybePrefixParam;
3940+
const PPEmbedParameterPrefix &PrefixParam = *Params.MaybePrefixParam;
38873941
for (const auto &Tok : PrefixParam.Tokens) {
3888-
TargetEmbedBuffer.append(this->getSpelling(Tok));
3942+
StringRef Spelling = this->getSpelling(Tok, TokSpellingBuffer);
3943+
TargetEmbedBuffer.append(Spelling.data(), Spelling.size());
38893944
}
38903945
}
38913946
for (size_t I = 0; I < BinaryContents.size(); ++I) {
38923947
unsigned char ByteValue = BinaryContents[I];
38933948
StringRef ByteRepresentation = IntegerLiterals[ByteValue];
38943949
TargetEmbedBuffer.append(2, '(');
3895-
TargetEmbedBuffer.append(SmallestType.data(), SmallestType.size());
3950+
TargetEmbedBuffer.append(TypeName.data(), TypeName.size());
38963951
TargetEmbedBuffer.append(1, ')');
38973952
TargetEmbedBuffer.append(ByteRepresentation.data(),
38983953
ByteRepresentation.size());
@@ -3903,9 +3958,10 @@ void Preprocessor::HandleEmbedDirectiveNaive(SourceLocation HashLoc,
39033958
}
39043959
}
39053960
if (Params.MaybeSuffixParam) {
3906-
PPEmbedParameterSuffix &SuffixParam = *Params.MaybeSuffixParam;
3961+
const PPEmbedParameterSuffix &SuffixParam = *Params.MaybeSuffixParam;
39073962
for (const auto &Tok : SuffixParam.Tokens) {
3908-
TargetEmbedBuffer.append(this->getSpelling(Tok));
3963+
StringRef Spelling = this->getSpelling(Tok, TokSpellingBuffer);
3964+
TargetEmbedBuffer.append(Spelling.data(), Spelling.size());
39093965
}
39103966
}
39113967
}
@@ -3926,7 +3982,7 @@ void Preprocessor::HandleEmbedDirectiveNaive(SourceLocation HashLoc,
39263982
static bool TokenListIsCharacterArray(Preprocessor &PP,
39273983
const size_t TargetCharWidth,
39283984
bool IsPrefix,
3929-
SmallVectorImpl<Token> &Tokens,
3985+
const SmallVectorImpl<Token> &Tokens,
39303986
llvm::SmallVectorImpl<char> &Output) {
39313987
const bool IsSuffix = !IsPrefix;
39323988
size_t MaxValue =
@@ -4032,7 +4088,7 @@ static void TripleEncodeBase64(StringRef Bytes0, StringRef Bytes1,
40324088
void Preprocessor::HandleEmbedDirectiveBuiltin(
40334089
SourceLocation HashLoc, const Token &FilenameTok,
40344090
StringRef ResolvedFilename, StringRef SearchPath, StringRef RelativePath,
4035-
LexEmbedParametersResult &Params, StringRef BinaryContents,
4091+
const LexEmbedParametersResult &Params, StringRef BinaryContents,
40364092
const size_t TargetCharWidth) {
40374093
// if it's empty, just process it like a normal expanded token stream
40384094
if (BinaryContents.empty()) {
@@ -4045,7 +4101,7 @@ void Preprocessor::HandleEmbedDirectiveBuiltin(
40454101
if (Params.MaybePrefixParam) {
40464102
// If we ahve a prefix, validate that it's a good fit for direct data
40474103
// embedded (and prepare to prepend it)
4048-
PPEmbedParameterPrefix &PrefixParam = *Params.MaybePrefixParam;
4104+
const PPEmbedParameterPrefix &PrefixParam = *Params.MaybePrefixParam;
40494105
if (!TokenListIsCharacterArray(*this, TargetCharWidth, true,
40504106
PrefixParam.Tokens, BinaryPrefix)) {
40514107
HandleEmbedDirectiveNaive(HashLoc, FilenameTok.getLocation(), Params,
@@ -4056,7 +4112,7 @@ void Preprocessor::HandleEmbedDirectiveBuiltin(
40564112
if (Params.MaybeSuffixParam) {
40574113
// If we ahve a prefix, validate that it's a good fit for direct data
40584114
// embedding (and prepare to append it)
4059-
PPEmbedParameterSuffix &SuffixParam = *Params.MaybeSuffixParam;
4115+
const PPEmbedParameterSuffix &SuffixParam = *Params.MaybeSuffixParam;
40604116
if (!TokenListIsCharacterArray(*this, TargetCharWidth, false,
40614117
SuffixParam.Tokens, BinarySuffix)) {
40624118
HandleEmbedDirectiveNaive(HashLoc, FilenameTok.getLocation(), Params,
@@ -4075,9 +4131,25 @@ void Preprocessor::HandleEmbedDirectiveBuiltin(
40754131
return PrefixNumber.concat(">");
40764132
}(EmbedBufferNumberVal);
40774133
std::string &TargetEmbedBuffer = EmbedBuffers.back();
4134+
StringRef TypeName = "unsigned char";
4135+
const size_t TotalSize =
4136+
BinaryPrefix.size() + BinaryContents.size() + BinarySuffix.size();
4137+
const size_t ReserveSize = // add up for necessary size:
4138+
19 // __builtin_pp_embed(
4139+
+ TypeName.size() // type-name
4140+
+ 2 // ,"
4141+
+ ResolvedFilename.size() // file-name
4142+
+ 3 // ","
4143+
+ (((TotalSize + 2) / 3) * 4) // base64-string
4144+
+ 2 // ");
4145+
;
4146+
// Reserve appropriate size
4147+
TargetEmbedBuffer.reserve(ReserveSize);
40784148

40794149
// Generate the look-alike source file
4080-
TargetEmbedBuffer.append("__builtin_pp_embed(unsigned char,\"");
4150+
TargetEmbedBuffer.append("__builtin_pp_embed(");
4151+
TargetEmbedBuffer.append(TypeName.data(), TypeName.size());
4152+
TargetEmbedBuffer.append(",\"");
40814153
TargetEmbedBuffer.append(ResolvedFilename.data(), ResolvedFilename.size());
40824154
TargetEmbedBuffer.append("\",\"");
40834155
// include the prefix(...) and suffix(...) binary data in the total contents

0 commit comments

Comments
 (0)