Skip to content

Commit 04db869

Browse files
committed
SILGen: Simplify delayed conformance emission
Instead of visiting all types in the ExternalDefinitions list and queuing up their conformances, just emit conformances as needed when they are first referenced.
1 parent 0218ac8 commit 04db869

File tree

5 files changed

+13
-96
lines changed

5 files changed

+13
-96
lines changed

lib/SILGen/SILGen.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,16 +1747,15 @@ SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF) {
17471747
// Emitting these may in turn force more definitions, so we have to take care
17481748
// to keep pumping the queues.
17491749
while (!SGM.forcedFunctions.empty()
1750-
|| !SGM.forcedConformances.empty()) {
1750+
|| !SGM.pendingConformances.empty()) {
17511751
while (!SGM.forcedFunctions.empty()) {
17521752
auto &front = SGM.forcedFunctions.front();
17531753
front.second.emitter(SGM.getFunction(front.first, ForDefinition));
17541754
SGM.forcedFunctions.pop_front();
17551755
}
1756-
while (!SGM.forcedConformances.empty()) {
1757-
auto &front = SGM.forcedConformances.front();
1758-
SGM.getWitnessTable(front.first);
1759-
SGM.forcedConformances.pop_front();
1756+
while (!SGM.pendingConformances.empty()) {
1757+
SGM.getWitnessTable(SGM.pendingConformances.front());
1758+
SGM.pendingConformances.pop_front();
17601759
}
17611760
}
17621761

lib/SILGen/SILGen.h

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,28 +77,16 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
7777
/// The most recent declaration we considered for emission.
7878
SILDeclRef lastEmittedFunction;
7979

80-
/// Set of used conformances for which witness tables need to be emitted.
81-
llvm::DenseSet<RootProtocolConformance *> usedConformances;
82-
8380
/// Bookkeeping to ensure that useConformancesFrom{ObjectiveC,}Type() is
8481
/// only called once for each unique type, as an optimization.
8582
llvm::DenseSet<TypeBase *> usedConformancesFromTypes;
8683
llvm::DenseSet<TypeBase *> usedConformancesFromObjectiveCTypes;
8784

88-
struct DelayedWitnessTable {
89-
NormalProtocolConformance *insertAfter;
90-
};
91-
92-
/// Set of conformances we delayed emitting witness tables for.
93-
llvm::DenseMap<NormalProtocolConformance *, DelayedWitnessTable>
94-
delayedConformances;
85+
/// Queue of delayed conformances that need to be emitted.
86+
std::deque<NormalProtocolConformance *> pendingConformances;
9587

96-
/// Queue of delayed conformances that need to be forced.
97-
std::deque<std::pair<NormalProtocolConformance *, DelayedWitnessTable>>
98-
forcedConformances;
99-
100-
/// The most recent conformance...
101-
NormalProtocolConformance *lastEmittedConformance = nullptr;
88+
/// Set of delayed conformances that have already been forced.
89+
llvm::DenseSet<NormalProtocolConformance *> forcedConformances;
10290

10391
/// Profiler instances for constructors, grouped by associated decl.
10492
/// Each profiler is shared by all member initializers for a nominal type.
@@ -279,9 +267,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
279267
/// Emit SIL related to a Clang-imported declaration.
280268
void emitExternalDefinition(Decl *d);
281269

282-
/// Emit SIL related to a Clang-imported declaration.
283-
void emitExternalWitnessTable(NormalProtocolConformance *d);
284-
285270
/// Emit the ObjC-compatible entry point for a method.
286271
void emitObjCMethodThunk(FuncDecl *method);
287272

lib/SILGen/SILGenDecl.cpp

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,17 +1391,6 @@ CleanupHandle SILGenFunction::enterDeinitExistentialCleanup(
13911391
return Cleanups.getTopCleanup();
13921392
}
13931393

1394-
void SILGenModule::emitExternalWitnessTable(NormalProtocolConformance *c) {
1395-
// Emit the witness table right now if we used it.
1396-
if (usedConformances.count(c)) {
1397-
getWitnessTable(c);
1398-
return;
1399-
}
1400-
// Otherwise, remember it for later.
1401-
delayedConformances.insert({c, {lastEmittedConformance}});
1402-
lastEmittedConformance = c;
1403-
}
1404-
14051394
static bool isDeclaredInPrimaryFile(SILModule &M, Decl *d) {
14061395
auto *dc = d->getDeclContext();
14071396
if (auto *sf = dyn_cast<SourceFile>(dc->getModuleScopeContext()))
@@ -1433,22 +1422,9 @@ void SILGenModule::emitExternalDefinition(Decl *d) {
14331422
}
14341423
case DeclKind::Enum:
14351424
case DeclKind::Struct:
1436-
case DeclKind::Class: {
1437-
// Emit witness tables.
1438-
auto nom = cast<NominalTypeDecl>(d);
1439-
for (auto c : nom->getLocalConformances(ConformanceLookupKind::NonInherited,
1440-
nullptr)) {
1441-
auto *proto = c->getProtocol();
1442-
if (Lowering::TypeConverter::protocolRequiresWitnessTable(proto) &&
1443-
isa<NormalProtocolConformance>(c)) {
1444-
emitExternalWitnessTable(cast<NormalProtocolConformance>(c));
1445-
}
1446-
}
1447-
break;
1448-
}
1449-
1425+
case DeclKind::Class:
14501426
case DeclKind::Protocol:
1451-
// Nothing to do in SILGen for other external types.
1427+
// Nothing to do in SILGen for external types.
14521428
break;
14531429

14541430
case DeclKind::Var:

lib/SILGen/SILGenLazyConformance.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,11 @@ void SILGenModule::useConformance(ProtocolConformanceRef conformanceRef) {
5353
if (emittedWitnessTables.count(normal))
5454
return;
5555

56-
// If we delayed emitting this witness table, force it.
57-
auto foundDelayed = delayedConformances.find(normal);
58-
if (foundDelayed != delayedConformances.end()) {
59-
forcedConformances.push_back(*foundDelayed);
60-
delayedConformances.erase(foundDelayed);
56+
// Check if we already forced this witness table but haven't emitted it yet.
57+
if (!forcedConformances.insert(normal).second)
6158
return;
62-
}
6359

64-
// Otherwise, just remember the fact we used this conformance.
65-
usedConformances.insert(normal);
60+
pendingConformances.push_back(normal);
6661
}
6762

6863
void SILGenModule::useConformancesFromSubstitutions(

lib/SILGen/SILGenType.cpp

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -545,27 +545,6 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
545545

546546
} // end anonymous namespace
547547

548-
static SILWitnessTable *
549-
getWitnessTableToInsertAfter(SILGenModule &SGM,
550-
NormalProtocolConformance *insertAfter) {
551-
while (insertAfter) {
552-
// If the table was emitted, emit after it.
553-
auto found = SGM.emittedWitnessTables.find(insertAfter);
554-
if (found != SGM.emittedWitnessTables.end())
555-
return found->second;
556-
557-
// Otherwise, try inserting after the table we would transitively be
558-
// inserted after.
559-
auto foundDelayed = SGM.delayedConformances.find(insertAfter);
560-
if (foundDelayed != SGM.delayedConformances.end())
561-
insertAfter = foundDelayed->second.insertAfter;
562-
else
563-
break;
564-
}
565-
566-
return nullptr;
567-
}
568-
569548
SILWitnessTable *
570549
SILGenModule::getWitnessTable(NormalProtocolConformance *conformance) {
571550
// If we've already emitted this witness table, return it.
@@ -576,23 +555,6 @@ SILGenModule::getWitnessTable(NormalProtocolConformance *conformance) {
576555
SILWitnessTable *table = SILGenConformance(*this, conformance).emit();
577556
emittedWitnessTables.insert({conformance, table});
578557

579-
// If we delayed emission of this witness table, move it to its rightful
580-
// place within the module.
581-
auto foundDelayed = delayedConformances.find(conformance);
582-
if (foundDelayed != delayedConformances.end()) {
583-
M.witnessTables.remove(table);
584-
auto insertAfter = getWitnessTableToInsertAfter(*this,
585-
foundDelayed->second.insertAfter);
586-
if (!insertAfter) {
587-
M.witnessTables.push_front(table);
588-
} else {
589-
M.witnessTables.insertAfter(insertAfter->getIterator(), table);
590-
}
591-
} else {
592-
// We would have marked a delayed conformance as "last emitted" when it
593-
// was delayed.
594-
lastEmittedConformance = conformance;
595-
}
596558
return table;
597559
}
598560

0 commit comments

Comments
 (0)