Skip to content

Commit d86ef3b

Browse files
committed
Add [serialized] flag to sil_vtables
1 parent 5047e1b commit d86ef3b

File tree

10 files changed

+52
-16
lines changed

10 files changed

+52
-16
lines changed

include/swift/SIL/SILVTable.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
namespace swift {
3333

3434
class ClassDecl;
35+
enum IsSerialized_t : unsigned char;
3536
class SILFunction;
3637
class SILModule;
3738

@@ -93,14 +94,18 @@ class SILVTable : public llvm::ilist_node<SILVTable>,
9394
/// The ClassDecl mapped to this VTable.
9495
ClassDecl *Class;
9596

97+
/// Whether or not this vtable is serialized, which allows
98+
/// devirtualization from another module.
99+
bool Serialized : 1;
100+
96101
/// The number of SILVTables entries.
97-
unsigned NumEntries;
102+
unsigned NumEntries : 31;
98103

99104
/// Tail-allocated SILVTable entries.
100105
Entry Entries[1];
101106

102107
/// Private constructor. Create SILVTables by calling SILVTable::create.
103-
SILVTable(ClassDecl *c, ArrayRef<Entry> entries);
108+
SILVTable(ClassDecl *c, IsSerialized_t serialized, ArrayRef<Entry> entries);
104109

105110
public:
106111
~SILVTable();
@@ -109,11 +114,15 @@ class SILVTable : public llvm::ilist_node<SILVTable>,
109114
/// The SILDeclRef keys should reference the most-overridden members available
110115
/// through the class.
111116
static SILVTable *create(SILModule &M, ClassDecl *Class,
117+
IsSerialized_t Serialized,
112118
ArrayRef<Entry> Entries);
113119

114120
/// Return the class that the vtable represents.
115121
ClassDecl *getClass() const { return Class; }
116122

123+
/// Returns true if this vtable is going to be (or was) serialized.
124+
IsSerialized_t isSerialized() const;
125+
117126
/// Return all of the method entries.
118127
ArrayRef<Entry> getEntries() const { return {Entries, NumEntries}; }
119128

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 371; // Last change: SILFunctionType.noescape
57+
const uint16_t VERSION_MINOR = 372; // Last change: VTable serialized
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;

lib/ParseSIL/ParseSIL.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5109,6 +5109,12 @@ bool SILParserTUState::parseSILVTable(Parser &P) {
51095109
P.consumeToken(tok::kw_sil_vtable);
51105110
SILParser VTableState(P);
51115111

5112+
IsSerialized_t Serialized = IsNotSerialized;
5113+
if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr,
5114+
nullptr, nullptr, nullptr, nullptr, nullptr,
5115+
nullptr, VTableState))
5116+
return true;
5117+
51125118
// Parse the class name.
51135119
Identifier Name;
51145120
SourceLoc Loc;
@@ -5196,7 +5202,7 @@ bool SILParserTUState::parseSILVTable(Parser &P) {
51965202
P.parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
51975203
LBraceLoc);
51985204

5199-
SILVTable::create(M, theClass, vtableEntries);
5205+
SILVTable::create(M, theClass, Serialized, vtableEntries);
52005206
return false;
52015207
}
52025208

lib/SIL/SILPrinter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2536,7 +2536,11 @@ void SILInstruction::printInContext(llvm::raw_ostream &OS) const {
25362536
}
25372537

25382538
void SILVTable::print(llvm::raw_ostream &OS, bool Verbose) const {
2539-
OS << "sil_vtable " << getClass()->getName() << " {\n";
2539+
OS << "sil_vtable ";
2540+
if (isSerialized())
2541+
OS << "[serialized] ";
2542+
OS << getClass()->getName() << " {\n";
2543+
25402544
PrintOptions QualifiedSILTypeOptions = PrintOptions::printQualifiedSILType();
25412545
for (auto &entry : getEntries()) {
25422546
OS << " ";

lib/SIL/SILVTable.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424
using namespace swift;
2525

2626
SILVTable *SILVTable::create(SILModule &M, ClassDecl *Class,
27+
IsSerialized_t Serialized,
2728
ArrayRef<Entry> Entries) {
2829
// SILVTable contains one element declared in Entries. We must allocate
2930
// space for it, because its default ctor will write to it.
3031
unsigned NumTailElements = std::max((unsigned)Entries.size(), 1U)-1;
3132
void *buf = M.allocate(sizeof(SILVTable) + sizeof(Entry) * NumTailElements,
3233
alignof(SILVTable));
33-
SILVTable *vt = ::new (buf) SILVTable(Class, Entries);
34+
SILVTable *vt = ::new (buf) SILVTable(Class, Serialized, Entries);
3435
M.vtables.push_back(vt);
3536
M.VTableMap[Class] = vt;
3637
// Update the Module's cache with new vtable + vtable entries:
@@ -57,9 +58,13 @@ void SILVTable::removeFromVTableCache(Entry &entry) {
5758
M.VTableEntryCache.erase({this, entry.Method});
5859
}
5960

60-
SILVTable::SILVTable(ClassDecl *c, ArrayRef<Entry> entries)
61-
: Class(c), NumEntries(entries.size())
62-
{
61+
IsSerialized_t SILVTable::isSerialized() const {
62+
return Serialized ? IsSerialized : IsNotSerialized;
63+
}
64+
65+
SILVTable::SILVTable(ClassDecl *c, IsSerialized_t serialized,
66+
ArrayRef<Entry> entries)
67+
: Class(c), Serialized(serialized), NumEntries(entries.size()) {
6368
memcpy(Entries, entries.begin(), sizeof(Entry) * NumEntries);
6469

6570
// Bump the reference count of functions referenced by this table.

lib/SIL/SILVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4438,7 +4438,7 @@ void SILVTable::verify(const SILModule &M) const {
44384438
assert(entry.Method.hasDecl() && "vtable entry is not a decl");
44394439
auto baseInfo = M.Types.getConstantInfo(entry.Method);
44404440
ValueDecl *decl = entry.Method.getDecl();
4441-
4441+
44424442
assert((!isa<FuncDecl>(decl)
44434443
|| !cast<FuncDecl>(decl)->isObservingAccessor())
44444444
&& "observing accessors shouldn't have vtable entries");

lib/SILGen/SILGenType.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,14 @@ class SILGenVTable : public SILVTableVisitor<SILGenVTable> {
226226
dtorFn->getLinkage()});
227227
}
228228

229+
IsSerialized_t serialized = IsNotSerialized;
230+
auto classIsPublic = theClass->getEffectiveAccess() >= AccessLevel::Public;
231+
// Only public, fixed-layout classes should be serialized.
232+
if (classIsPublic && theClass->hasFixedLayout())
233+
serialized = IsSerialized;
234+
229235
// Finally, create the vtable.
230-
SILVTable::create(SGM.M, theClass, vtableEntries);
236+
SILVTable::create(SGM.M, theClass, serialized, vtableEntries);
231237
}
232238

233239
void visitAncestor(ClassDecl *ancestor) {

lib/Serialization/DeserializeSIL.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2486,7 +2486,8 @@ SILVTable *SILDeserializer::readVTable(DeclID VId) {
24862486
(void)kind;
24872487

24882488
DeclID ClassID;
2489-
VTableLayout::readRecord(scratch, ClassID);
2489+
unsigned Serialized;
2490+
VTableLayout::readRecord(scratch, ClassID, Serialized);
24902491
if (ClassID == 0) {
24912492
DEBUG(llvm::dbgs() << "VTable classID is 0.\n");
24922493
return nullptr;
@@ -2539,7 +2540,10 @@ SILVTable *SILDeserializer::readVTable(DeclID VId) {
25392540
break;
25402541
kind = SILCursor.readRecord(entry.ID, scratch);
25412542
}
2542-
SILVTable *vT = SILVTable::create(SILMod, theClass, vtableEntries);
2543+
SILVTable *vT = SILVTable::create(
2544+
SILMod, theClass,
2545+
(Serialized) ? IsSerialized : IsNotSerialized,
2546+
vtableEntries);
25432547
vTableOrOffset = vT;
25442548

25452549
if (Callback) Callback->didDeserialize(MF->getAssociatedModule(), vT);

lib/Serialization/SILFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ namespace sil_block {
186186

187187
using VTableLayout = BCRecordLayout<
188188
SIL_VTABLE,
189-
DeclIDField // Class Decl
189+
DeclIDField, // Class Decl
190+
BCFixed<1> // IsSerialized.
190191
>;
191192

192193
using VTableEntryLayout = BCRecordLayout<

lib/Serialization/SerializeSIL.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2080,7 +2080,8 @@ void SILSerializer::writeSILVTable(const SILVTable &vt) {
20802080
VTableList[vt.getClass()->getName()] = NextVTableID++;
20812081
VTableOffset.push_back(Out.GetCurrentBitNo());
20822082
VTableLayout::emitRecord(Out, ScratchRecord, SILAbbrCodes[VTableLayout::Code],
2083-
S.addDeclRef(vt.getClass()));
2083+
S.addDeclRef(vt.getClass()),
2084+
vt.isSerialized() == IsSerialized ? 1 : 0);
20842085

20852086
for (auto &entry : vt.getEntries()) {
20862087
SmallVector<ValueID, 4> ListOfValues;
@@ -2287,7 +2288,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
22872288
const DeclContext *assocDC = SILMod->getAssociatedContext();
22882289
assert(assocDC && "cannot serialize SIL without an associated DeclContext");
22892290
for (const SILVTable &vt : SILMod->getVTables()) {
2290-
if ((ShouldSerializeAll || SILMod->getOptions().SILSerializeVTables) &&
2291+
if ((ShouldSerializeAll || vt.isSerialized()) &&
22912292
vt.getClass()->isChildContextOf(assocDC))
22922293
writeSILVTable(vt);
22932294
}

0 commit comments

Comments
 (0)