Skip to content

Commit 017ee7b

Browse files
committed
[SIL] NFC: Simplify SILVTable and save 8 bytes per SILVTable
We were not using the primary benefits of an intrusive list, namely the ability to insert or remove from the middle of the list, so let's switch to a plain vector. This also avoids linked-list pointer chasing.
1 parent fe8893d commit 017ee7b

File tree

14 files changed

+53
-58
lines changed

14 files changed

+53
-58
lines changed

include/swift/SIL/SILModule.h

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class SILModule {
110110
public:
111111
using FunctionListType = llvm::ilist<SILFunction>;
112112
using GlobalListType = llvm::ilist<SILGlobalVariable>;
113-
using VTableListType = llvm::ilist<SILVTable>;
113+
using VTableListType = llvm::ArrayRef<SILVTable*>;
114114
using PropertyListType = llvm::ilist<SILProperty>;
115115
using WitnessTableListType = llvm::ilist<SILWitnessTable>;
116116
using DefaultWitnessTableListType = llvm::ilist<SILDefaultWitnessTable>;
@@ -178,7 +178,7 @@ class SILModule {
178178
llvm::DenseMap<const ClassDecl *, SILVTable *> VTableMap;
179179

180180
/// The list of SILVTables in the module.
181-
VTableListType vtables;
181+
std::vector<SILVTable*> vtables;
182182

183183
/// This is a cache of vtable entries for quick look-up
184184
llvm::DenseMap<std::pair<const SILVTable *, SILDeclRef>, SILVTable::Entry>
@@ -404,20 +404,15 @@ class SILModule {
404404
const_iterator zombies_begin() const { return zombieFunctions.begin(); }
405405
const_iterator zombies_end() const { return zombieFunctions.end(); }
406406

407+
llvm::ArrayRef<SILVTable*> getVTables() const {
408+
return llvm::ArrayRef<SILVTable*>(vtables);
409+
}
407410
using vtable_iterator = VTableListType::iterator;
408411
using vtable_const_iterator = VTableListType::const_iterator;
409-
VTableListType &getVTableList() { return vtables; }
410-
const VTableListType &getVTableList() const { return vtables; }
411-
vtable_iterator vtable_begin() { return vtables.begin(); }
412-
vtable_iterator vtable_end() { return vtables.end(); }
413-
vtable_const_iterator vtable_begin() const { return vtables.begin(); }
414-
vtable_const_iterator vtable_end() const { return vtables.end(); }
415-
iterator_range<vtable_iterator> getVTables() {
416-
return {vtables.begin(), vtables.end()};
417-
}
418-
iterator_range<vtable_const_iterator> getVTables() const {
419-
return {vtables.begin(), vtables.end()};
420-
}
412+
vtable_iterator vtable_begin() { return getVTables().begin(); }
413+
vtable_iterator vtable_end() { return getVTables().end(); }
414+
vtable_const_iterator vtable_begin() const { return getVTables().begin(); }
415+
vtable_const_iterator vtable_end() const { return getVTables().end(); }
421416

422417
using witness_table_iterator = WitnessTableListType::iterator;
423418
using witness_table_const_iterator = WitnessTableListType::const_iterator;

include/swift/SIL/SILVTable.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
#include "swift/SIL/SILAllocated.h"
3030
#include "swift/SIL/SILDeclRef.h"
3131
#include "swift/SIL/SILFunction.h"
32-
#include "llvm/ADT/ilist_node.h"
33-
#include "llvm/ADT/ilist.h"
3432
#include "llvm/ADT/Optional.h"
3533
#include <algorithm>
3634

@@ -44,8 +42,7 @@ class SILModule;
4442
/// A mapping from each dynamically-dispatchable method of a class to the
4543
/// SILFunction that implements the method for that class.
4644
/// Note that dead methods are completely removed from the vtable.
47-
class SILVTable : public llvm::ilist_node<SILVTable>,
48-
public SILAllocated<SILVTable> {
45+
class SILVTable : public SILAllocated<SILVTable> {
4946
public:
5047
// TODO: Entry should include substitutions needed to invoke an overridden
5148
// generic base class method.

lib/Frontend/Frontend.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ static void countStatsPostSILOpt(UnifiedStatsReporter &Stats,
10001000
auto &C = Stats.getFrontendCounters();
10011001
// FIXME: calculate these in constant time, via the dense maps.
10021002
C.NumSILOptFunctions += Module.getFunctionList().size();
1003-
C.NumSILOptVtables += Module.getVTableList().size();
1003+
C.NumSILOptVtables += Module.getVTables().size();
10041004
C.NumSILOptWitnessTables += Module.getWitnessTableList().size();
10051005
C.NumSILOptDefaultWitnessTables += Module.getDefaultWitnessTableList().size();
10061006
C.NumSILOptGlobalVariables += Module.getSILGlobalList().size();

lib/FrontendTool/FrontendTool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ static void countStatsPostSILGen(UnifiedStatsReporter &Stats,
736736
auto &C = Stats.getFrontendCounters();
737737
// FIXME: calculate these in constant time, via the dense maps.
738738
C.NumSILGenFunctions += Module.getFunctionList().size();
739-
C.NumSILGenVtables += Module.getVTableList().size();
739+
C.NumSILGenVtables += Module.getVTables().size();
740740
C.NumSILGenWitnessTables += Module.getWitnessTableList().size();
741741
C.NumSILGenDefaultWitnessTables += Module.getDefaultWitnessTableList().size();
742742
C.NumSILGenGlobalVariables += Module.getSILGlobalList().size();

lib/SIL/IR/SILModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ SILModule::~SILModule() {
115115
for (SILGlobalVariable &v : silGlobals)
116116
v.dropAllReferences();
117117

118+
for (auto vt : vtables)
119+
vt->~SILVTable();
120+
118121
// Drop everything functions in this module reference.
119122
//
120123
// This is necessary since the functions may reference each other. We don't

lib/SIL/IR/SILPrinter.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2797,15 +2797,15 @@ static void printSILFunctions(SILPrintContext &Ctx,
27972797
static void printSILVTables(SILPrintContext &Ctx,
27982798
const SILModule::VTableListType &VTables) {
27992799
if (!Ctx.sortSIL()) {
2800-
for (const SILVTable &vt : VTables)
2801-
vt.print(Ctx.OS(), Ctx.printVerbose());
2800+
for (const auto &vt : VTables)
2801+
vt->print(Ctx.OS(), Ctx.printVerbose());
28022802
return;
28032803
}
28042804

28052805
std::vector<const SILVTable *> vtables;
28062806
vtables.reserve(VTables.size());
2807-
for (const SILVTable &vt : VTables)
2808-
vtables.push_back(&vt);
2807+
for (const auto &vt : VTables)
2808+
vtables.push_back(vt);
28092809
std::sort(vtables.begin(), vtables.end(),
28102810
[] (const SILVTable *v1, const SILVTable *v2) -> bool {
28112811
StringRef Name1 = v1->getClass()->getName().str();
@@ -3067,7 +3067,7 @@ void SILModule::print(SILPrintContext &PrintCtx, ModuleDecl *M,
30673067
printSILDifferentiabilityWitnesses(PrintCtx,
30683068
getDifferentiabilityWitnessList());
30693069
printSILFunctions(PrintCtx, getFunctionList());
3070-
printSILVTables(PrintCtx, getVTableList());
3070+
printSILVTables(PrintCtx, getVTables());
30713071
printSILWitnessTables(PrintCtx, getWitnessTableList());
30723072
printSILDefaultWitnessTables(PrintCtx, getDefaultWitnessTableList());
30733073
printSILCoverageMaps(PrintCtx, getCoverageMaps());

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5367,8 +5367,8 @@ void SILVTable::verify(const SILModule &M) const {
53675367
auto superclass = getClass()->getSuperclassDecl();
53685368
if (superclass) {
53695369
for (auto &vt : M.getVTables()) {
5370-
if (vt.getClass() == superclass) {
5371-
superVTable = &vt;
5370+
if (vt->getClass() == superclass) {
5371+
superVTable = vt;
53725372
break;
53735373
}
53745374
}
@@ -5582,15 +5582,15 @@ void SILModule::verify() const {
55825582
// Check all vtables and the vtable cache.
55835583
llvm::DenseSet<ClassDecl*> vtableClasses;
55845584
unsigned EntriesSZ = 0;
5585-
for (const SILVTable &vt : getVTables()) {
5586-
if (!vtableClasses.insert(vt.getClass()).second) {
5587-
llvm::errs() << "Vtable redefined: " << vt.getClass()->getName() << "!\n";
5585+
for (const auto &vt : getVTables()) {
5586+
if (!vtableClasses.insert(vt->getClass()).second) {
5587+
llvm::errs() << "Vtable redefined: " << vt->getClass()->getName() << "!\n";
55885588
assert(false && "triggering standard assertion failure routine");
55895589
}
5590-
vt.verify(*this);
5590+
vt->verify(*this);
55915591
// Check if there is a cache entry for each vtable entry
5592-
for (auto entry : vt.getEntries()) {
5593-
if (VTableEntryCache.find({&vt, entry.Method}) == VTableEntryCache.end()) {
5592+
for (auto entry : vt->getEntries()) {
5593+
if (VTableEntryCache.find({vt, entry.Method}) == VTableEntryCache.end()) {
55945594
llvm::errs() << "Vtable entry for function: "
55955595
<< entry.Implementation->getName() << "not in cache!\n";
55965596
assert(false && "triggering standard assertion failure routine");

lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ void CalleeCache::computeClassMethodCallees() {
107107
// This is a little bit more complicated than to just check the VTable
108108
// entry.Method itself, because an overridden method might be more accessible
109109
// than the base method (e.g. a public method overrides a private method).
110-
for (auto &VTable : M.getVTableList()) {
111-
assert(!VTable.getClass()->hasClangNode());
110+
for (auto &VTable : M.getVTables()) {
111+
assert(!VTable->getClass()->hasClangNode());
112112

113-
for (Decl *member : VTable.getClass()->getMembers()) {
113+
for (Decl *member : VTable->getClass()->getMembers()) {
114114
if (auto *afd = dyn_cast<AbstractFunctionDecl>(member)) {
115115
// If a method implementation might be overridden in another translation
116116
// unit, also mark all the base methods as 'unknown'.
@@ -127,8 +127,8 @@ void CalleeCache::computeClassMethodCallees() {
127127
}
128128

129129
// Second step: collect all implementations of a method.
130-
for (auto &VTable : M.getVTableList()) {
131-
for (const SILVTable::Entry &entry : VTable.getEntries()) {
130+
for (auto &VTable : M.getVTables()) {
131+
for (const SILVTable::Entry &entry : VTable->getEntries()) {
132132
if (auto *afd = entry.Method.getAbstractFunctionDecl()) {
133133
CalleesAndCanCallUnknown &callees = getOrCreateCalleesForMethod(entry.Method);
134134
if (unknownCallees.count(afd) != 0)
@@ -308,8 +308,8 @@ void BasicCalleeAnalysis::print(llvm::raw_ostream &os) const {
308308
os << "<no cache>\n";
309309
}
310310
llvm::DenseSet<SILDeclRef> printed;
311-
for (auto &VTable : M.getVTableList()) {
312-
for (const SILVTable::Entry &entry : VTable.getEntries()) {
311+
for (auto &VTable : M.getVTables()) {
312+
for (const SILVTable::Entry &entry : VTable->getEntries()) {
313313
if (printed.insert(entry.Method).second) {
314314
os << "callees for " << entry.Method << ":\n";
315315
Cache->getCalleeList(entry.Method).print(os);

lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ void ClassHierarchyAnalysis::init() {
2323
auto module = M->getSwiftModule();
2424

2525
// For each class declaration in our V-table list:
26-
for (auto &VT : M->getVTableList()) {
27-
ClassDecl *C = VT.getClass();
26+
for (auto &VT : M->getVTables()) {
27+
ClassDecl *C = VT->getClass();
2828

2929
while (true) {
3030
// Ignore classes that are at the top of the class hierarchy:

lib/SILOptimizer/IPO/DeadFunctionElimination.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,8 @@ class DeadFunctionElimination : FunctionLivenessComputation {
440440

441441
void collectMethodImplementations() {
442442
// Collect vtable method implementations.
443-
for (SILVTable &vTable : Module->getVTableList()) {
444-
for (const SILVTable::Entry &entry : vTable.getEntries()) {
443+
for (auto &vTable : Module->getVTables()) {
444+
for (const SILVTable::Entry &entry : vTable->getEntries()) {
445445
// We don't need to collect destructors because we mark them as alive
446446
// anyway.
447447
if (entry.Method.kind == SILDeclRef::Kind::Deallocator ||
@@ -452,7 +452,7 @@ class DeadFunctionElimination : FunctionLivenessComputation {
452452
auto *fd = getBaseMethod(cast<AbstractFunctionDecl>(
453453
entry.Method.getDecl()));
454454
MethodInfo *mi = getMethodInfo(fd, /*isWitnessTable*/ false);
455-
mi->addClassMethodImpl(F, vTable.getClass());
455+
mi->addClassMethodImpl(F, vTable->getClass());
456456
}
457457
}
458458

@@ -500,8 +500,8 @@ class DeadFunctionElimination : FunctionLivenessComputation {
500500
collectMethodImplementations();
501501

502502
// Check vtable methods.
503-
for (SILVTable &vTable : Module->getVTableList()) {
504-
for (const SILVTable::Entry &entry : vTable.getEntries()) {
503+
for (auto &vTable : Module->getVTables()) {
504+
for (const SILVTable::Entry &entry : vTable->getEntries()) {
505505
if (entry.Method.kind == SILDeclRef::Kind::Deallocator ||
506506
entry.Method.kind == SILDeclRef::Kind::IVarDestroyer) {
507507
// Destructors are alive because they are called from swift_release
@@ -600,9 +600,9 @@ class DeadFunctionElimination : FunctionLivenessComputation {
600600
/// Removes all dead methods from vtables and witness tables.
601601
bool removeDeadEntriesFromTables() {
602602
bool changedTable = false;
603-
for (SILVTable &vTable : Module->getVTableList()) {
604-
vTable.removeEntries_if([this, &changedTable]
605-
(SILVTable::Entry &entry) -> bool {
603+
for (auto &vTable : Module->getVTables()) {
604+
vTable->removeEntries_if([this, &changedTable]
605+
(SILVTable::Entry &entry) -> bool {
606606
if (!isAlive(entry.Implementation)) {
607607
LLVM_DEBUG(llvm::dbgs() << " erase dead vtable method "
608608
<< entry.Implementation->getName() << "\n");

lib/SILOptimizer/Transforms/PruneVTables.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class PruneVTables : public SILModuleTransform {
6161
SILModule *M = getModule();
6262

6363
for (auto &vtable : M->getVTables()) {
64-
runOnVTable(M, &vtable);
64+
runOnVTable(M, vtable);
6565
}
6666
}
6767
};

lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ class SerializeSILPass : public SILModuleTransform {
427427
}
428428

429429
for (auto &VT : M.getVTables()) {
430-
VT.setSerialized(IsNotSerialized);
430+
VT->setSerialized(IsNotSerialized);
431431
}
432432
}
433433

lib/Serialization/SerializeSIL.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2659,10 +2659,10 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
26592659
// Go through all SILVTables in SILMod and write them if we should
26602660
// serialize everything.
26612661
// FIXME: Resilience: could write out vtable for fragile classes.
2662-
for (const SILVTable &vt : SILMod->getVTables()) {
2663-
if ((ShouldSerializeAll || vt.isSerialized()) &&
2664-
SILMod->shouldSerializeEntitiesAssociatedWithDeclContext(vt.getClass()))
2665-
writeSILVTable(vt);
2662+
for (const auto &vt : SILMod->getVTables()) {
2663+
if ((ShouldSerializeAll || vt->isSerialized()) &&
2664+
SILMod->shouldSerializeEntitiesAssociatedWithDeclContext(vt->getClass()))
2665+
writeSILVTable(*vt);
26662666
}
26672667

26682668
// Write out property descriptors.

tools/sil-nm/SILNM.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ static void nmModule(SILModule *M) {
126126
{
127127
std::vector<StringRef> VTableNames;
128128
llvm::transform(M->getVTables(), std::back_inserter(VTableNames),
129-
[](const SILVTable &VT) -> StringRef {
130-
return VT.getClass()->getName().str();
129+
[](const SILVTable *VT) -> StringRef {
130+
return VT->getClass()->getName().str();
131131
});
132132
printAndSortNames(VTableNames, 'V');
133133
}

0 commit comments

Comments
 (0)