@@ -179,6 +179,37 @@ class LazyReexportsManager : public ResourceManager {
179179 lazyReexports (LazyReexportsManager &, SymbolAliasMap);
180180
181181public:
182+ struct CallThroughInfo {
183+ JITDylibSP JD;
184+ SymbolStringPtr Name;
185+ SymbolStringPtr BodyName;
186+ };
187+
188+ class Listener {
189+ public:
190+ using CallThroughInfo = LazyReexportsManager::CallThroughInfo;
191+
192+ virtual ~Listener ();
193+
194+ // / Called under the session lock when new lazy reexports are created.
195+ virtual void onLazyReexportsCreated (JITDylib &JD, ResourceKey K,
196+ const SymbolAliasMap &Reexports) = 0;
197+
198+ // / Called under the session lock when lazy reexports have their ownership
199+ // / transferred to a new ResourceKey.
200+ virtual void onLazyReexportsTransfered (JITDylib &JD, ResourceKey DstK,
201+ ResourceKey SrcK) = 0;
202+
203+ // / Called under the session lock when lazy reexports are removed.
204+ virtual Error onLazyReexportsRemoved (JITDylib &JD, ResourceKey K) = 0;
205+
206+ // / Called outside the session lock when a lazy reexport is called.
207+ // / NOTE: Since this is called outside the session lock there is a chance
208+ // / that the reexport referred to has already been removed. Listeners
209+ // / must be prepared to handle requests for stale reexports.
210+ virtual void onLazyReexportCalled (const CallThroughInfo &CTI) = 0;
211+ };
212+
182213 using OnTrampolinesReadyFn = unique_function<void (
183214 Expected<std::vector<ExecutorSymbolDef>> EntryAddrs)>;
184215 using EmitTrampolinesFn =
@@ -189,7 +220,7 @@ class LazyReexportsManager : public ResourceManager {
189220 // / This will work both in-process and out-of-process.
190221 static Expected<std::unique_ptr<LazyReexportsManager>>
191222 Create (EmitTrampolinesFn EmitTrampolines, RedirectableSymbolManager &RSMgr,
192- JITDylib &PlatformJD);
223+ JITDylib &PlatformJD, Listener *L = nullptr );
193224
194225 LazyReexportsManager (LazyReexportsManager &&) = delete ;
195226 LazyReexportsManager &operator =(LazyReexportsManager &&) = delete ;
@@ -199,12 +230,6 @@ class LazyReexportsManager : public ResourceManager {
199230 ResourceKey SrcK) override ;
200231
201232private:
202- struct CallThroughInfo {
203- SymbolStringPtr Name;
204- SymbolStringPtr BodyName;
205- JITDylibSP JD;
206- };
207-
208233 class MU ;
209234 class Plugin ;
210235
@@ -213,7 +238,7 @@ class LazyReexportsManager : public ResourceManager {
213238
214239 LazyReexportsManager (EmitTrampolinesFn EmitTrampolines,
215240 RedirectableSymbolManager &RSMgr, JITDylib &PlatformJD,
216- Error &Err);
241+ Listener *L, Error &Err);
217242
218243 std::unique_ptr<MaterializationUnit>
219244 createLazyReexports (SymbolAliasMap Reexports);
@@ -229,6 +254,7 @@ class LazyReexportsManager : public ResourceManager {
229254 ExecutionSession &ES;
230255 EmitTrampolinesFn EmitTrampolines;
231256 RedirectableSymbolManager &RSMgr;
257+ Listener *L;
232258
233259 DenseMap<ResourceKey, std::vector<ExecutorAddr>> KeyToReentryAddrs;
234260 DenseMap<ExecutorAddr, CallThroughInfo> CallThroughs;
@@ -242,6 +268,66 @@ lazyReexports(LazyReexportsManager &LRM, SymbolAliasMap Reexports) {
242268 return LRM.createLazyReexports (std::move (Reexports));
243269}
244270
271+ class SimpleLazyReexportsSpeculator : public LazyReexportsManager ::Listener {
272+ friend std::shared_ptr<SimpleLazyReexportsSpeculator> std::make_shared ();
273+
274+ public:
275+ using RecordExecutionFunction =
276+ unique_function<void (const CallThroughInfo &CTI)>;
277+
278+ static std::shared_ptr<SimpleLazyReexportsSpeculator>
279+ Create (ExecutionSession &ES, RecordExecutionFunction RecordExec = {}) {
280+ class make_shared_helper : public SimpleLazyReexportsSpeculator {
281+ public:
282+ make_shared_helper (ExecutionSession &ES,
283+ RecordExecutionFunction RecordExec)
284+ : SimpleLazyReexportsSpeculator(ES, std::move(RecordExec)) {}
285+ };
286+
287+ auto Instance =
288+ std::make_shared<make_shared_helper>(ES, std::move (RecordExec));
289+ Instance->WeakThis = Instance;
290+ return Instance;
291+ }
292+
293+ SimpleLazyReexportsSpeculator (SimpleLazyReexportsSpeculator &&) = delete ;
294+ SimpleLazyReexportsSpeculator &
295+ operator =(SimpleLazyReexportsSpeculator &&) = delete ;
296+ ~SimpleLazyReexportsSpeculator () override ;
297+
298+ void onLazyReexportsCreated (JITDylib &JD, ResourceKey K,
299+ const SymbolAliasMap &Reexports) override ;
300+
301+ void onLazyReexportsTransfered (JITDylib &JD, ResourceKey DstK,
302+ ResourceKey SrcK) override ;
303+
304+ Error onLazyReexportsRemoved (JITDylib &JD, ResourceKey K) override ;
305+
306+ void onLazyReexportCalled (const CallThroughInfo &CTI) override ;
307+
308+ void addSpeculationSuggestions (
309+ std::vector<std::pair<std::string, SymbolStringPtr>> NewSuggestions);
310+
311+ private:
312+ SimpleLazyReexportsSpeculator (ExecutionSession &ES,
313+ RecordExecutionFunction RecordExec)
314+ : ES(ES), RecordExec(std::move(RecordExec)) {}
315+
316+ bool doNextSpeculativeLookup ();
317+
318+ class SpeculateTask ;
319+
320+ using KeyToFunctionBodiesMap =
321+ DenseMap<ResourceKey, std::vector<SymbolStringPtr>>;
322+
323+ ExecutionSession &ES;
324+ RecordExecutionFunction RecordExec;
325+ std::weak_ptr<SimpleLazyReexportsSpeculator> WeakThis;
326+ DenseMap<JITDylib *, KeyToFunctionBodiesMap> LazyReexports;
327+ std::deque<std::pair<std::string, SymbolStringPtr>> SpeculateSuggestions;
328+ bool SpeculateTaskActive = false ;
329+ };
330+
245331} // End namespace orc
246332} // End namespace llvm
247333
0 commit comments