Skip to content

Commit 9b036b2

Browse files
authored
Merge pull request swiftlang#18724 from gottesmm/pr-e32bbcf553e857952e63a87d9b9f24d9d991da98
[sil-optimizer] Centralize how we send out serialization notifications.
2 parents 428c580 + 872bf40 commit 9b036b2

File tree

10 files changed

+350
-103
lines changed

10 files changed

+350
-103
lines changed

include/swift/SIL/Notifications.h

Lines changed: 224 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,232 @@
1313
#ifndef SWIFT_SIL_NOTIFICATIONS_H
1414
#define SWIFT_SIL_NOTIFICATIONS_H
1515

16+
#include "swift/Basic/LLVM.h"
17+
#include "swift/Basic/STLExtras.h"
18+
#include "llvm/ADT/PointerUnion.h"
19+
#include "llvm/ADT/SmallVector.h"
20+
#include <memory>
21+
1622
namespace swift {
1723

1824
class SILNode;
25+
class ModuleDecl;
26+
class SILFunction;
27+
class SILWitnessTable;
28+
class SILDefaultWitnessTable;
29+
class SILGlobalVariable;
30+
class SILVTable;
31+
32+
/// An abstract class for handling SIL deserialization notifications.
33+
///
34+
/// This is an interface that should be implemented by clients that wish to
35+
/// maintain a list of notification handlers. In contrast, handler
36+
/// implementations should instead subclass DeserializationNotificationHandler
37+
/// so that default no-op implementations can be inherited and so that it can be
38+
/// passed into DeserializationNotificationHandlerSet.
39+
class DeserializationNotificationHandlerBase {
40+
public:
41+
/// Observe that we deserialized a function declaration.
42+
virtual void didDeserialize(ModuleDecl *mod, SILFunction *fn) = 0;
43+
44+
/// Observe that we successfully deserialized a function body.
45+
virtual void didDeserializeFunctionBody(ModuleDecl *mod, SILFunction *fn) = 0;
46+
47+
/// Observe that we successfully deserialized a witness table's entries.
48+
virtual void didDeserializeWitnessTableEntries(ModuleDecl *mod,
49+
SILWitnessTable *wt) = 0;
50+
51+
/// Observe that we successfully deserialized a default witness table's
52+
/// entries.
53+
virtual void
54+
didDeserializeDefaultWitnessTableEntries(ModuleDecl *mod,
55+
SILDefaultWitnessTable *wt) = 0;
56+
57+
/// Observe that we deserialized a global variable declaration.
58+
virtual void didDeserialize(ModuleDecl *mod, SILGlobalVariable *var) = 0;
59+
60+
/// Observe that we deserialized a v-table declaration.
61+
virtual void didDeserialize(ModuleDecl *mod, SILVTable *vtable) = 0;
62+
63+
/// Observe that we deserialized a witness-table declaration.
64+
virtual void didDeserialize(ModuleDecl *mod, SILWitnessTable *wtable) = 0;
65+
66+
/// Observe that we deserialized a default witness-table declaration.
67+
virtual void didDeserialize(ModuleDecl *mod,
68+
SILDefaultWitnessTable *wtable) = 0;
69+
70+
virtual ~DeserializationNotificationHandlerBase() = default;
71+
};
72+
73+
/// A no-op implementation of DeserializationNotificationHandlerBase. Intended
74+
/// to allow for users to implement only one of the relevant methods and have
75+
/// all other methods be no-ops.
76+
class DeserializationNotificationHandler
77+
: public DeserializationNotificationHandlerBase {
78+
public:
79+
/// Observe that we deserialized a function declaration.
80+
virtual void didDeserialize(ModuleDecl *mod, SILFunction *fn) override {}
81+
82+
/// Observe that we successfully deserialized a function body.
83+
virtual void didDeserializeFunctionBody(ModuleDecl *mod,
84+
SILFunction *fn) override {}
85+
86+
/// Observe that we successfully deserialized a witness table's entries.
87+
virtual void didDeserializeWitnessTableEntries(ModuleDecl *mod,
88+
SILWitnessTable *wt) override {
89+
}
90+
91+
/// Observe that we successfully deserialized a default witness table's
92+
/// entries.
93+
virtual void didDeserializeDefaultWitnessTableEntries(
94+
ModuleDecl *mod, SILDefaultWitnessTable *wt) override {}
95+
96+
/// Observe that we deserialized a global variable declaration.
97+
virtual void didDeserialize(ModuleDecl *mod,
98+
SILGlobalVariable *var) override {}
99+
100+
/// Observe that we deserialized a v-table declaration.
101+
virtual void didDeserialize(ModuleDecl *mod, SILVTable *vtable) override {}
102+
103+
/// Observe that we deserialized a witness-table declaration.
104+
virtual void didDeserialize(ModuleDecl *mod,
105+
SILWitnessTable *wtable) override {}
106+
107+
/// Observe that we deserialized a default witness-table declaration.
108+
virtual void didDeserialize(ModuleDecl *mod,
109+
SILDefaultWitnessTable *wtable) override {}
110+
111+
virtual StringRef getName() const = 0;
112+
113+
virtual ~DeserializationNotificationHandler() = default;
114+
};
115+
116+
/// A notification handler that only overrides didDeserializeFunctionBody and
117+
/// calls the passed in function pointer.
118+
class FunctionBodyDeserializationNotificationHandler final
119+
: public DeserializationNotificationHandler {
120+
public:
121+
using Handler = void (*)(ModuleDecl *, SILFunction *);
122+
123+
private:
124+
Handler handler;
125+
126+
public:
127+
FunctionBodyDeserializationNotificationHandler(Handler handler)
128+
: handler(handler) {}
129+
virtual ~FunctionBodyDeserializationNotificationHandler() {}
130+
131+
void didDeserializeFunctionBody(ModuleDecl *mod, SILFunction *fn) override {
132+
(*handler)(mod, fn);
133+
}
134+
135+
StringRef getName() const override {
136+
return "FunctionBodyDeserializationNotificationHandler";
137+
}
138+
};
139+
140+
/// A type that contains a set of unique DeserializationNotificationHandlers and
141+
/// implements DeserializationNotificationHandlerBase by iterating over the
142+
/// stored handlers and calling each handler's implementation.
143+
class DeserializationNotificationHandlerSet final
144+
: public DeserializationNotificationHandlerBase {
145+
public:
146+
using NotificationUniquePtr =
147+
std::unique_ptr<DeserializationNotificationHandler>;
148+
149+
private:
150+
/// A list of deserialization callbacks that update the SILModule and other
151+
/// parts of SIL as deserialization occurs.
152+
///
153+
/// We use 3 here since that is the most that will ever be used today in the
154+
/// compiler. If that changed, that number should be changed as well. The
155+
/// specific users are:
156+
///
157+
/// 1. SILModule's serialization callback.
158+
/// 2. SILPassManager notifications.
159+
/// 3. Access Enforcement Stripping notification.
160+
SmallVector<NotificationUniquePtr, 3> handlerSet;
161+
162+
public:
163+
DeserializationNotificationHandlerSet() = default;
164+
~DeserializationNotificationHandlerSet() = default;
165+
166+
bool erase(DeserializationNotificationHandler *handler) {
167+
auto iter = find_if(handlerSet, [&](const NotificationUniquePtr &h) {
168+
return handler == h.get();
169+
});
170+
if (iter == handlerSet.end())
171+
return false;
172+
handlerSet.erase(iter);
173+
return true;
174+
}
175+
176+
void add(NotificationUniquePtr &&handler) {
177+
// Since we store unique_ptrs and are accepting a movable rvalue here, we
178+
// should never have a case where we have a notification added twice. But
179+
// just to be careful, lets use an assert.
180+
assert(!count_if(handlerSet, [&](const NotificationUniquePtr &h) {
181+
return handler.get() == h.get();
182+
}) && "Two unique ptrs pointing at the same memory?!");
183+
handlerSet.emplace_back(std::move(handler));
184+
}
185+
186+
static DeserializationNotificationHandler *
187+
getUnderlyingHandler(const NotificationUniquePtr &h) {
188+
return h.get();
189+
}
190+
191+
/// An iterator into the notification set that returns a bare
192+
/// 'DeserializationNotificationHandler *' projected from one of the
193+
/// underlying std::unique_ptr<DeserializationNotificationHandler>.
194+
using iterator = llvm::mapped_iterator<
195+
decltype(handlerSet)::const_iterator,
196+
decltype(&DeserializationNotificationHandlerSet::getUnderlyingHandler)>;
197+
using range = llvm::iterator_range<iterator>;
198+
199+
/// Returns an iterator to the first element of the handler set.
200+
///
201+
/// NOTE: This iterator has a value_type of
202+
/// 'DeserializationNotificationHandler'.
203+
iterator begin() const {
204+
auto *fptr = &DeserializationNotificationHandlerSet::getUnderlyingHandler;
205+
return llvm::map_iterator(handlerSet.begin(), fptr);
206+
}
207+
208+
/// Returns an iterator to the end of the handler set.
209+
///
210+
/// NOTE: This iterator has a value_type of
211+
/// 'DeserializationNotificationHandler'.
212+
iterator end() const {
213+
auto *fptr = &DeserializationNotificationHandlerSet::getUnderlyingHandler;
214+
return llvm::map_iterator(handlerSet.end(), fptr);
215+
}
216+
217+
/// Returns a range that iterates over bare pointers projected from the
218+
/// internal owned memory pointers in the handlerSet.
219+
///
220+
/// NOTE: The underlying iterator value_type here is
221+
/// 'DeserializationNotificationHandler *'.
222+
auto getRange() const -> range { return llvm::make_range(begin(), end()); }
223+
224+
//===--------------------------------------------------------------------===//
225+
// DeserializationNotificationHandler implementation via chaining to the
226+
// handlers we contain.
227+
//===--------------------------------------------------------------------===//
228+
229+
void didDeserialize(ModuleDecl *mod, SILFunction *fn) override;
230+
void didDeserializeFunctionBody(ModuleDecl *mod, SILFunction *fn) override;
231+
void didDeserializeWitnessTableEntries(ModuleDecl *mod,
232+
SILWitnessTable *wt) override;
233+
void
234+
didDeserializeDefaultWitnessTableEntries(ModuleDecl *mod,
235+
SILDefaultWitnessTable *wt) override;
236+
void didDeserialize(ModuleDecl *mod, SILGlobalVariable *var) override;
237+
void didDeserialize(ModuleDecl *mod, SILVTable *vtable) override;
238+
void didDeserialize(ModuleDecl *mod, SILWitnessTable *wtable) override;
239+
void didDeserialize(ModuleDecl *mod,
240+
SILDefaultWitnessTable *wtable) override;
241+
};
19242

20243
/// A protocol (or interface) for handling value deletion notifications.
21244
///
@@ -24,7 +247,6 @@ class SILNode;
24247
/// analysis that need to invalidate data structures that contain pointers.
25248
/// This is similar to LLVM's ValueHandle.
26249
struct DeleteNotificationHandler {
27-
28250
DeleteNotificationHandler() { }
29251
virtual ~DeleteNotificationHandler() {}
30252

@@ -38,7 +260,6 @@ struct DeleteNotificationHandler {
38260
virtual bool needsNotifications() { return false; }
39261
};
40262

41-
} // end swift namespace
263+
} // namespace swift
42264

43265
#endif
44-

include/swift/SIL/SILModule.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,8 @@ class SILModule {
226226
/// The stage of processing this module is at.
227227
SILStage Stage;
228228

229-
/// The callback used by the SILLoader.
230-
std::unique_ptr<SerializationCallback> Callback;
231-
232-
// Callbacks registered by the SIL optimizer to run on each deserialized
233-
// function body. This is intentionally a stateless type because the
234-
// ModuleDecl and SILFunction should be sufficient context.
235-
using SILFunctionBodyCallback = void (*)(ModuleDecl *, SILFunction *F);
236-
SmallVector<SILFunctionBodyCallback, 0> DeserializationCallbacks;
229+
/// The set of deserialization notification handlers.
230+
DeserializationNotificationHandlerSet deserializationNotificationHandlers;
237231

238232
/// The SILLoader used when linking functions into this module.
239233
///
@@ -283,10 +277,19 @@ class SILModule {
283277
~SILModule();
284278

285279
/// Add a callback for each newly deserialized SIL function body.
286-
void registerDeserializationCallback(SILFunctionBodyCallback callBack);
280+
void registerDeserializationNotificationHandler(
281+
std::unique_ptr<DeserializationNotificationHandler> &&handler);
282+
283+
/// Return the set of registered deserialization callbacks.
284+
DeserializationNotificationHandlerSet::range
285+
getDeserializationHandlers() const {
286+
return deserializationNotificationHandlers.getRange();
287+
}
287288

288-
/// Return set of registered deserialization callbacks.
289-
ArrayRef<SILFunctionBodyCallback> getDeserializationCallbacks();
289+
void removeDeserializationNotificationHandler(
290+
DeserializationNotificationHandler *handler) {
291+
deserializationNotificationHandlers.erase(handler);
292+
}
290293

291294
/// Add a delete notification handler \p Handler to the module context.
292295
void registerDeleteNotificationHandler(DeleteNotificationHandler* Handler);

include/swift/Serialization/SerializedSILLoader.h

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "swift/AST/Decl.h"
1717
#include "swift/AST/Identifier.h"
18+
#include "swift/SIL/Notifications.h"
1819
#include "swift/SIL/SILDeclRef.h"
1920
#include "swift/SIL/SILLinkage.h"
2021
#include <memory>
@@ -36,56 +37,22 @@ class SILDefaultWitnessTable;
3637
/// in ASTContext. It provides lookupSILFunction that will perform lookup
3738
/// on each SILDeserializer.
3839
class SerializedSILLoader {
39-
public:
40-
class Callback {
41-
public:
42-
/// Observe that we deserialized a function declaration.
43-
virtual void didDeserialize(ModuleDecl *M, SILFunction *fn) {}
44-
45-
/// Observe that we successfully deserialized a function body.
46-
virtual void didDeserializeFunctionBody(ModuleDecl *M, SILFunction *fn) {}
47-
48-
/// Observe that we successfully deserialized a witness table's entries.
49-
virtual void didDeserializeWitnessTableEntries(ModuleDecl *M,
50-
SILWitnessTable *wt) {}
51-
52-
/// Observe that we successfully deserialized a default witness table's
53-
/// entries.
54-
virtual void didDeserializeDefaultWitnessTableEntries(ModuleDecl *M,
55-
SILDefaultWitnessTable *wt) {}
56-
57-
/// Observe that we deserialized a global variable declaration.
58-
virtual void didDeserialize(ModuleDecl *M, SILGlobalVariable *var) {}
59-
60-
/// Observe that we deserialized a v-table declaration.
61-
virtual void didDeserialize(ModuleDecl *M, SILVTable *vtable) {}
62-
63-
/// Observe that we deserialized a witness-table declaration.
64-
virtual void didDeserialize(ModuleDecl *M, SILWitnessTable *wtable) {}
65-
66-
/// Observe that we deserialized a default witness-table declaration.
67-
virtual void didDeserialize(ModuleDecl *M, SILDefaultWitnessTable *wtable) {}
68-
69-
virtual ~Callback() = default;
70-
private:
71-
virtual void _anchor();
72-
};
73-
7440
private:
75-
std::vector<std::unique_ptr<SILDeserializer> > LoadedSILSections;
41+
std::vector<std::unique_ptr<SILDeserializer>> LoadedSILSections;
7642

77-
explicit SerializedSILLoader(ASTContext &ctx, SILModule *SILMod,
78-
Callback *callback);
43+
explicit SerializedSILLoader(
44+
ASTContext &ctx, SILModule *SILMod,
45+
DeserializationNotificationHandlerSet *callbacks);
7946

8047
public:
8148
/// Create a new loader.
8249
///
83-
/// \param callback - not owned by the loader
84-
static std::unique_ptr<SerializedSILLoader> create(ASTContext &ctx,
85-
SILModule *SILMod,
86-
Callback *callback) {
50+
/// \param callbacks - not owned by the loader
51+
static std::unique_ptr<SerializedSILLoader>
52+
create(ASTContext &ctx, SILModule *SILMod,
53+
DeserializationNotificationHandlerSet *callbacks) {
8754
return std::unique_ptr<SerializedSILLoader>(
88-
new SerializedSILLoader(ctx, SILMod, callback));
55+
new SerializedSILLoader(ctx, SILMod, callbacks));
8956
}
9057
~SerializedSILLoader();
9158

lib/SIL/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_swift_library(swiftSIL STATIC
1010
Linker.cpp
1111
LinearLifetimeChecker.cpp
1212
LoopInfo.cpp
13+
Notifications.cpp
1314
OptimizationRemark.cpp
1415
PrettyStackTrace.cpp
1516
Projection.cpp

0 commit comments

Comments
 (0)