Skip to content

Commit 4d5b958

Browse files
committed
Split partial specializations from the lookup table
1 parent 493cb7c commit 4d5b958

File tree

9 files changed

+216
-142
lines changed

9 files changed

+216
-142
lines changed

clang/include/clang/AST/DeclTemplate.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -806,13 +806,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
806806
/// was explicitly specialized.
807807
llvm::PointerIntPair<RedeclarableTemplateDecl *, 1, bool>
808808
InstantiatedFromMember;
809-
810-
/// If non-null, points to an array of specializations (including
811-
/// partial specializations) known only by their external declaration IDs.
812-
///
813-
/// The first value in the array is the number of specializations/partial
814-
/// specializations that follow.
815-
LazySpecializationInfo *LazySpecializations = nullptr;
816809
};
817810

818811
/// Pointer to the common data shared by all declarations of this

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -737,8 +737,10 @@ enum ASTRecordTypes {
737737

738738
/// Record code for updated specialization
739739
UPDATE_SPECIALIZATION = 73,
740-
740+
741741
CXX_ADDED_TEMPLATE_SPECIALIZATION = 74,
742+
743+
CXX_ADDED_TEMPLATE_PARTIAL_SPECIALIZATION = 75,
742744
};
743745

744746
/// Record types used within a source manager block.
@@ -1505,11 +1507,14 @@ enum DeclCode {
15051507
/// A HLSLBufferDecl record.
15061508
DECL_HLSL_BUFFER,
15071509

1510+
/// An ImplicitConceptSpecializationDecl record.
1511+
DECL_IMPLICIT_CONCEPT_SPECIALIZATION,
1512+
15081513
// A decls specilization record.
15091514
DECL_SPECIALIZATIONS,
15101515

1511-
/// An ImplicitConceptSpecializationDecl record.
1512-
DECL_IMPLICIT_CONCEPT_SPECIALIZATION,
1516+
// A decls specilization record.
1517+
DECL_PARTIAL_SPECIALIZATIONS,
15131518

15141519
DECL_LAST = DECL_IMPLICIT_CONCEPT_SPECIALIZATION
15151520
};

clang/include/clang/Serialization/ASTReader.h

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,19 @@ class ASTReader
635635
llvm::DenseMap<const DeclContext *,
636636
serialization::reader::DeclContextLookupTable> Lookups;
637637

638+
using SpecLookupTableTy =
639+
llvm::DenseMap<const Decl *,
640+
serialization::reader::LazySpecializationInfoLookupTable>;
638641
/// Map from decls to specialized decls.
639-
llvm::DenseMap<const Decl *,
640-
serialization::reader::LazySpecializationInfoLookupTable>
641-
SpecializationsLookups;
642+
SpecLookupTableTy SpecializationsLookups;
643+
/// Split partial specialization from specialization to speed up lookups.
644+
SpecLookupTableTy PartialSpecializationsLookups;
645+
646+
bool LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups,
647+
const Decl *D);
648+
bool LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups,
649+
const Decl *D,
650+
ArrayRef<TemplateArgument> TemplateArgs);
642651

643652
// Updates for visible decls can occur for other contexts than just the
644653
// TU, and when we read those update records, the actual context may not
@@ -655,8 +664,10 @@ class ASTReader
655664
llvm::DenseMap<GlobalDeclID, DeclContextVisibleUpdates> PendingVisibleUpdates;
656665

657666
using SpecializationsUpdate = SmallVector<UpdateData, 1>;
658-
llvm::DenseMap<GlobalDeclID, SpecializationsUpdate>
659-
PendingSpecializationsUpdates;
667+
using SpecializationsUpdateMap =
668+
llvm::DenseMap<GlobalDeclID, SpecializationsUpdate>;
669+
SpecializationsUpdateMap PendingSpecializationsUpdates;
670+
SpecializationsUpdateMap PendingPartialSpecializationsUpdates;
660671

661672
/// The set of C++ or Objective-C classes that have forward
662673
/// declarations that have not yet been linked to their definitions.
@@ -691,9 +702,9 @@ class ASTReader
691702
uint64_t Offset, GlobalDeclID ID);
692703

693704
bool ReadSpecializations(ModuleFile &M, llvm::BitstreamCursor &Cursor,
694-
uint64_t Offset, Decl *D);
705+
uint64_t Offset, Decl *D, bool IsPartial);
695706
void AddSpecializations(const Decl *D, const unsigned char *Data,
696-
ModuleFile &M);
707+
ModuleFile &M, bool IsPartial);
697708

698709
/// A vector containing identifiers that have already been
699710
/// loaded.
@@ -1439,7 +1450,10 @@ class ASTReader
14391450
/// Get the loaded specializations lookup tables for \p D,
14401451
/// if any.
14411452
serialization::reader::LazySpecializationInfoLookupTable *
1442-
getLoadedSpecializationsLookupTables(const Decl *D);
1453+
getLoadedSpecializationsLookupTables(const Decl *D, bool IsPartial);
1454+
1455+
/// If we have any unloaded specialization for \p D
1456+
bool haveUnloadedSpecializations(const Decl *D) const;
14431457

14441458
private:
14451459
struct ImportedModule {

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ class ASTWriter : public ASTDeserializationListener,
428428
using SpecializationUpdateMap =
429429
llvm::MapVector<const NamedDecl *, SmallVector<const Decl *>>;
430430
SpecializationUpdateMap SpecializationsUpdates;
431+
SpecializationUpdateMap PartialSpecializationsUpdates;
431432

432433
using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>;
433434

@@ -580,9 +581,10 @@ class ASTWriter : public ASTDeserializationListener,
580581

581582
void GenerateSpecializationInfoLookupTable(
582583
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
583-
llvm::SmallVectorImpl<char> &LookupTable);
584+
llvm::SmallVectorImpl<char> &LookupTable, bool IsPartial);
584585
uint64_t WriteSpecializationInfoLookupTable(
585-
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations);
586+
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
587+
bool IsPartial);
586588
void GenerateNameLookupTable(ASTContext &Context, const DeclContext *DC,
587589
llvm::SmallVectorImpl<char> &LookupTable);
588590
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context,
@@ -598,7 +600,7 @@ class ASTWriter : public ASTDeserializationListener,
598600
void WriteDeclAndTypes(ASTContext &Context);
599601
void PrepareWritingSpecialDecls(Sema &SemaRef);
600602
void WriteSpecialDeclRecords(Sema &SemaRef);
601-
void WriteSpecializationsUpdates();
603+
void WriteSpecializationsUpdates(bool IsPartial);
602604
void WriteDeclUpdatesBlocks(ASTContext &Context,
603605
RecordDataImpl &OffsetsRecord);
604606
void WriteDeclContextVisibleUpdate(ASTContext &Context,
@@ -629,6 +631,7 @@ class ASTWriter : public ASTDeserializationListener,
629631
unsigned DeclObjCIvarAbbrev = 0;
630632
unsigned DeclCXXMethodAbbrev = 0;
631633
unsigned DeclSpecializationsAbbrev = 0;
634+
unsigned DeclPartialSpecializationsAbbrev = 0;
632635

633636
unsigned DeclDependentNonTemplateCXXMethodAbbrev = 0;
634637
unsigned DeclTemplateCXXMethodAbbrev = 0;

clang/lib/Serialization/ASTReader.cpp

Lines changed: 79 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,13 +1311,11 @@ void LazySpecializationInfoLookupTrait::ReadDataInto(internal_key_type,
13111311
using namespace llvm::support;
13121312

13131313
for (unsigned NumDecls =
1314-
DataLen / serialization::reader::LazySpecializationInfo::Length;
1314+
DataLen / sizeof(serialization::reader::LazySpecializationInfo);
13151315
NumDecls; --NumDecls) {
13161316
LocalDeclID LocalID =
13171317
LocalDeclID::get(Reader, F, endian::readNext<DeclID, llvm::endianness::little, unaligned>(d));
1318-
const bool IsPartial =
1319-
endian::readNext<bool, llvm::endianness::little, unaligned>(d);
1320-
Val.insert({Reader.getGlobalDeclID(F, LocalID), IsPartial});
1318+
Val.insert(Reader.getGlobalDeclID(F, LocalID));
13211319
}
13221320
}
13231321

@@ -1410,14 +1408,16 @@ bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M,
14101408
}
14111409

14121410
void ASTReader::AddSpecializations(const Decl *D, const unsigned char *Data,
1413-
ModuleFile &M) {
1411+
ModuleFile &M, bool IsPartial) {
14141412
D = D->getCanonicalDecl();
1415-
SpecializationsLookups[D].Table.add(
1416-
&M, Data, reader::LazySpecializationInfoLookupTrait(*this, M));
1413+
auto &SpecLookups =
1414+
IsPartial ? PartialSpecializationsLookups : SpecializationsLookups;
1415+
SpecLookups[D].Table.add(&M, Data,
1416+
reader::LazySpecializationInfoLookupTrait(*this, M));
14171417
}
14181418

14191419
bool ASTReader::ReadSpecializations(ModuleFile &M, BitstreamCursor &Cursor,
1420-
uint64_t Offset, Decl *D) {
1420+
uint64_t Offset, Decl *D, bool IsPartial) {
14211421
assert(Offset != 0);
14221422

14231423
SavedStreamPosition SavedPosition(Cursor);
@@ -1441,13 +1441,14 @@ bool ASTReader::ReadSpecializations(ModuleFile &M, BitstreamCursor &Cursor,
14411441
return true;
14421442
}
14431443
unsigned RecCode = MaybeRecCode.get();
1444-
if (RecCode != DECL_SPECIALIZATIONS) {
1444+
if (RecCode != DECL_SPECIALIZATIONS &&
1445+
RecCode != DECL_PARTIAL_SPECIALIZATIONS) {
14451446
Error("Expected decl specs block");
14461447
return true;
14471448
}
14481449

14491450
auto *Data = (const unsigned char *)Blob.data();
1450-
AddSpecializations(D, Data, M);
1451+
AddSpecializations(D, Data, M, IsPartial);
14511452
return false;
14521453
}
14531454

@@ -3556,6 +3557,19 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
35563557
break;
35573558
}
35583559

3560+
case CXX_ADDED_TEMPLATE_PARTIAL_SPECIALIZATION: {
3561+
unsigned Idx = 0;
3562+
GlobalDeclID ID = ReadDeclID(F, Record, Idx);
3563+
auto *Data = (const unsigned char *)Blob.data();
3564+
PendingPartialSpecializationsUpdates[ID].push_back(UpdateData{&F, Data});
3565+
// If we've already loaded the decl, perform the updates when we finish
3566+
// loading this block.
3567+
if (Decl *D = GetExistingDecl(ID))
3568+
PendingUpdateRecords.push_back(
3569+
PendingUpdateRecord(ID, D, /*JustLoaded=*/false));
3570+
break;
3571+
}
3572+
35593573
case IDENTIFIER_TABLE:
35603574
F.IdentifierTableData =
35613575
reinterpret_cast<const unsigned char *>(Blob.data());
@@ -8136,11 +8150,12 @@ Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
81368150
return ReadStmtFromStream(*Loc.F);
81378151
}
81388152

8139-
bool ASTReader::LoadExternalSpecializations(const Decl *D, bool OnlyPartial) {
8153+
bool ASTReader::LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups,
8154+
const Decl *D) {
81408155
assert(D);
81418156

8142-
auto It = SpecializationsLookups.find(D);
8143-
if (It == SpecializationsLookups.end())
8157+
auto It = SpecLookups.find(D);
8158+
if (It == SpecLookups.end())
81448159
return false;
81458160

81468161
// Get Decl may violate the iterator from SpecializationsLookups so we store
@@ -8150,48 +8165,71 @@ bool ASTReader::LoadExternalSpecializations(const Decl *D, bool OnlyPartial) {
81508165

81518166
// Since we've loaded all the specializations, we can erase it from
81528167
// the lookup table.
8153-
if (!OnlyPartial)
8154-
SpecializationsLookups.erase(It);
8168+
SpecLookups.erase(It);
81558169

81568170
bool NewSpecsFound = false;
81578171
Deserializing LookupResults(this);
8158-
for (auto &Info : Infos)
8159-
if (!OnlyPartial || Info.IsPartial) {
8160-
if (GetExistingDecl(Info.ID))
8161-
continue;
8162-
NewSpecsFound = true;
8163-
GetDecl(Info.ID);
8164-
}
8172+
for (auto &Info : Infos) {
8173+
if (GetExistingDecl(Info))
8174+
continue;
8175+
NewSpecsFound = true;
8176+
GetDecl(Info);
8177+
}
81658178

81668179
return NewSpecsFound;
81678180
}
81688181

8169-
bool ASTReader::LoadExternalSpecializations(
8170-
const Decl *D, ArrayRef<TemplateArgument> TemplateArgs) {
8182+
bool ASTReader::LoadExternalSpecializations(const Decl *D, bool OnlyPartial) {
81718183
assert(D);
81728184

8173-
auto It = SpecializationsLookups.find(D);
8174-
if (It == SpecializationsLookups.end())
8185+
bool NewSpecsFound =
8186+
LoadExternalSpecializationsImpl(PartialSpecializationsLookups, D);
8187+
if (OnlyPartial)
8188+
return NewSpecsFound;
8189+
8190+
NewSpecsFound |= LoadExternalSpecializationsImpl(SpecializationsLookups, D);
8191+
return NewSpecsFound;
8192+
}
8193+
8194+
bool ASTReader::LoadExternalSpecializationsImpl(
8195+
SpecLookupTableTy &SpecLookups, const Decl *D,
8196+
ArrayRef<TemplateArgument> TemplateArgs) {
8197+
assert(D);
8198+
8199+
auto It = SpecLookups.find(D);
8200+
if (It == SpecLookups.end())
81758201
return false;
81768202

81778203
Deserializing LookupResults(this);
81788204
auto HashValue = StableHashForTemplateArguments(TemplateArgs);
81798205

8180-
// Get Decl may violate the iterator from SpecializationsLookups
8206+
// Get Decl may violate the iterator from SpecLookups
81818207
llvm::SmallVector<serialization::reader::LazySpecializationInfo, 8> Infos =
81828208
It->second.Table.find(HashValue);
81838209

81848210
bool NewSpecsFound = false;
81858211
for (auto &Info : Infos) {
8186-
if (GetExistingDecl(Info.ID))
8212+
if (GetExistingDecl(Info))
81878213
continue;
81888214
NewSpecsFound = true;
8189-
GetDecl(Info.ID);
8215+
GetDecl(Info);
81908216
}
81918217

81928218
return NewSpecsFound;
81938219
}
81948220

8221+
bool ASTReader::LoadExternalSpecializations(
8222+
const Decl *D, ArrayRef<TemplateArgument> TemplateArgs) {
8223+
assert(D);
8224+
8225+
bool NewDeclsFound = LoadExternalSpecializationsImpl(
8226+
PartialSpecializationsLookups, D, TemplateArgs);
8227+
NewDeclsFound |=
8228+
LoadExternalSpecializationsImpl(SpecializationsLookups, D, TemplateArgs);
8229+
8230+
return NewDeclsFound;
8231+
}
8232+
81958233
void ASTReader::FindExternalLexicalDecls(
81968234
const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
81978235
SmallVectorImpl<Decl *> &Decls) {
@@ -8372,10 +8410,19 @@ ASTReader::getLoadedLookupTables(DeclContext *Primary) const {
83728410
}
83738411

83748412
serialization::reader::LazySpecializationInfoLookupTable *
8375-
ASTReader::getLoadedSpecializationsLookupTables(const Decl *D) {
8413+
ASTReader::getLoadedSpecializationsLookupTables(const Decl *D, bool IsPartial) {
8414+
assert(D->isCanonicalDecl());
8415+
auto &LookupTable =
8416+
IsPartial ? PartialSpecializationsLookups : SpecializationsLookups;
8417+
auto I = LookupTable.find(D);
8418+
return I == LookupTable.end() ? nullptr : &I->second;
8419+
}
8420+
8421+
bool ASTReader::haveUnloadedSpecializations(const Decl *D) const {
83768422
assert(D->isCanonicalDecl());
8377-
auto I = SpecializationsLookups.find(D);
8378-
return I == SpecializationsLookups.end() ? nullptr : &I->second;
8423+
return (PartialSpecializationsLookups.find(D) !=
8424+
PartialSpecializationsLookups.end()) ||
8425+
(SpecializationsLookups.find(D) != SpecializationsLookups.end());
83798426
}
83808427

83818428
/// Under non-PCH compilation the consumer receives the objc methods

0 commit comments

Comments
 (0)