@@ -39,43 +39,54 @@ enum IsSerialized_t : unsigned char;
3939class SILFunction ;
4040class SILModule ;
4141
42+ // TODO: Entry should include substitutions needed to invoke an overridden
43+ // generic base class method.
44+ class SILVTableEntry {
45+ // / The declaration reference to the least-derived method visible through
46+ // / the class.
47+ SILDeclRef Method;
48+
49+ // / The function which implements the method for the class and the entry kind.
50+ llvm::PointerIntPair<SILFunction *, 2 , unsigned > ImplAndKind;
51+
52+ public:
53+ enum Kind : uint8_t {
54+ // / The vtable entry is for a method defined directly in this class.
55+ Normal,
56+ // / The vtable entry is for a method defined directly in this class, and is
57+ // / never overridden by subclasses.
58+ NormalNonOverridden,
59+ // / The vtable entry is inherited from the superclass.
60+ Inherited,
61+ // / The vtable entry is inherited from the superclass, and overridden
62+ // / in this class.
63+ Override,
64+
65+ // Please update the PointerIntPair above if you add/remove enums.
66+ };
67+
68+ SILVTableEntry () : ImplAndKind(nullptr , Kind::Normal) {}
69+
70+ SILVTableEntry (SILDeclRef Method, SILFunction *Implementation, Kind TheKind)
71+ : Method(Method), ImplAndKind(Implementation, TheKind) {}
72+
73+ SILDeclRef getMethod () const { return Method; }
74+
75+ Kind getKind () const { return Kind (ImplAndKind.getInt ()); }
76+ void setKind (Kind kind) { ImplAndKind.setInt (kind); }
77+
78+ SILFunction *getImplementation () const { return ImplAndKind.getPointer (); }
79+ };
80+
4281// / A mapping from each dynamically-dispatchable method of a class to the
4382// / SILFunction that implements the method for that class.
4483// / Note that dead methods are completely removed from the vtable.
45- class SILVTable : public SILAllocated <SILVTable> {
84+ class SILVTable final : public SILAllocated<SILVTable>,
85+ llvm::TrailingObjects<SILVTable, SILVTableEntry> {
86+ friend TrailingObjects;
87+
4688public:
47- // TODO: Entry should include substitutions needed to invoke an overridden
48- // generic base class method.
49- struct Entry {
50- enum Kind : uint8_t {
51- // / The vtable entry is for a method defined directly in this class.
52- Normal,
53- // / The vtable entry is for a method defined directly in this class, and is never overridden
54- // / by subclasses.
55- NormalNonOverridden,
56- // / The vtable entry is inherited from the superclass.
57- Inherited,
58- // / The vtable entry is inherited from the superclass, and overridden
59- // / in this class.
60- Override,
61- };
62-
63- Entry ()
64- : Implementation(nullptr ), TheKind(Kind::Normal) { }
65-
66- Entry (SILDeclRef Method, SILFunction *Implementation, Kind TheKind)
67- : Method(Method), Implementation(Implementation), TheKind(TheKind) { }
68-
69- // / The declaration reference to the least-derived method visible through
70- // / the class.
71- SILDeclRef Method;
72-
73- // / The function which implements the method for the class.
74- SILFunction *Implementation;
75-
76- // / The entry kind.
77- Kind TheKind;
78- };
89+ using Entry = SILVTableEntry;
7990
8091 // Disallow copying into temporary objects.
8192 SILVTable (const SILVTable &other) = delete ;
@@ -92,9 +103,6 @@ class SILVTable : public SILAllocated<SILVTable> {
92103 // / The number of SILVTables entries.
93104 unsigned NumEntries : 31 ;
94105
95- // / Tail-allocated SILVTable entries.
96- Entry Entries[1 ];
97-
98106 // / Private constructor. Create SILVTables by calling SILVTable::create.
99107 SILVTable (ClassDecl *c, IsSerialized_t serialized, ArrayRef<Entry> entries);
100108
@@ -123,29 +131,34 @@ class SILVTable : public SILAllocated<SILVTable> {
123131 }
124132
125133 // / Return all of the method entries.
126- ArrayRef<Entry> getEntries () const { return {Entries, NumEntries}; }
134+ ArrayRef<Entry> getEntries () const {
135+ return {getTrailingObjects<SILVTableEntry>(), NumEntries};
136+ }
127137
128138 // / Return all of the method entries mutably.
129- MutableArrayRef<Entry> getMutableEntries () { return {Entries, NumEntries}; }
139+ MutableArrayRef<Entry> getMutableEntries () {
140+ return {getTrailingObjects<SILVTableEntry>(), NumEntries};
141+ }
130142
131143 // / Look up the implementation function for the given method.
132144 Optional<Entry> getEntry (SILModule &M, SILDeclRef method) const ;
133145
134146 // / Removes entries from the vtable.
135147 // / \p predicate Returns true if the passed entry should be removed.
136148 template <typename Predicate> void removeEntries_if (Predicate predicate) {
137- Entry *end = std::remove_if (Entries, Entries + NumEntries,
138- [&](Entry &entry) -> bool {
139- if (predicate (entry)) {
140- entry.Implementation ->decrementRefCount ();
141- removeFromVTableCache (entry);
142- return true ;
143- }
144- return false ;
145- });
146- NumEntries = end - Entries;
149+ auto Entries = getMutableEntries ();
150+ Entry *end = std::remove_if (
151+ Entries.begin (), Entries.end (), [&](Entry &entry) -> bool {
152+ if (predicate (entry)) {
153+ entry.getImplementation ()->decrementRefCount ();
154+ removeFromVTableCache (entry);
155+ return true ;
156+ }
157+ return false ;
158+ });
159+ NumEntries = std::distance (Entries.begin (), end);
147160 }
148-
161+
149162 // / Verify that the vtable is well-formed for the given class.
150163 void verify (const SILModule &M) const ;
151164
0 commit comments