Skip to content

Commit 96b7d1f

Browse files
committed
[clang][lex] Remove HeaderFileInfo::Framework (llvm#114460)
This PR removes the `HeaderFileInfo::Framework` member and reduces the size of this data type from 32B to 16B. This should improve Clang's memory usage in situations where it keeps track of lots of header files. NFCI. Depends on llvm#114459. (cherry picked from commit e494e26)
1 parent c1c9966 commit 96b7d1f

File tree

8 files changed

+38
-96
lines changed

8 files changed

+38
-96
lines changed

clang-tools-extra/clangd/index/SymbolCollector.cpp

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,10 @@ class SymbolCollector::HeaderFileURICache {
290290
}
291291

292292
struct FrameworkHeaderPath {
293-
// Path to the framework directory containing the Headers/PrivateHeaders
294-
// directories e.g. /Frameworks/Foundation.framework/
295-
llvm::StringRef HeadersParentDir;
293+
// Path to the frameworks directory containing the .framework directory.
294+
llvm::StringRef FrameworkParentDir;
295+
// Name of the framework.
296+
llvm::StringRef FrameworkName;
296297
// Subpath relative to the Headers or PrivateHeaders dir, e.g. NSObject.h
297298
// Note: This is NOT relative to the `HeadersParentDir`.
298299
llvm::StringRef HeaderSubpath;
@@ -306,19 +307,17 @@ class SymbolCollector::HeaderFileURICache {
306307
path::reverse_iterator I = path::rbegin(Path);
307308
path::reverse_iterator Prev = I;
308309
path::reverse_iterator E = path::rend(Path);
310+
FrameworkHeaderPath HeaderPath;
309311
while (I != E) {
310-
if (*I == "Headers") {
311-
FrameworkHeaderPath HeaderPath;
312-
HeaderPath.HeadersParentDir = Path.substr(0, I - E);
312+
if (*I == "Headers" || *I == "PrivateHeaders") {
313313
HeaderPath.HeaderSubpath = Path.substr(Prev - E);
314-
HeaderPath.IsPrivateHeader = false;
315-
return HeaderPath;
316-
}
317-
if (*I == "PrivateHeaders") {
318-
FrameworkHeaderPath HeaderPath;
319-
HeaderPath.HeadersParentDir = Path.substr(0, I - E);
320-
HeaderPath.HeaderSubpath = Path.substr(Prev - E);
321-
HeaderPath.IsPrivateHeader = true;
314+
HeaderPath.IsPrivateHeader = *I == "PrivateHeaders";
315+
if (++I == E)
316+
break;
317+
HeaderPath.FrameworkName = *I;
318+
if (!HeaderPath.FrameworkName.consume_back(".framework"))
319+
break;
320+
HeaderPath.FrameworkParentDir = Path.substr(0, I - E);
322321
return HeaderPath;
323322
}
324323
Prev = I;
@@ -334,26 +333,27 @@ class SymbolCollector::HeaderFileURICache {
334333
// <Foundation/NSObject_Private.h> which should be used instead of directly
335334
// importing the header.
336335
std::optional<std::string>
337-
getFrameworkUmbrellaSpelling(llvm::StringRef Framework,
338-
const HeaderSearch &HS,
336+
getFrameworkUmbrellaSpelling(const HeaderSearch &HS,
339337
FrameworkHeaderPath &HeaderPath) {
338+
StringRef Framework = HeaderPath.FrameworkName;
340339
auto Res = CacheFrameworkToUmbrellaHeaderSpelling.try_emplace(Framework);
341340
auto *CachedSpelling = &Res.first->second;
342341
if (!Res.second) {
343342
return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader
344343
: CachedSpelling->PublicHeader;
345344
}
346-
SmallString<256> UmbrellaPath(HeaderPath.HeadersParentDir);
347-
llvm::sys::path::append(UmbrellaPath, "Headers", Framework + ".h");
345+
SmallString<256> UmbrellaPath(HeaderPath.FrameworkParentDir);
346+
llvm::sys::path::append(UmbrellaPath, Framework + ".framework", "Headers",
347+
Framework + ".h");
348348

349349
llvm::vfs::Status Status;
350350
auto StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
351351
if (!StatErr)
352352
CachedSpelling->PublicHeader = llvm::formatv("<{0}/{0}.h>", Framework);
353353

354-
UmbrellaPath = HeaderPath.HeadersParentDir;
355-
llvm::sys::path::append(UmbrellaPath, "PrivateHeaders",
356-
Framework + "_Private.h");
354+
UmbrellaPath = HeaderPath.FrameworkParentDir;
355+
llvm::sys::path::append(UmbrellaPath, Framework + ".framework",
356+
"PrivateHeaders", Framework + "_Private.h");
357357

358358
StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
359359
if (!StatErr)
@@ -369,8 +369,7 @@ class SymbolCollector::HeaderFileURICache {
369369
// give <Foundation/Foundation.h> if the umbrella header exists, otherwise
370370
// <Foundation/NSObject.h>.
371371
std::optional<llvm::StringRef>
372-
getFrameworkHeaderIncludeSpelling(FileEntryRef FE, llvm::StringRef Framework,
373-
HeaderSearch &HS) {
372+
getFrameworkHeaderIncludeSpelling(FileEntryRef FE, HeaderSearch &HS) {
374373
auto Res = CachePathToFrameworkSpelling.try_emplace(FE.getName());
375374
auto *CachedHeaderSpelling = &Res.first->second;
376375
if (!Res.second)
@@ -384,13 +383,15 @@ class SymbolCollector::HeaderFileURICache {
384383
return std::nullopt;
385384
}
386385
if (auto UmbrellaSpelling =
387-
getFrameworkUmbrellaSpelling(Framework, HS, *HeaderPath)) {
386+
getFrameworkUmbrellaSpelling(HS, *HeaderPath)) {
388387
*CachedHeaderSpelling = *UmbrellaSpelling;
389388
return llvm::StringRef(*CachedHeaderSpelling);
390389
}
391390

392391
*CachedHeaderSpelling =
393-
llvm::formatv("<{0}/{1}>", Framework, HeaderPath->HeaderSubpath).str();
392+
llvm::formatv("<{0}/{1}>", HeaderPath->FrameworkName,
393+
HeaderPath->HeaderSubpath)
394+
.str();
394395
return llvm::StringRef(*CachedHeaderSpelling);
395396
}
396397

@@ -409,11 +410,8 @@ class SymbolCollector::HeaderFileURICache {
409410
// Framework headers are spelled as <FrameworkName/Foo.h>, not
410411
// "path/FrameworkName.framework/Headers/Foo.h".
411412
auto &HS = PP->getHeaderSearchInfo();
412-
if (const auto *HFI = HS.getExistingFileInfo(*FE))
413-
if (!HFI->Framework.empty())
414-
if (auto Spelling =
415-
getFrameworkHeaderIncludeSpelling(*FE, HFI->Framework, HS))
416-
return *Spelling;
413+
if (auto Spelling = getFrameworkHeaderIncludeSpelling(*FE, HS))
414+
return *Spelling;
417415

418416
if (!tooling::isSelfContainedHeader(*FE, PP->getSourceManager(),
419417
PP->getHeaderSearchInfo())) {

clang/include/clang/Lex/HeaderSearch.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,6 @@ struct HeaderFileInfo {
122122
/// external storage.
123123
LazyIdentifierInfoPtr LazyControllingMacro;
124124

125-
/// If this header came from a framework include, this is the name
126-
/// of the framework.
127-
StringRef Framework;
128-
129125
HeaderFileInfo()
130126
: IsLocallyIncluded(false), isImport(false), isPragmaOnce(false),
131127
DirInfo(SrcMgr::C_User), External(false), isModuleHeader(false),
@@ -144,6 +140,8 @@ struct HeaderFileInfo {
144140
void mergeModuleMembership(ModuleMap::ModuleHeaderRole Role);
145141
};
146142

143+
static_assert(sizeof(HeaderFileInfo) <= 16);
144+
147145
/// An external source of header file information, which may supply
148146
/// information about header files already included.
149147
class ExternalHeaderFileInfoSource {

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ namespace serialization {
4444
/// Version 4 of AST files also requires that the version control branch and
4545
/// revision match exactly, since there is no backward compatibility of
4646
/// AST files at this time.
47-
const unsigned VERSION_MAJOR = 32;
47+
const unsigned VERSION_MAJOR = 33;
4848

4949
/// AST file minor version number supported by this version of
5050
/// Clang.

clang/lib/Lex/HeaderSearch.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -973,11 +973,9 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
973973
const HeaderFileInfo *FromHFI = getExistingFileInfo(*Includer);
974974
assert(FromHFI && "includer without file info");
975975
unsigned DirInfo = FromHFI->DirInfo;
976-
StringRef Framework = FromHFI->Framework;
977976

978977
HeaderFileInfo &ToHFI = getFileInfo(*FE);
979978
ToHFI.DirInfo = DirInfo;
980-
ToHFI.Framework = Framework;
981979

982980
if (SearchPath) {
983981
StringRef SearchPathRef(IncluderAndDir.second.getName());
@@ -1119,16 +1117,6 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
11191117
}
11201118
}
11211119

1122-
// Set the `Framework` info if this file is in a header map with framework
1123-
// style include spelling or found in a framework dir. The header map case
1124-
// is possible when building frameworks which use header maps.
1125-
if ((CurDir->isHeaderMap() && isAngled) || CurDir->isFramework()) {
1126-
size_t SlashPos = Filename.find('/');
1127-
if (SlashPos != StringRef::npos)
1128-
HFI.Framework =
1129-
getUniqueFrameworkName(StringRef(Filename.begin(), SlashPos));
1130-
}
1131-
11321120
if (checkMSVCHeaderSearch(Diags, MSFE, &File->getFileEntry(), IncludeLoc)) {
11331121
if (SuggestedModule)
11341122
*SuggestedModule = MSSuggestedModule;
@@ -1313,9 +1301,6 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
13131301
HFI.DirInfo = OtherHFI.DirInfo;
13141302
HFI.External = (!HFI.IsValid || HFI.External);
13151303
HFI.IsValid = true;
1316-
1317-
if (HFI.Framework.empty())
1318-
HFI.Framework = OtherHFI.Framework;
13191304
}
13201305

13211306
HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) {

clang/lib/Serialization/ASTReader.cpp

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,13 +2111,6 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
21112111
HFI.DirInfo = (Flags >> 1) & 0x07;
21122112
HFI.LazyControllingMacro = Reader.getGlobalIdentifierID(
21132113
M, endian::readNext<IdentifierID, llvm::endianness::little>(d));
2114-
if (unsigned FrameworkOffset =
2115-
endian::readNext<uint32_t, llvm::endianness::little>(d)) {
2116-
// The framework offset is 1 greater than the actual offset,
2117-
// since 0 is used as an indicator for "no framework name".
2118-
StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
2119-
HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
2120-
}
21212114

21222115
assert((End - d) % 4 == 0 &&
21232116
"Wrong data length in HeaderFileInfo deserialization");
@@ -3894,13 +3887,10 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
38943887
F.HeaderFileInfoTableData = Blob.data();
38953888
F.LocalNumHeaderFileInfos = Record[1];
38963889
if (Record[0]) {
3897-
F.HeaderFileInfoTable
3898-
= HeaderFileInfoLookupTable::Create(
3899-
(const unsigned char *)F.HeaderFileInfoTableData + Record[0],
3900-
(const unsigned char *)F.HeaderFileInfoTableData,
3901-
HeaderFileInfoTrait(*this, F,
3902-
&PP.getHeaderSearchInfo(),
3903-
Blob.data() + Record[2]));
3890+
F.HeaderFileInfoTable = HeaderFileInfoLookupTable::Create(
3891+
(const unsigned char *)F.HeaderFileInfoTableData + Record[0],
3892+
(const unsigned char *)F.HeaderFileInfoTableData,
3893+
HeaderFileInfoTrait(*this, F));
39043894

39053895
PP.getHeaderSearchInfo().SetExternalSource(this);
39063896
if (!PP.getHeaderSearchInfo().getExternalLookup())

clang/lib/Serialization/ASTReaderInternals.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,6 @@ using ASTSelectorLookupTable =
243243
class HeaderFileInfoTrait {
244244
ASTReader &Reader;
245245
ModuleFile &M;
246-
HeaderSearch *HS;
247-
const char *FrameworkStrings;
248246

249247
public:
250248
using external_key_type = FileEntryRef;
@@ -262,9 +260,8 @@ class HeaderFileInfoTrait {
262260
using hash_value_type = unsigned;
263261
using offset_type = unsigned;
264262

265-
HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS,
266-
const char *FrameworkStrings)
267-
: Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) {}
263+
HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M)
264+
: Reader(Reader), M(M) {}
268265

269266
static hash_value_type ComputeHash(internal_key_ref ikey);
270267
internal_key_type GetInternalKey(external_key_type ekey);

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,10 +1988,6 @@ namespace {
19881988
class HeaderFileInfoTrait {
19891989
ASTWriter &Writer;
19901990

1991-
// Keep track of the framework names we've used during serialization.
1992-
SmallString<128> FrameworkStringData;
1993-
llvm::StringMap<unsigned> FrameworkNameOffset;
1994-
19951991
public:
19961992
HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {}
19971993

@@ -2035,7 +2031,7 @@ namespace {
20352031
std::pair<unsigned, unsigned>
20362032
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
20372033
unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;
2038-
unsigned DataLen = 1 + sizeof(IdentifierID) + 4;
2034+
unsigned DataLen = 1 + sizeof(IdentifierID);
20392035
for (auto ModInfo : Data.KnownHeaders)
20402036
if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))
20412037
DataLen += 4;
@@ -2075,22 +2071,6 @@ namespace {
20752071
LE.write<IdentifierID>(
20762072
Writer.getIdentifierRef(Data.HFI.LazyControllingMacro.getPtr()));
20772073

2078-
unsigned Offset = 0;
2079-
if (!Data.HFI.Framework.empty()) {
2080-
// If this header refers into a framework, save the framework name.
2081-
llvm::StringMap<unsigned>::iterator Pos
2082-
= FrameworkNameOffset.find(Data.HFI.Framework);
2083-
if (Pos == FrameworkNameOffset.end()) {
2084-
Offset = FrameworkStringData.size() + 1;
2085-
FrameworkStringData.append(Data.HFI.Framework);
2086-
FrameworkStringData.push_back(0);
2087-
2088-
FrameworkNameOffset[Data.HFI.Framework] = Offset;
2089-
} else
2090-
Offset = Pos->second;
2091-
}
2092-
LE.write<uint32_t>(Offset);
2093-
20942074
auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) {
20952075
if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) {
20962076
uint32_t Value = (ModID << 3) | (unsigned)Role;
@@ -2106,9 +2086,6 @@ namespace {
21062086

21072087
assert(Out.tell() - Start == DataLen && "Wrong data length");
21082088
}
2109-
2110-
const char *strings_begin() const { return FrameworkStringData.begin(); }
2111-
const char *strings_end() const { return FrameworkStringData.end(); }
21122089
};
21132090

21142091
} // namespace
@@ -2243,7 +2220,6 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
22432220
// Write the header search table
22442221
RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset,
22452222
NumHeaderSearchEntries, TableData.size()};
2246-
TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end());
22472223
Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData);
22482224

22492225
// Free all of the strings we had to duplicate.

clang/unittests/Lex/HeaderSearchTest.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ TEST_F(HeaderSearchTest, HeaderFrameworkLookup) {
250250
auto FI = Search.getExistingFileInfo(FE);
251251
EXPECT_TRUE(FI);
252252
EXPECT_TRUE(FI->IsValid);
253-
EXPECT_EQ(FI->Framework.str(), "Foo");
254253
EXPECT_EQ(Search.getIncludeNameForHeader(FE), "Foo/Foo.h");
255254
}
256255

@@ -320,7 +319,6 @@ TEST_F(HeaderSearchTest, HeaderMapFrameworkLookup) {
320319
auto FI = Search.getExistingFileInfo(FE);
321320
EXPECT_TRUE(FI);
322321
EXPECT_TRUE(FI->IsValid);
323-
EXPECT_EQ(FI->Framework.str(), "Foo");
324322
EXPECT_EQ(Search.getIncludeNameForHeader(FE), "Foo/Foo.h");
325323
}
326324

0 commit comments

Comments
 (0)