Skip to content

Commit c5f402f

Browse files
authored
[APINotes] Reduce memory footprint for Obj-C/C++ contexts
We were storing extraneous data for certain Objective-C/C++ entities. Specifically, for declarations that can be nested in another context (such as functions) we were storing the kind of the parent context in addition to its ID. The ID is always sufficient. This removes the logically incorrect usages of `ContextTableKey` that don't actually describe a context, but rather describe a single declaration. This introduces `SingleDeclTableKey` to store that kind of entities in a more compact and reasonable way.
1 parent bf02f41 commit c5f402f

File tree

3 files changed

+84
-51
lines changed

3 files changed

+84
-51
lines changed

clang/lib/APINotes/APINotesFormat.h

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0;
2424
/// API notes file minor version number.
2525
///
2626
/// When the format changes IN ANY WAY, this number should be incremented.
27-
const uint16_t VERSION_MINOR = 26; // SwiftCopyable
27+
const uint16_t VERSION_MINOR = 27; // SingleDeclTableKey
2828

2929
const uint8_t kSwiftCopyable = 1;
3030
const uint8_t kSwiftNonCopyable = 2;
@@ -269,12 +269,6 @@ struct ContextTableKey {
269269
: parentContextID(parentContextID), contextKind(contextKind),
270270
contextID(contextID) {}
271271

272-
ContextTableKey(std::optional<Context> context, IdentifierID nameID)
273-
: parentContextID(context ? context->id.Value : (uint32_t)-1),
274-
contextKind(context ? static_cast<uint8_t>(context->kind)
275-
: static_cast<uint8_t>(-1)),
276-
contextID(nameID) {}
277-
278272
llvm::hash_code hashValue() const {
279273
return llvm::hash_value(
280274
std::tuple{parentContextID, contextKind, contextID});
@@ -286,6 +280,32 @@ inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) {
286280
lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID;
287281
}
288282

283+
/// A stored Objective-C or C++ declaration, represented by the ID of its parent
284+
/// context, and the name of the declaration.
285+
struct SingleDeclTableKey {
286+
uint32_t parentContextID;
287+
uint32_t nameID;
288+
289+
SingleDeclTableKey() : parentContextID(-1), nameID(-1) {}
290+
291+
SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID)
292+
: parentContextID(ParentContextID), nameID(NameID) {}
293+
294+
SingleDeclTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)
295+
: parentContextID(ParentCtx ? ParentCtx->id.Value
296+
: static_cast<uint32_t>(-1)),
297+
nameID(NameID) {}
298+
299+
llvm::hash_code hashValue() const {
300+
return llvm::hash_value(std::make_pair(parentContextID, nameID));
301+
}
302+
};
303+
304+
inline bool operator==(const SingleDeclTableKey &lhs,
305+
const SingleDeclTableKey &rhs) {
306+
return lhs.parentContextID == rhs.parentContextID && lhs.nameID == rhs.nameID;
307+
}
308+
289309
} // namespace api_notes
290310
} // namespace clang
291311

@@ -341,6 +361,29 @@ template <> struct DenseMapInfo<clang::api_notes::ContextTableKey> {
341361
return lhs == rhs;
342362
}
343363
};
364+
365+
template <> struct DenseMapInfo<clang::api_notes::SingleDeclTableKey> {
366+
static inline clang::api_notes::SingleDeclTableKey getEmptyKey() {
367+
return clang::api_notes::SingleDeclTableKey();
368+
}
369+
370+
static inline clang::api_notes::SingleDeclTableKey getTombstoneKey() {
371+
return clang::api_notes::SingleDeclTableKey{
372+
DenseMapInfo<uint32_t>::getTombstoneKey(),
373+
DenseMapInfo<uint32_t>::getTombstoneKey()};
374+
}
375+
376+
static unsigned
377+
getHashValue(const clang::api_notes::SingleDeclTableKey &value) {
378+
return value.hashValue();
379+
}
380+
381+
static bool isEqual(const clang::api_notes::SingleDeclTableKey &lhs,
382+
const clang::api_notes::SingleDeclTableKey &rhs) {
383+
return lhs == rhs;
384+
}
385+
};
386+
344387
} // namespace llvm
345388

346389
#endif

clang/lib/APINotes/APINotesReader.cpp

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -429,15 +429,13 @@ class ObjCSelectorTableInfo {
429429

430430
/// Used to deserialize the on-disk global variable table.
431431
class GlobalVariableTableInfo
432-
: public VersionedTableInfo<GlobalVariableTableInfo, ContextTableKey,
432+
: public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
433433
GlobalVariableInfo> {
434434
public:
435435
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
436436
auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
437-
auto ContextKind =
438-
endian::readNext<uint8_t, llvm::endianness::little>(Data);
439437
auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
440-
return {CtxID, ContextKind, NameID};
438+
return {CtxID, NameID};
441439
}
442440

443441
hash_value_type ComputeHash(internal_key_type Key) {
@@ -454,15 +452,13 @@ class GlobalVariableTableInfo
454452

455453
/// Used to deserialize the on-disk global function table.
456454
class GlobalFunctionTableInfo
457-
: public VersionedTableInfo<GlobalFunctionTableInfo, ContextTableKey,
455+
: public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
458456
GlobalFunctionInfo> {
459457
public:
460458
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
461459
auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
462-
auto ContextKind =
463-
endian::readNext<uint8_t, llvm::endianness::little>(Data);
464460
auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
465-
return {CtxID, ContextKind, NameID};
461+
return {CtxID, NameID};
466462
}
467463

468464
hash_value_type ComputeHash(internal_key_type Key) {
@@ -501,15 +497,13 @@ class EnumConstantTableInfo
501497

502498
/// Used to deserialize the on-disk tag table.
503499
class TagTableInfo
504-
: public VersionedTableInfo<TagTableInfo, ContextTableKey, TagInfo> {
500+
: public VersionedTableInfo<TagTableInfo, SingleDeclTableKey, TagInfo> {
505501
public:
506502
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
507503
auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
508-
auto ContextKind =
509-
endian::readNext<uint8_t, llvm::endianness::little>(Data);
510504
auto NameID =
511505
endian::readNext<IdentifierID, llvm::endianness::little>(Data);
512-
return {CtxID, ContextKind, NameID};
506+
return {CtxID, NameID};
513507
}
514508

515509
hash_value_type ComputeHash(internal_key_type Key) {
@@ -563,16 +557,14 @@ class TagTableInfo
563557

564558
/// Used to deserialize the on-disk typedef table.
565559
class TypedefTableInfo
566-
: public VersionedTableInfo<TypedefTableInfo, ContextTableKey,
560+
: public VersionedTableInfo<TypedefTableInfo, SingleDeclTableKey,
567561
TypedefInfo> {
568562
public:
569563
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
570564
auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
571-
auto ContextKind =
572-
endian::readNext<uint8_t, llvm::endianness::little>(Data);
573565
auto nameID =
574566
endian::readNext<IdentifierID, llvm::endianness::little>(Data);
575-
return {CtxID, ContextKind, nameID};
567+
return {CtxID, nameID};
576568
}
577569

578570
hash_value_type ComputeHash(internal_key_type Key) {
@@ -1929,7 +1921,7 @@ auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name,
19291921
if (!NameID)
19301922
return std::nullopt;
19311923

1932-
ContextTableKey Key(Ctx, *NameID);
1924+
SingleDeclTableKey Key(Ctx, *NameID);
19331925

19341926
auto Known = Implementation->GlobalVariableTable->find(Key);
19351927
if (Known == Implementation->GlobalVariableTable->end())
@@ -1948,7 +1940,7 @@ auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name,
19481940
if (!NameID)
19491941
return std::nullopt;
19501942

1951-
ContextTableKey Key(Ctx, *NameID);
1943+
SingleDeclTableKey Key(Ctx, *NameID);
19521944

19531945
auto Known = Implementation->GlobalFunctionTable->find(Key);
19541946
if (Known == Implementation->GlobalFunctionTable->end())
@@ -1982,7 +1974,7 @@ auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
19821974
if (!NameID)
19831975
return std::nullopt;
19841976

1985-
ContextTableKey Key(Ctx, *NameID);
1977+
SingleDeclTableKey Key(Ctx, *NameID);
19861978

19871979
auto Known = Implementation->TagTable->find(Key);
19881980
if (Known == Implementation->TagTable->end())
@@ -2001,7 +1993,7 @@ auto APINotesReader::lookupTypedef(llvm::StringRef Name,
20011993
if (!NameID)
20021994
return std::nullopt;
20031995

2004-
ContextTableKey Key(Ctx, *NameID);
1996+
SingleDeclTableKey Key(Ctx, *NameID);
20051997

20061998
auto Known = Implementation->TypedefTable->find(Key);
20071999
if (Known == Implementation->TypedefTable->end())

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,17 @@ class APINotesWriter::Implementation {
7575

7676
/// Information about global variables.
7777
///
78-
/// Indexed by the context ID, contextKind, identifier ID.
78+
/// Indexed by the context ID, identifier ID.
7979
llvm::DenseMap<
80-
ContextTableKey,
80+
SingleDeclTableKey,
8181
llvm::SmallVector<std::pair<VersionTuple, GlobalVariableInfo>, 1>>
8282
GlobalVariables;
8383

8484
/// Information about global functions.
8585
///
86-
/// Indexed by the context ID, contextKind, identifier ID.
86+
/// Indexed by the context ID, identifier ID.
8787
llvm::DenseMap<
88-
ContextTableKey,
88+
SingleDeclTableKey,
8989
llvm::SmallVector<std::pair<VersionTuple, GlobalFunctionInfo>, 1>>
9090
GlobalFunctions;
9191

@@ -98,15 +98,15 @@ class APINotesWriter::Implementation {
9898

9999
/// Information about tags.
100100
///
101-
/// Indexed by the context ID, contextKind, identifier ID.
102-
llvm::DenseMap<ContextTableKey,
101+
/// Indexed by the context ID, identifier ID.
102+
llvm::DenseMap<SingleDeclTableKey,
103103
llvm::SmallVector<std::pair<VersionTuple, TagInfo>, 1>>
104104
Tags;
105105

106106
/// Information about typedefs.
107107
///
108-
/// Indexed by the context ID, contextKind, identifier ID.
109-
llvm::DenseMap<ContextTableKey,
108+
/// Indexed by the context ID, identifier ID.
109+
llvm::DenseMap<SingleDeclTableKey,
110110
llvm::SmallVector<std::pair<VersionTuple, TypedefInfo>, 1>>
111111
Typedefs;
112112

@@ -865,18 +865,17 @@ void APINotesWriter::Implementation::writeObjCSelectorBlock(
865865
namespace {
866866
/// Used to serialize the on-disk global variable table.
867867
class GlobalVariableTableInfo
868-
: public VersionedTableInfo<GlobalVariableTableInfo, ContextTableKey,
868+
: public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
869869
GlobalVariableInfo> {
870870
public:
871871
unsigned getKeyLength(key_type_ref) {
872-
return sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
872+
return sizeof(uint32_t) + sizeof(uint32_t);
873873
}
874874

875875
void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
876876
llvm::support::endian::Writer writer(OS, llvm::endianness::little);
877877
writer.write<uint32_t>(Key.parentContextID);
878-
writer.write<uint8_t>(Key.contextKind);
879-
writer.write<uint32_t>(Key.contextID);
878+
writer.write<uint32_t>(Key.nameID);
880879
}
881880

882881
hash_value_type ComputeHash(key_type_ref Key) {
@@ -979,18 +978,17 @@ void emitFunctionInfo(raw_ostream &OS, const FunctionInfo &FI) {
979978

980979
/// Used to serialize the on-disk global function table.
981980
class GlobalFunctionTableInfo
982-
: public VersionedTableInfo<GlobalFunctionTableInfo, ContextTableKey,
981+
: public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
983982
GlobalFunctionInfo> {
984983
public:
985984
unsigned getKeyLength(key_type_ref) {
986-
return sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
985+
return sizeof(uint32_t) + sizeof(uint32_t);
987986
}
988987

989988
void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
990989
llvm::support::endian::Writer writer(OS, llvm::endianness::little);
991990
writer.write<uint32_t>(Key.parentContextID);
992-
writer.write<uint8_t>(Key.contextKind);
993-
writer.write<uint32_t>(Key.contextID);
991+
writer.write<uint32_t>(Key.nameID);
994992
}
995993

996994
hash_value_type ComputeHash(key_type_ref Key) {
@@ -1091,20 +1089,20 @@ void APINotesWriter::Implementation::writeEnumConstantBlock(
10911089
namespace {
10921090
template <typename Derived, typename UnversionedDataType>
10931091
class CommonTypeTableInfo
1094-
: public VersionedTableInfo<Derived, ContextTableKey, UnversionedDataType> {
1092+
: public VersionedTableInfo<Derived, SingleDeclTableKey,
1093+
UnversionedDataType> {
10951094
public:
10961095
using key_type_ref = typename CommonTypeTableInfo::key_type_ref;
10971096
using hash_value_type = typename CommonTypeTableInfo::hash_value_type;
10981097

10991098
unsigned getKeyLength(key_type_ref) {
1100-
return sizeof(uint32_t) + sizeof(uint8_t) + sizeof(IdentifierID);
1099+
return sizeof(uint32_t) + sizeof(IdentifierID);
11011100
}
11021101

11031102
void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
11041103
llvm::support::endian::Writer writer(OS, llvm::endianness::little);
11051104
writer.write<uint32_t>(Key.parentContextID);
1106-
writer.write<uint8_t>(Key.contextKind);
1107-
writer.write<IdentifierID>(Key.contextID);
1105+
writer.write<IdentifierID>(Key.nameID);
11081106
}
11091107

11101108
hash_value_type ComputeHash(key_type_ref Key) {
@@ -1351,7 +1349,7 @@ void APINotesWriter::addGlobalVariable(std::optional<Context> Ctx,
13511349
const GlobalVariableInfo &Info,
13521350
VersionTuple SwiftVersion) {
13531351
IdentifierID VariableID = Implementation->getIdentifier(Name);
1354-
ContextTableKey Key(Ctx, VariableID);
1352+
SingleDeclTableKey Key(Ctx, VariableID);
13551353
Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
13561354
}
13571355

@@ -1360,7 +1358,7 @@ void APINotesWriter::addGlobalFunction(std::optional<Context> Ctx,
13601358
const GlobalFunctionInfo &Info,
13611359
VersionTuple SwiftVersion) {
13621360
IdentifierID NameID = Implementation->getIdentifier(Name);
1363-
ContextTableKey Key(Ctx, NameID);
1361+
SingleDeclTableKey Key(Ctx, NameID);
13641362
Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
13651363
}
13661364

@@ -1374,15 +1372,15 @@ void APINotesWriter::addEnumConstant(llvm::StringRef Name,
13741372
void APINotesWriter::addTag(std::optional<Context> Ctx, llvm::StringRef Name,
13751373
const TagInfo &Info, VersionTuple SwiftVersion) {
13761374
IdentifierID TagID = Implementation->getIdentifier(Name);
1377-
ContextTableKey Key(Ctx, TagID);
1375+
SingleDeclTableKey Key(Ctx, TagID);
13781376
Implementation->Tags[Key].push_back({SwiftVersion, Info});
13791377
}
13801378

13811379
void APINotesWriter::addTypedef(std::optional<Context> Ctx,
13821380
llvm::StringRef Name, const TypedefInfo &Info,
13831381
VersionTuple SwiftVersion) {
13841382
IdentifierID TypedefID = Implementation->getIdentifier(Name);
1385-
ContextTableKey Key(Ctx, TypedefID);
1383+
SingleDeclTableKey Key(Ctx, TypedefID);
13861384
Implementation->Typedefs[Key].push_back({SwiftVersion, Info});
13871385
}
13881386
} // namespace api_notes

0 commit comments

Comments
 (0)