Skip to content

Commit e0533e6

Browse files
committed
SIL: add an API to replace all entries of a VTable
* add `ModulePassContext.replaceVTableEntries()` * add `ModulePassContext.notifyFunctionTablesChanged()`
1 parent a9d5903 commit e0533e6

File tree

8 files changed

+61
-4
lines changed

8 files changed

+61
-4
lines changed

SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ struct ModulePassContext : Context, CustomStringConvertible {
168168
return VTable(bridged: bridgedVTable)
169169
}
170170

171+
func replaceVTableEntries(of vTable: VTable, with entries: [VTable.Entry]) {
172+
let bridgedEntries = entries.map { $0.bridged }
173+
bridgedEntries.withBridgedArrayRef {
174+
vTable.bridged.replaceEntries($0)
175+
}
176+
notifyFunctionTablesChanged()
177+
}
178+
171179
func createEmptyFunction(
172180
name: String,
173181
parameters: [ParameterInfo],
@@ -201,6 +209,10 @@ struct ModulePassContext : Context, CustomStringConvertible {
201209
}
202210
}
203211
}
212+
213+
func notifyFunctionTablesChanged() {
214+
_bridged.asNotificationHandler().notifyChanges(.functionTablesChanged)
215+
}
204216
}
205217

206218
extension GlobalVariable {

SwiftCompilerSources/Sources/SIL/VTable.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import AST
1414
import SILBridging
1515

1616
public struct VTable : CustomStringConvertible, NoReflectionChildren {
17-
let bridged: BridgedVTable
17+
public let bridged: BridgedVTable
1818

1919
public init(bridged: BridgedVTable) { self.bridged = bridged }
2020

include/swift/SIL/SILBridging.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,17 +1065,18 @@ struct BridgedVTableEntryArray {
10651065
};
10661066

10671067
struct BridgedVTable {
1068-
const swift::SILVTable * _Nonnull vTable;
1068+
swift::SILVTable * _Nonnull vTable;
10691069

10701070
BridgedOwnedString getDebugDescription() const;
10711071
BRIDGED_INLINE SwiftInt getNumEntries() const;
10721072
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedVTableEntry getEntry(SwiftInt index) const;
10731073
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDeclObj getClass() const;
10741074
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getSpecializedClassType() const;
1075+
BRIDGED_INLINE void replaceEntries(BridgedArrayRef bridgedEntries) const;
10751076
};
10761077

10771078
struct OptionalBridgedVTable {
1078-
const swift::SILVTable * _Nullable table;
1079+
swift::SILVTable * _Nullable table;
10791080
};
10801081

10811082
struct BridgedWitnessTableEntry {
@@ -1328,7 +1329,8 @@ struct BridgedChangeNotificationHandler {
13281329
instructionsChanged,
13291330
callsChanged,
13301331
branchesChanged,
1331-
effectsChanged
1332+
effectsChanged,
1333+
functionTablesChanged
13321334
};
13331335

13341336
void notifyChanges(Kind changeKind) const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,14 @@ BridgedType BridgedVTable::getSpecializedClassType() const {
17151715
return {vTable->getClassType()};
17161716
}
17171717

1718+
void BridgedVTable::replaceEntries(BridgedArrayRef bridgedEntries) const {
1719+
llvm::SmallVector<swift::SILVTableEntry, 8> entries;
1720+
for (const BridgedVTableEntry &e : bridgedEntries.unbridged<BridgedVTableEntry>()) {
1721+
entries.push_back(e.unbridged());
1722+
}
1723+
vTable->replaceEntries(entries);
1724+
}
1725+
17181726
//===----------------------------------------------------------------------===//
17191727
// BridgedWitnessTable, BridgedDefaultWitnessTable
17201728
//===----------------------------------------------------------------------===//

include/swift/SIL/SILVTable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ class SILVTable final : public SILAllocated<SILVTable>,
205205
NumEntries = std::distance(Entries.begin(), end);
206206
}
207207

208+
void replaceEntries(ArrayRef<Entry> newEntries);
209+
208210
/// Verify that the vtable is well-formed for the given class.
209211
void verify(const SILModule &M) const;
210212

include/swift/SILOptimizer/PassManager/PassManager.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class SwiftPassInvocation {
6969
SILAnalysis::InvalidationKind changeNotifications =
7070
SILAnalysis::InvalidationKind::Nothing;
7171

72+
bool functionTablesChanged = false;
73+
7274
/// All slabs, allocated by the pass.
7375
SILModule::SlabList allocatedSlabs;
7476

@@ -141,6 +143,8 @@ class SwiftPassInvocation {
141143
/// Called by the pass when changes are made to the SIL.
142144
void notifyChanges(SILAnalysis::InvalidationKind invalidationKind);
143145

146+
void notifyFunctionTablesChanged();
147+
144148
/// Called by the pass manager before the pass starts running.
145149
void startModulePassRun(SILModuleTransform *transform);
146150

@@ -513,6 +517,9 @@ notifyChanges(SILAnalysis::InvalidationKind invalidationKind) {
513517
changeNotifications = (SILAnalysis::InvalidationKind)
514518
(changeNotifications | invalidationKind);
515519
}
520+
inline void SwiftPassInvocation::notifyFunctionTablesChanged() {
521+
functionTablesChanged = true;
522+
}
516523

517524
} // end namespace swift
518525

lib/SIL/IR/SILVTable.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,22 @@ void SILVTable::updateVTableCache(const Entry &entry) {
7575
M.VTableEntryCache[{this, entry.getMethod()}] = entry;
7676
}
7777

78+
void SILVTable::replaceEntries(ArrayRef<Entry> newEntries) {
79+
auto entries = getMutableEntries();
80+
ASSERT(newEntries.size() <= entries.size());
81+
for (unsigned i = 0; i < entries.size(); ++i) {
82+
entries[i].getImplementation()->decrementRefCount();
83+
if (i < newEntries.size()) {
84+
entries[i] = newEntries[i];
85+
entries[i].getImplementation()->incrementRefCount();
86+
updateVTableCache(entries[i]);
87+
} else {
88+
removeFromVTableCache(entries[i]);
89+
}
90+
}
91+
NumEntries = newEntries.size();
92+
}
93+
7894
SILVTable::SILVTable(ClassDecl *c, SILType classType,
7995
SerializedKind_t serialized, ArrayRef<Entry> entries)
8096
: Class(c), classType(classType), SerializedKind(serialized),

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,6 +1516,7 @@ void SwiftPassInvocation::finishedModulePassRun() {
15161516
endPass();
15171517
assert(!function && transform && "not running a pass");
15181518
assert(changeNotifications == SILAnalysis::InvalidationKind::Nothing
1519+
&& !functionTablesChanged
15191520
&& "unhandled change notifications at end of module pass");
15201521
transform = nullptr;
15211522
}
@@ -1551,6 +1552,7 @@ void SwiftPassInvocation::endPass() {
15511552
void SwiftPassInvocation::beginTransformFunction(SILFunction *function) {
15521553
assert(!this->function && transform && "not running a pass");
15531554
assert(changeNotifications == SILAnalysis::InvalidationKind::Nothing
1555+
&& !functionTablesChanged
15541556
&& "change notifications not cleared");
15551557
this->function = function;
15561558
}
@@ -1561,6 +1563,10 @@ void SwiftPassInvocation::endTransformFunction() {
15611563
passManager->invalidateAnalysis(function, changeNotifications);
15621564
changeNotifications = SILAnalysis::InvalidationKind::Nothing;
15631565
}
1566+
if (functionTablesChanged) {
1567+
passManager->invalidateFunctionTables();
1568+
functionTablesChanged = false;
1569+
}
15641570
function = nullptr;
15651571
assert(numBlockSetsAllocated == 0 && "Not all BasicBlockSets deallocated");
15661572
assert(numNodeSetsAllocated == 0 && "Not all NodeSets deallocated");
@@ -1580,6 +1586,7 @@ void SwiftPassInvocation::endVerifyFunction() {
15801586
assert(function);
15811587
if (!transform) {
15821588
assert(changeNotifications == SILAnalysis::InvalidationKind::Nothing &&
1589+
!functionTablesChanged &&
15831590
"verifyication must not change the SIL of a function");
15841591
assert(numBlockSetsAllocated == 0 && "Not all BasicBlockSets deallocated");
15851592
assert(numNodeSetsAllocated == 0 && "Not all NodeSets deallocated");
@@ -1634,6 +1641,9 @@ void BridgedChangeNotificationHandler::notifyChanges(Kind changeKind) const {
16341641
case Kind::effectsChanged:
16351642
invocation->notifyChanges(SILAnalysis::InvalidationKind::Effects);
16361643
break;
1644+
case Kind::functionTablesChanged:
1645+
invocation->notifyFunctionTablesChanged();
1646+
break;
16371647
}
16381648
}
16391649

0 commit comments

Comments
 (0)