@@ -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,64 @@ lazyReexports(LazyReexportsManager &LRM, SymbolAliasMap Reexports) {
242268 return LRM.createLazyReexports (std::move (Reexports));
243269}
244270
271+ class SimpleLazyReexportsSpeculator : public LazyReexportsManager ::Listener {
272+ public:
273+ using RecordExecutionFunction =
274+ unique_function<void (const CallThroughInfo &CTI)>;
275+
276+ static std::shared_ptr<SimpleLazyReexportsSpeculator>
277+ Create (ExecutionSession &ES, RecordExecutionFunction RecordExec = {}) {
278+ class make_shared_helper : public SimpleLazyReexportsSpeculator {
279+ public:
280+ make_shared_helper (ExecutionSession &ES,
281+ RecordExecutionFunction RecordExec)
282+ : SimpleLazyReexportsSpeculator(ES, std::move(RecordExec)) {}
283+ };
284+
285+ auto Instance =
286+ std::make_shared<make_shared_helper>(ES, std::move (RecordExec));
287+ Instance->WeakThis = Instance;
288+ return Instance;
289+ }
290+
291+ SimpleLazyReexportsSpeculator (SimpleLazyReexportsSpeculator &&) = delete ;
292+ SimpleLazyReexportsSpeculator &
293+ operator =(SimpleLazyReexportsSpeculator &&) = delete ;
294+ ~SimpleLazyReexportsSpeculator () override ;
295+
296+ void onLazyReexportsCreated (JITDylib &JD, ResourceKey K,
297+ const SymbolAliasMap &Reexports) override ;
298+
299+ void onLazyReexportsTransfered (JITDylib &JD, ResourceKey DstK,
300+ ResourceKey SrcK) override ;
301+
302+ Error onLazyReexportsRemoved (JITDylib &JD, ResourceKey K) override ;
303+
304+ void onLazyReexportCalled (const CallThroughInfo &CTI) override ;
305+
306+ void addSpeculationSuggestions (
307+ std::vector<std::pair<std::string, SymbolStringPtr>> NewSuggestions);
308+
309+ private:
310+ SimpleLazyReexportsSpeculator (ExecutionSession &ES,
311+ RecordExecutionFunction RecordExec)
312+ : ES(ES), RecordExec(std::move(RecordExec)) {}
313+
314+ bool doNextSpeculativeLookup ();
315+
316+ class SpeculateTask ;
317+
318+ using KeyToFunctionBodiesMap =
319+ DenseMap<ResourceKey, std::vector<SymbolStringPtr>>;
320+
321+ ExecutionSession &ES;
322+ RecordExecutionFunction RecordExec;
323+ std::weak_ptr<SimpleLazyReexportsSpeculator> WeakThis;
324+ DenseMap<JITDylib *, KeyToFunctionBodiesMap> LazyReexports;
325+ std::deque<std::pair<std::string, SymbolStringPtr>> SpeculateSuggestions;
326+ bool SpeculateTaskActive = false ;
327+ };
328+
245329} // End namespace orc
246330} // End namespace llvm
247331
0 commit comments