Skip to content

Commit cc358ba

Browse files
committed
PruneVTables: Keep SILModule's vtable lookup table in sync with updates.
And add a verifier check to ensure the cache remains synced.
1 parent b4a0cea commit cc358ba

File tree

4 files changed

+70
-39
lines changed

4 files changed

+70
-39
lines changed

include/swift/SIL/SILVTable.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ class SILVTableEntry {
6464
// Please update the PointerIntPair above if you add/remove enums.
6565
};
6666

67-
SILVTableEntry() : ImplAndKind(nullptr, Kind::Normal) {}
67+
SILVTableEntry() : ImplAndKind(nullptr, Kind::Normal),
68+
IsNonOverridden(false) {}
6869

6970
SILVTableEntry(SILDeclRef Method, SILFunction *Implementation, Kind TheKind,
7071
bool NonOverridden)
@@ -80,6 +81,19 @@ class SILVTableEntry {
8081
void setNonOverridden(bool value) { IsNonOverridden = value; }
8182

8283
SILFunction *getImplementation() const { return ImplAndKind.getPointer(); }
84+
85+
void print(llvm::raw_ostream &os) const;
86+
87+
bool operator==(const SILVTableEntry &e) const {
88+
return Method == e.Method
89+
&& getImplementation() == e.getImplementation()
90+
&& getKind() == e.getKind()
91+
&& isNonOverridden() == e.isNonOverridden();
92+
}
93+
94+
bool operator!=(const SILVTableEntry &e) const {
95+
return !(*this == e);
96+
}
8397
};
8498

8599
/// A mapping from each dynamically-dispatchable method of a class to the
@@ -140,9 +154,13 @@ class SILVTable final : public SILAllocated<SILVTable>,
140154
}
141155

142156
/// Return all of the method entries mutably.
157+
/// If you do modify entries, make sure to invoke `updateVTableCache` to update the
158+
/// SILModule's cache entry.
143159
MutableArrayRef<Entry> getMutableEntries() {
144160
return {getTrailingObjects<SILVTableEntry>(), NumEntries};
145161
}
162+
163+
void updateVTableCache(const Entry &entry);
146164

147165
/// Look up the implementation function for the given method.
148166
Optional<Entry> getEntry(SILModule &M, SILDeclRef method) const;

lib/SIL/IR/SILPrinter.cpp

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3103,52 +3103,56 @@ void SILInstruction::printInContext(llvm::raw_ostream &OS) const {
31033103
SILPrinter(Ctx).printInContext(this);
31043104
}
31053105

3106+
void SILVTableEntry::print(llvm::raw_ostream &OS) const {
3107+
getMethod().print(OS);
3108+
OS << ": ";
3109+
3110+
PrintOptions QualifiedSILTypeOptions = PrintOptions::printQualifiedSILType();
3111+
bool HasSingleImplementation = false;
3112+
switch (getMethod().kind) {
3113+
default:
3114+
break;
3115+
case SILDeclRef::Kind::IVarDestroyer:
3116+
case SILDeclRef::Kind::Destroyer:
3117+
case SILDeclRef::Kind::Deallocator:
3118+
HasSingleImplementation = true;
3119+
}
3120+
// No need to emit the signature for methods that may have only
3121+
// single implementation, e.g. for destructors.
3122+
if (!HasSingleImplementation) {
3123+
QualifiedSILTypeOptions.CurrentModule =
3124+
getMethod().getDecl()->getDeclContext()->getParentModule();
3125+
getMethod().getDecl()->getInterfaceType().print(
3126+
OS, QualifiedSILTypeOptions);
3127+
OS << " : ";
3128+
}
3129+
OS << '@' << getImplementation()->getName();
3130+
switch (getKind()) {
3131+
case SILVTable::Entry::Kind::Normal:
3132+
break;
3133+
case SILVTable::Entry::Kind::Inherited:
3134+
OS << " [inherited]";
3135+
break;
3136+
case SILVTable::Entry::Kind::Override:
3137+
OS << " [override]";
3138+
break;
3139+
}
3140+
if (isNonOverridden()) {
3141+
OS << " [nonoverridden]";
3142+
}
3143+
3144+
OS << "\t// " << demangleSymbol(getImplementation()->getName());
3145+
}
3146+
31063147
void SILVTable::print(llvm::raw_ostream &OS, bool Verbose) const {
31073148
OS << "sil_vtable ";
31083149
if (isSerialized())
31093150
OS << "[serialized] ";
31103151
OS << getClass()->getName() << " {\n";
31113152

3112-
PrintOptions QualifiedSILTypeOptions = PrintOptions::printQualifiedSILType();
31133153
for (auto &entry : getEntries()) {
31143154
OS << " ";
3115-
entry.getMethod().print(OS);
3116-
OS << ": ";
3117-
3118-
bool HasSingleImplementation = false;
3119-
switch (entry.getMethod().kind) {
3120-
default:
3121-
break;
3122-
case SILDeclRef::Kind::IVarDestroyer:
3123-
case SILDeclRef::Kind::Destroyer:
3124-
case SILDeclRef::Kind::Deallocator:
3125-
HasSingleImplementation = true;
3126-
}
3127-
// No need to emit the signature for methods that may have only
3128-
// single implementation, e.g. for destructors.
3129-
if (!HasSingleImplementation) {
3130-
QualifiedSILTypeOptions.CurrentModule =
3131-
entry.getMethod().getDecl()->getDeclContext()->getParentModule();
3132-
entry.getMethod().getDecl()->getInterfaceType().print(
3133-
OS, QualifiedSILTypeOptions);
3134-
OS << " : ";
3135-
}
3136-
OS << '@' << entry.getImplementation()->getName();
3137-
switch (entry.getKind()) {
3138-
case SILVTable::Entry::Kind::Normal:
3139-
break;
3140-
case SILVTable::Entry::Kind::Inherited:
3141-
OS << " [inherited]";
3142-
break;
3143-
case SILVTable::Entry::Kind::Override:
3144-
OS << " [override]";
3145-
break;
3146-
}
3147-
if (entry.isNonOverridden()) {
3148-
OS << " [nonoverridden]";
3149-
}
3150-
3151-
OS << "\t// " << demangleSymbol(entry.getImplementation()->getName());
3155+
entry.print(OS);
31523156
OS << "\n";
31533157
}
31543158
OS << "}\n\n";

lib/SIL/IR/SILVTable.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ void SILVTable::removeFromVTableCache(Entry &entry) {
5555
M.VTableEntryCache.erase({this, entry.getMethod()});
5656
}
5757

58+
void SILVTable::updateVTableCache(const Entry &entry) {
59+
SILModule &M = entry.getImplementation()->getModule();
60+
M.VTableEntryCache[{this, entry.getMethod()}] = entry;
61+
}
62+
5863
SILVTable::SILVTable(ClassDecl *c, IsSerialized_t serialized,
5964
ArrayRef<Entry> entries)
6065
: Class(c), Serialized(serialized), NumEntries(entries.size()) {

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5381,6 +5381,10 @@ void SILVTable::verify(const SILModule &M) const {
53815381
for (unsigned i : indices(getEntries())) {
53825382
auto &entry = getEntries()[i];
53835383

5384+
// Make sure the module's lookup cache is consistent.
5385+
assert(entry == *getEntry(const_cast<SILModule &>(M), entry.getMethod())
5386+
&& "vtable entry is out of sync with method's vtable cache");
5387+
53845388
// All vtable entries must be decls in a class context.
53855389
assert(entry.getMethod().hasDecl() && "vtable entry is not a decl");
53865390
auto baseInfo = M.Types.getConstantInfo(TypeExpansionContext::minimal(),

0 commit comments

Comments
 (0)