Skip to content

Commit e975c2e

Browse files
committed
Split partial specializations from the lookup table
1 parent 3b60dc2 commit e975c2e

File tree

9 files changed

+192
-134
lines changed

9 files changed

+192
-134
lines changed

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,8 @@ enum ASTRecordTypes {
739739
UPDATE_SPECIALIZATION = 73,
740740

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: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -634,10 +634,16 @@ class ASTReader
634634
llvm::DenseMap<const DeclContext *,
635635
serialization::reader::DeclContextLookupTable> Lookups;
636636

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

642648
// Updates for visible decls can occur for other contexts than just the
643649
// TU, and when we read those update records, the actual context may not
@@ -654,8 +660,9 @@ class ASTReader
654660
llvm::DenseMap<GlobalDeclID, DeclContextVisibleUpdates> PendingVisibleUpdates;
655661

656662
using SpecializationsUpdate = SmallVector<UpdateData, 1>;
657-
llvm::DenseMap<GlobalDeclID, SpecializationsUpdate>
658-
PendingSpecializationsUpdates;
663+
using SpecializationsUpdateMap = llvm::DenseMap<GlobalDeclID, SpecializationsUpdate>;
664+
SpecializationsUpdateMap PendingSpecializationsUpdates;
665+
SpecializationsUpdateMap PendingPartialSpecializationsUpdates;
659666

660667
/// The set of C++ or Objective-C classes that have forward
661668
/// declarations that have not yet been linked to their definitions.
@@ -690,9 +697,9 @@ class ASTReader
690697
uint64_t Offset, GlobalDeclID ID);
691698

692699
bool ReadSpecializations(ModuleFile &M, llvm::BitstreamCursor &Cursor,
693-
uint64_t Offset, Decl *D);
700+
uint64_t Offset, Decl *D, bool IsPartial);
694701
void AddSpecializations(const Decl *D, const unsigned char *Data,
695-
ModuleFile &M);
702+
ModuleFile &M, bool IsPartial);
696703

697704
/// A vector containing identifiers that have already been
698705
/// loaded.
@@ -1399,7 +1406,10 @@ class ASTReader
13991406
/// Get the loaded specializations lookup tables for \p D,
14001407
/// if any.
14011408
serialization::reader::LazySpecializationInfoLookupTable *
1402-
getLoadedSpecializationsLookupTables(const Decl *D);
1409+
getLoadedSpecializationsLookupTables(const Decl *D, bool IsPartial);
1410+
1411+
/// If we have any unloaded specialization for \p D
1412+
bool haveUnloadedSpecializations(const Decl *D) const;
14031413

14041414
private:
14051415
struct ImportedModule {

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ class ASTWriter : public ASTDeserializationListener,
431431
using SpecializationUpdateMap =
432432
llvm::MapVector<const NamedDecl *, SmallVector<const Decl *>>;
433433
SpecializationUpdateMap SpecializationsUpdates;
434+
SpecializationUpdateMap PartialSpecializationsUpdates;
434435

435436
using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>;
436437

@@ -585,9 +586,9 @@ class ASTWriter : public ASTDeserializationListener,
585586

586587
void GenerateSpecializationInfoLookupTable(
587588
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
588-
llvm::SmallVectorImpl<char> &LookupTable);
589+
llvm::SmallVectorImpl<char> &LookupTable, bool IsPartial);
589590
uint64_t WriteSpecializationInfoLookupTable(
590-
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations);
591+
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations, bool IsPartial);
591592

592593
void GenerateNameLookupTable(const DeclContext *DC,
593594
llvm::SmallVectorImpl<char> &LookupTable);
@@ -604,7 +605,7 @@ class ASTWriter : public ASTDeserializationListener,
604605
void WriteDeclAndTypes(ASTContext &Context);
605606
void PrepareWritingSpecialDecls(Sema &SemaRef);
606607
void WriteSpecialDeclRecords(Sema &SemaRef);
607-
void WriteSpecializationsUpdates();
608+
void WriteSpecializationsUpdates(bool IsPartial);
608609
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
609610
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
610611
void WriteFPPragmaOptions(const FPOptionsOverride &Opts);
@@ -633,6 +634,7 @@ class ASTWriter : public ASTDeserializationListener,
633634
unsigned DeclObjCIvarAbbrev = 0;
634635
unsigned DeclCXXMethodAbbrev = 0;
635636
unsigned DeclSpecializationsAbbrev = 0;
637+
unsigned DeclPartialSpecializationsAbbrev = 0;
636638

637639
unsigned DeclDependentNonTemplateCXXMethodAbbrev = 0;
638640
unsigned DeclTemplateCXXMethodAbbrev = 0;

clang/lib/Serialization/ASTReader.cpp

Lines changed: 70 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,13 +1321,11 @@ void LazySpecializationInfoLookupTrait::ReadDataInto(internal_key_type,
13211321
using namespace llvm::support;
13221322

13231323
for (unsigned NumDecls =
1324-
DataLen / serialization::reader::LazySpecializationInfo::Length;
1324+
DataLen / sizeof(serialization::reader::LazySpecializationInfo);
13251325
NumDecls; --NumDecls) {
13261326
LocalDeclID LocalID =
13271327
LocalDeclID::get(Reader, F, endian::readNext<DeclID, llvm::endianness::little, unaligned>(d));
1328-
const bool IsPartial =
1329-
endian::readNext<bool, llvm::endianness::little, unaligned>(d);
1330-
Val.insert({Reader.getGlobalDeclID(F, LocalID), IsPartial});
1328+
Val.insert(Reader.getGlobalDeclID(F, LocalID));
13311329
}
13321330
}
13331331

@@ -1420,14 +1418,15 @@ bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M,
14201418
}
14211419

14221420
void ASTReader::AddSpecializations(const Decl *D, const unsigned char *Data,
1423-
ModuleFile &M) {
1421+
ModuleFile &M, bool IsPartial) {
14241422
D = D->getCanonicalDecl();
1425-
SpecializationsLookups[D].Table.add(
1423+
auto &SpecLookups = IsPartial ? PartialSpecializationsLookups : SpecializationsLookups;
1424+
SpecLookups[D].Table.add(
14261425
&M, Data, reader::LazySpecializationInfoLookupTrait(*this, M));
14271426
}
14281427

14291428
bool ASTReader::ReadSpecializations(ModuleFile &M, BitstreamCursor &Cursor,
1430-
uint64_t Offset, Decl *D) {
1429+
uint64_t Offset, Decl *D, bool IsPartial) {
14311430
assert(Offset != 0);
14321431

14331432
SavedStreamPosition SavedPosition(Cursor);
@@ -1451,13 +1450,14 @@ bool ASTReader::ReadSpecializations(ModuleFile &M, BitstreamCursor &Cursor,
14511450
return true;
14521451
}
14531452
unsigned RecCode = MaybeRecCode.get();
1454-
if (RecCode != DECL_SPECIALIZATIONS) {
1453+
if (RecCode != DECL_SPECIALIZATIONS &&
1454+
RecCode != DECL_PARTIAL_SPECIALIZATIONS) {
14551455
Error("Expected decl specs block");
14561456
return true;
14571457
}
14581458

14591459
auto *Data = (const unsigned char *)Blob.data();
1460-
AddSpecializations(D, Data, M);
1460+
AddSpecializations(D, Data, M, IsPartial);
14611461
return false;
14621462
}
14631463

@@ -3565,6 +3565,19 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
35653565
break;
35663566
}
35673567

3568+
case CXX_ADDED_TEMPLATE_PARTIAL_SPECIALIZATION: {
3569+
unsigned Idx = 0;
3570+
GlobalDeclID ID = ReadDeclID(F, Record, Idx);
3571+
auto *Data = (const unsigned char *)Blob.data();
3572+
PendingPartialSpecializationsUpdates[ID].push_back(UpdateData{&F, Data});
3573+
// If we've already loaded the decl, perform the updates when we finish
3574+
// loading this block.
3575+
if (Decl *D = GetExistingDecl(ID))
3576+
PendingUpdateRecords.push_back(
3577+
PendingUpdateRecord(ID, D, /*JustLoaded=*/false));
3578+
break;
3579+
}
3580+
35683581
case IDENTIFIER_TABLE:
35693582
F.IdentifierTableData =
35703583
reinterpret_cast<const unsigned char *>(Blob.data());
@@ -8156,11 +8169,11 @@ Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
81568169
return ReadStmtFromStream(*Loc.F);
81578170
}
81588171

8159-
bool ASTReader::LoadExternalSpecializations(const Decl *D, bool OnlyPartial) {
8172+
bool ASTReader::LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups, const Decl *D) {
81608173
assert(D);
81618174

8162-
auto It = SpecializationsLookups.find(D);
8163-
if (It == SpecializationsLookups.end())
8175+
auto It = SpecLookups.find(D);
8176+
if (It == SpecLookups.end())
81648177
return false;
81658178

81668179
// Get Decl may violate the iterator from SpecializationsLookups so we store
@@ -8170,48 +8183,67 @@ bool ASTReader::LoadExternalSpecializations(const Decl *D, bool OnlyPartial) {
81708183

81718184
// Since we've loaded all the specializations, we can erase it from
81728185
// the lookup table.
8173-
if (!OnlyPartial)
8174-
SpecializationsLookups.erase(It);
8186+
SpecLookups.erase(It);
81758187

81768188
bool NewSpecsFound = false;
81778189
Deserializing LookupResults(this);
8178-
for (auto &Info : Infos)
8179-
if (!OnlyPartial || Info.IsPartial) {
8180-
if (GetExistingDecl(Info.ID))
8181-
continue;
8182-
NewSpecsFound = true;
8183-
GetDecl(Info.ID);
8184-
}
8190+
for (auto &Info : Infos) {
8191+
if (GetExistingDecl(Info))
8192+
continue;
8193+
NewSpecsFound = true;
8194+
GetDecl(Info);
8195+
}
81858196

81868197
return NewSpecsFound;
81878198
}
81888199

8189-
bool ASTReader::LoadExternalSpecializations(
8190-
const Decl *D, ArrayRef<TemplateArgument> TemplateArgs) {
8200+
bool ASTReader::LoadExternalSpecializations(const Decl *D, bool OnlyPartial) {
81918201
assert(D);
81928202

8193-
auto It = SpecializationsLookups.find(D);
8194-
if (It == SpecializationsLookups.end())
8203+
bool NewSpecsFound = LoadExternalSpecializationsImpl(PartialSpecializationsLookups, D);
8204+
if (OnlyPartial)
8205+
return NewSpecsFound;
8206+
8207+
NewSpecsFound |= LoadExternalSpecializationsImpl(SpecializationsLookups, D);
8208+
return NewSpecsFound;
8209+
}
8210+
8211+
bool ASTReader::LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups, const Decl *D,
8212+
ArrayRef<TemplateArgument> TemplateArgs) {
8213+
assert(D);
8214+
8215+
auto It = SpecLookups.find(D);
8216+
if (It == SpecLookups.end())
81958217
return false;
81968218

81978219
Deserializing LookupResults(this);
81988220
auto HashValue = StableHashForTemplateArguments(TemplateArgs);
81998221

8200-
// Get Decl may violate the iterator from SpecializationsLookups
8222+
// Get Decl may violate the iterator from SpecLookups
82018223
llvm::SmallVector<serialization::reader::LazySpecializationInfo, 8> Infos =
82028224
It->second.Table.find(HashValue);
82038225

82048226
bool NewSpecsFound = false;
82058227
for (auto &Info : Infos) {
8206-
if (GetExistingDecl(Info.ID))
8228+
if (GetExistingDecl(Info))
82078229
continue;
82088230
NewSpecsFound = true;
8209-
GetDecl(Info.ID);
8231+
GetDecl(Info);
82108232
}
82118233

82128234
return NewSpecsFound;
82138235
}
82148236

8237+
bool ASTReader::LoadExternalSpecializations(
8238+
const Decl *D, ArrayRef<TemplateArgument> TemplateArgs) {
8239+
assert(D);
8240+
8241+
bool NewDeclsFound = LoadExternalSpecializationsImpl(PartialSpecializationsLookups, D, TemplateArgs);
8242+
NewDeclsFound |= LoadExternalSpecializationsImpl(SpecializationsLookups, D, TemplateArgs);
8243+
8244+
return NewDeclsFound;
8245+
}
8246+
82158247
void ASTReader::FindExternalLexicalDecls(
82168248
const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
82178249
SmallVectorImpl<Decl *> &Decls) {
@@ -8392,10 +8424,17 @@ ASTReader::getLoadedLookupTables(DeclContext *Primary) const {
83928424
}
83938425

83948426
serialization::reader::LazySpecializationInfoLookupTable *
8395-
ASTReader::getLoadedSpecializationsLookupTables(const Decl *D) {
8427+
ASTReader::getLoadedSpecializationsLookupTables(const Decl *D, bool IsPartial) {
8428+
assert(D->isCanonicalDecl());
8429+
auto &LookupTable = IsPartial ? PartialSpecializationsLookups : SpecializationsLookups;
8430+
auto I = LookupTable.find(D);
8431+
return I == LookupTable.end() ? nullptr : &I->second;
8432+
}
8433+
8434+
bool ASTReader::haveUnloadedSpecializations(const Decl *D) const {
83968435
assert(D->isCanonicalDecl());
8397-
auto I = SpecializationsLookups.find(D);
8398-
return I == SpecializationsLookups.end() ? nullptr : &I->second;
8436+
return (PartialSpecializationsLookups.find(D) != PartialSpecializationsLookups.end()) ||
8437+
(SpecializationsLookups.find(D) != SpecializationsLookups.end());
83998438
}
84008439

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

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> {
304304
static void markIncompleteDeclChainImpl(...);
305305

306306
void ReadSpecializations(ModuleFile &M, Decl *D,
307-
llvm::BitstreamCursor &DeclsCursor);
307+
llvm::BitstreamCursor &DeclsCursor,
308+
bool IsPartial);
308309

309310
void ReadFunctionDefinition(FunctionDecl *FD);
310311
void Visit(Decl *D);
@@ -2384,9 +2385,10 @@ void ASTDeclReader::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
23842385
}
23852386

23862387
void ASTDeclReader::ReadSpecializations(ModuleFile &M, Decl *D,
2387-
llvm::BitstreamCursor &DeclsCursor) {
2388+
llvm::BitstreamCursor &DeclsCursor,
2389+
bool IsPartial) {
23882390
uint64_t Offset = ReadLocalOffset();
2389-
bool Failed = Reader.ReadSpecializations(M, DeclsCursor, Offset, D);
2391+
bool Failed = Reader.ReadSpecializations(M, DeclsCursor, Offset, D, IsPartial);
23902392
(void)Failed;
23912393
assert(!Failed);
23922394
}
@@ -2429,7 +2431,8 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
24292431
if (ThisDeclID == Redecl.getFirstID()) {
24302432
// This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
24312433
// the specializations.
2432-
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor);
2434+
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor, /*IsPartial=*/false);
2435+
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor, /*IsPartial=*/true);
24332436
}
24342437

24352438
if (D->getTemplatedDecl()->TemplateOrInstantiation) {
@@ -2455,7 +2458,8 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
24552458
if (ThisDeclID == Redecl.getFirstID()) {
24562459
// This VarTemplateDecl owns a CommonPtr; read it to keep track of all of
24572460
// the specializations.
2458-
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor);
2461+
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor, /*IsPartial=*/false);
2462+
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor, /*IsPartial=*/true);
24592463
}
24602464
}
24612465

@@ -2554,7 +2558,7 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
25542558

25552559
if (ThisDeclID == Redecl.getFirstID()) {
25562560
// This FunctionTemplateDecl owns a CommonPtr; read it.
2557-
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor);
2561+
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor, /*IsPartial=*/false);
25582562
}
25592563
}
25602564

@@ -3845,6 +3849,7 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) {
38453849
case DECL_CONTEXT_LEXICAL:
38463850
case DECL_CONTEXT_VISIBLE:
38473851
case DECL_SPECIALIZATIONS:
3852+
case DECL_PARTIAL_SPECIALIZATIONS:
38483853
llvm_unreachable("Record cannot be de-serialized with readDeclRecord");
38493854
case DECL_TYPEDEF:
38503855
D = TypedefDecl::CreateDeserialized(Context, ID);
@@ -4332,7 +4337,17 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
43324337
PendingSpecializationsUpdates.erase(I);
43334338

43344339
for (const auto &Update : SpecializationUpdates)
4335-
AddSpecializations(D, Update.Data, *Update.Mod);
4340+
AddSpecializations(D, Update.Data, *Update.Mod, /*IsPartial=*/false);
4341+
}
4342+
4343+
// Load the pending specializations update for this decl, if it has any.
4344+
if (auto I = PendingPartialSpecializationsUpdates.find(ID);
4345+
I != PendingPartialSpecializationsUpdates.end()) {
4346+
auto SpecializationUpdates = std::move(I->second);
4347+
PendingPartialSpecializationsUpdates.erase(I);
4348+
4349+
for (const auto &Update : SpecializationUpdates)
4350+
AddSpecializations(D, Update.Data, *Update.Mod, /*IsPartial=*/true);
43364351
}
43374352
}
43384353

0 commit comments

Comments
 (0)