Skip to content

Commit 9b2c0cd

Browse files
author
Joe Shajrawi
committed
add a sidetable cache in the module for VTable entries, replacing linear lookup
1 parent 4866403 commit 9b2c0cd

File tree

4 files changed

+37
-14
lines changed

4 files changed

+37
-14
lines changed

include/swift/SIL/SILModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ class SILModule {
132132
/// The list of SILVTables in the module.
133133
VTableListType vtables;
134134

135+
/// This is a cache of vtable entries for quick look-up
136+
llvm::DenseMap<std::pair<const SILVTable *, SILDeclRef>, SILFunction *>
137+
VTableEntryCache;
138+
135139
/// Lookup table for SIL witness tables from conformances.
136140
llvm::DenseMap<const NormalProtocolConformance *, SILWitnessTable *>
137141
WitnessTableMap;

include/swift/SIL/SILVTable.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class SILVTable : public llvm::ilist_node<SILVTable>,
8686
[&](Pair &entry) -> bool {
8787
if (predicate(entry)) {
8888
entry.second->decrementRefCount();
89+
removeFromVTableCache(entry);
8990
return true;
9091
}
9192
return false;
@@ -99,6 +100,9 @@ class SILVTable : public llvm::ilist_node<SILVTable>,
99100
/// Print the vtable.
100101
void print(llvm::raw_ostream &OS, bool Verbose = false) const;
101102
void dump() const;
103+
104+
private:
105+
void removeFromVTableCache(Pair &entry);
102106
};
103107

104108
} // end swift namespace

lib/SIL/SILVTable.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,27 +33,30 @@ SILVTable *SILVTable::create(SILModule &M, ClassDecl *Class,
3333
SILVTable *vt = ::new (buf) SILVTable(Class, Entries);
3434
M.vtables.push_back(vt);
3535
M.VTableMap[Class] = vt;
36+
// Update the Module's cache with new vtable + vtable entries:
37+
for (auto &entry : Entries) {
38+
M.VTableEntryCache.insert({{vt, entry.first}, entry.second});
39+
}
3640
return vt;
3741
}
3842

3943
SILFunction *
4044
SILVTable::getImplementation(SILModule &M, SILDeclRef method) const {
41-
// FIXME: We should build a sidetable cache in the module. Linear lookup here
42-
// is lame.
43-
44-
for (auto &entry : getEntries()) {
45-
// Check whether this mapping matches either the given decl directly or
46-
// one of its overridden decl.
47-
SILDeclRef m = method;
48-
do {
49-
if (entry.first == m)
50-
return entry.second;
51-
} while ((m = m.getOverridden()));
52-
}
53-
45+
SILDeclRef m = method;
46+
do {
47+
auto entry = M.VTableEntryCache.find({this, m});
48+
if (entry != M.VTableEntryCache.end()) {
49+
return (*entry).second;
50+
}
51+
} while ((m = m.getOverridden()));
5452
return nullptr;
5553
}
5654

55+
void SILVTable::removeFromVTableCache(Pair &entry) {
56+
SILModule &M = entry.second->getModule();
57+
M.VTableEntryCache.erase({this, entry.first});
58+
}
59+
5760
SILVTable::SILVTable(ClassDecl *c, ArrayRef<Pair> entries)
5861
: Class(c), NumEntries(entries.size())
5962
{

lib/SIL/SILVerifier.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3546,15 +3546,27 @@ void SILModule::verify() const {
35463546
g.verify();
35473547
}
35483548

3549-
// Check all vtables.
3549+
// Check all vtables and the vtable cache.
35503550
llvm::DenseSet<ClassDecl*> vtableClasses;
3551+
unsigned EntriesSZ = 0;
35513552
for (const SILVTable &vt : getVTables()) {
35523553
if (!vtableClasses.insert(vt.getClass()).second) {
35533554
llvm::errs() << "Vtable redefined: " << vt.getClass()->getName() << "!\n";
35543555
assert(false && "triggering standard assertion failure routine");
35553556
}
35563557
vt.verify(*this);
3558+
// Check if there is a cache entry for each vtable entry
3559+
for (auto entry : vt.getEntries()) {
3560+
if (VTableEntryCache.find({&vt, entry.first}) == VTableEntryCache.end()) {
3561+
llvm::errs() << "Vtable entry for function: " << entry.second->getName()
3562+
<< "not in cache!\n";
3563+
assert(false && "triggering standard assertion failure routine");
3564+
}
3565+
EntriesSZ++;
3566+
}
35573567
}
3568+
assert(EntriesSZ == VTableEntryCache.size() &&
3569+
"Cache size is not equal to true number of VTable entries");
35583570

35593571
// Check all witness tables.
35603572
DEBUG(llvm::dbgs() << "*** Checking witness tables for duplicates ***\n");

0 commit comments

Comments
 (0)